Skip to content

Instantly share code, notes, and snippets.

@skord
Last active November 18, 2016 18:07
Show Gist options
  • Save skord/34d2911079074caac682e18612683d79 to your computer and use it in GitHub Desktop.
Save skord/34d2911079074caac682e18612683d79 to your computer and use it in GitHub Desktop.
class Server
include ActiveModel::Model
extend ActiveModel::Naming
include ActiveModel::Validations
attr_accessor :id, :name, :server, :status, :protocol, :port,
:server_version, :node_id, :master_id, :slave_ids,
:repl_depth, :number_of_connections, :current_no_of_conns,
:current_no_of_operations, :errors
validates :server, presence: true, format: {with: /\A[A-Za-z0-9\.]{1,}\z/}
validates :name, presence: true, format: {with: /\A[A-Za-z0-9\.]{1,}\z/}
validates :port, presence: true, numericality: {integer: true, greater_than_or_equal_to: 1024, less_than_or_equal_to: 65535}
def initialize(attributes={})
super
@name = normalize_name(attributes[:name])
@id = normalize_name(attributes[:id])
@errors = ActiveModel::Errors.new(self)
end
def self.all
MaxAdmin::ShowLoader.new.objects_for(/Server/,Server)
end
def self.find(id)
self.all.select {|x| x.id == id}.first
end
def self.find_by_name(name)
self.all.select {|x| x.name == name}.first
end
def self.where(query_hash)
result = []
sets = query_hash.collect {|k,v| self.all.select {|x| x.send(k.to_s) == v}}
sets.inject(:&)
end
def persisted?
id.present?
end
def save
cmd = IO.popen("maxadmin create server #{@name} #{@server} #{@port}").read
if cmd =~ /already exists/
@errors.add(:base, "server already exists")
return false
elsif cmd =~ /Created server/
return true
end
end
private
def normalize_name(name)
if name.present? && name.match(/\AServer [[:alnum:]]{1,} \(.*\)\z/)
return name.scan(/\AServer [[:alnum:]]{1,} \((.*)\)\z/).flatten.first
else
return name
end
end
end
module MaxAdmin
class ShowLoader
include MaxAdmin::Command
def objects_for(regex, klass)
parsed = MaxAdmin::Parser.new.parse(show_all(klass))
tree= MaxAdmin::Transform.new.apply(parsed)
pruned_tree = tree.select {|x| x.keys.any? {|k| k =~ regex}}
values = pruned_tree.collect {|x| x.values[0].reduce({}, :merge)
.transform_keys {|key| key.to_s.parameterize.underscore.to_sym}
.merge({:name => x.keys[0], :id => x.keys[0]})}
values.collect {|val| klass.new(val)}
end
end
end
module MaxAdmin
class Parser < Parslet::Parser
root(:document)
rule(:document) { root.repeat.as(:root) }
rule(:root) {(
(match["[:alnum:][:punct:] "].repeat.as(:root) >> newline) >>
items.repeat.as(:items)
).repeat
}
rule(:items) {(list | key_value)}
rule(:list) {
tab.repeat(1) >> alnumspace.repeat.as(:list) >> str(":\n") >>
listitems.repeat.as(:values)
}
rule(:key_value) {
tab.repeat(1) >> key.repeat.as(:key) >> str(":") >>
tabspace.repeat >> value.repeat.as(:value) >> newline
}
rule(:listitems) {(tab.repeat(2) >> value.repeat.as(:value) >> newline)}
rule(:key) {match["0-9A-Za-z \."]}
rule(:value) {match["[0-9A-Za-z], [:punct:]"]}
rule(:space) {match[" "]}
rule(:tabspace) {match["\t "]}
rule(:newline) { str("\r").maybe >> str("\n") | str("\r") >> str("\n").maybe }
rule(:tab) {match["\t"]}
rule(:alnumspace) {match["[0-9A-Za-z] "]}
rule(:alnum) {match["[0-9A-Za-z]"]}
end
end
module MaxAdmin
class Transform < Parslet::Transform
rule(:root => simple(:r), :items => subtree(:i)) {
{"#{r}" => i }
}
rule(:key => simple(:k), :value => simple(:v)) {
{"#{k}" => v.to_s}
}
rule(:list => simple(:l), :values => subtree(:v)) {
{"#{l}" => v.collect {|x| x[:value].to_s}}
}
rule(:key => simple(:k), :value => sequence(:v)) {
{"#{k}" => v}
}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment