lib/specinfra/command/base.rb in specinfra-2.0.0.beta6 vs lib/specinfra/command/base.rb in specinfra-2.0.0.beta7
- old
+ new
@@ -1,354 +1,94 @@
require 'shellwords'
+class Specinfra::Command::Base
+ attr_accessor :types
-module Specinfra
- module Command
- class Base
- class NotImplementedError < Exception; end
+ class NotImplementedError < Exception; end
- def escape(target)
- str = case target
- when Regexp
- target.source
- else
- target.to_s
- end
+ def self.create
+ self.new
+ end
- Shellwords.shellescape(str)
- end
+ def escape(target)
+ str = case target
+ when Regexp
+ target.source
+ else
+ target.to_s
+ end
- def check_enabled(service, level=3)
- raise NotImplementedError.new
- end
+ Shellwords.shellescape(str)
+ end
- def check_yumrepo(repository)
- raise NotImplementedError.new
- end
+ def method_missing(meth, *args)
+ action, resource_type, subaction = breakdown(meth)
+ method = action
+ method += "_#{subaction}" if subaction
+ command_object = command_class(resource_type).create
+ if command_object.respond_to?(method)
+ command_object.send(method, *args)
+ else
+ raise NotImplementedError.new("#{method} is not implemented in #{command_class(resource_type)}")
+ end
+ end
- def check_yumrepo_enabled(repository)
- raise NotImplementedError.new
- end
+ def command_class(resource_type)
+ family = os[:family]
+ version = os[:release] ? "V#{os[:release].to_i}" : nil
- def check_mounted(path)
- regexp = "on #{path}"
- "mount | grep -w -- #{escape(regexp)}"
- end
+ common_class = self.class.const_get('Specinfra').const_get('Command')
+ base_class = common_class.const_get('Base')
+ os_class = family.nil? ? base_class : common_class.const_get(family.capitalize)
- def check_routing_table(destination)
- "ip route | grep -E '^#{destination} |^default '"
+ if family && version
+ begin
+ version_class = os_class.const_get(version)
+ rescue
+ version_class = os_class.const_get('Base')
end
+ elsif family.nil?
+ version_class = os_class
+ elsif family != 'base' && version.nil?
+ version_class = os_class.const_get('Base')
+ end
- def check_reachable(host, port, proto, timeout)
- if port.nil?
- "ping -w #{escape(timeout)} -c 2 -n #{escape(host)}"
- else
- "nc -vvvvz#{escape(proto[0].chr)} #{escape(host)} #{escape(port)} -w #{escape(timeout)}"
- end
- end
+ begin
+ command_klass = version_class.const_get(resource_type.to_camel_case)
+ rescue
+ end
- def check_resolvable(name, type)
- if type == "dns"
- "nslookup -timeout=1 #{escape(name)}"
- elsif type == "hosts"
- "grep -w -- #{escape(name)} /etc/hosts"
- else
- "getent hosts #{escape(name)}"
- end
- end
+ if command_klass.nil? ||( (command_klass < Specinfra::Command::Base).nil? && (command_klass < Specinfra::Command::Windows::Base).nil? )
+ command_klass = base_class.const_get(resource_type.to_camel_case)
+ end
- def check_file(file)
- "test -f #{escape(file)}"
- end
+ command_klass
+ end
- def get_file_mtime(file)
- "stat -c %Y #{escape(file)}"
- end
+ private
+ def breakdown(meth)
+ types = resource_types.map {|t| t.to_snake_case }.join('|')
+ md = meth.to_s.match(/^([^_]+)_(#{types})_?(.+)?$/)
+ if md.nil?
+ message = "Could not break down `#{meth}' to appropriate type and method.\n"
+ message += "The method name shoud be in the form of `action_type_subaction'."
+ raise message
+ end
+ return md[1], md[2], md[3]
+ end
- def get_file_size(file)
- "stat -c %s #{escape(file)}"
+ def resource_types
+ if @types.nil?
+ @types = []
+ Specinfra::Command::Base.subclasses.each do |s|
+ @types << s.to_s.split(':')[-1]
end
-
- def check_socket(file)
- "test -S #{escape(file)}"
+ Specinfra::Command::Windows::Base.subclasses.each do |s|
+ @types << s.to_s.split(':')[-1]
end
-
- def check_directory(directory)
- "test -d #{escape(directory)}"
- end
-
- def check_user(user)
- "id #{escape(user)}"
- end
-
- def check_group(group)
- "getent group #{escape(group)}"
- end
-
- def check_installed(package, version=nil)
- raise NotImplementedError.new
- end
-
- def check_service_installed(service)
- raise NotImplementedError.new
- end
-
- def check_service_start_mode(service, mode)
- raise NotImplementedError.new
- end
-
- def check_listening(port, options = {})
- pattern = ":#{port}"
- pattern = " #{options[:local_address]}#{pattern}" if options[:local_address]
- pattern = "^#{options[:protocol]} .*#{pattern}" if options[:protocol]
- "netstat -tunl | grep -- #{escape(pattern)}"
- end
-
- def check_listening_with_protocol(port, protocol)
- check_listening port, {:protocol => protocol}
- end
-
- def check_running(service)
- "service #{escape(service)} status"
- end
-
- def check_running_under_supervisor(service)
- "supervisorctl status #{escape(service)} | grep RUNNING"
- end
-
- def check_running_under_upstart(service)
- "initctl status #{escape(service)} | grep running"
- end
-
- def check_monitored_by_monit(service)
- "monit status"
- end
-
- def check_monitored_by_god(service)
- "god status #{escape(service)}"
- end
-
- def check_process(process)
- "ps aux | grep -w -- #{escape(process)} | grep -qv grep"
- end
-
- def check_process_count(process,count)
- "test $(ps aux | grep -w -- #{escape(process)} | grep -v grep | wc -l) -eq #{escape(count)}"
- end
-
- def get_process(process, opts)
- "ps -C #{escape(process)} -o #{opts[:format]} | head -1"
- end
-
- def check_file_contain(file, expected_pattern)
- "#{check_file_contain_with_regexp(file, expected_pattern)} || #{check_file_contain_with_fixed_strings(file, expected_pattern)}"
- end
-
- def check_file_contain_with_regexp(file, expected_pattern)
- "grep -q -- #{escape(expected_pattern)} #{escape(file)}"
- end
-
- def check_file_contain_with_fixed_strings(file, expected_pattern)
- "grep -qF -- #{escape(expected_pattern)} #{escape(file)}"
- end
-
- def check_file_checksum(file, expected)
- regexp = "^#{expected}"
- "cksum #{escape(file)} | grep -iw -- #{escape(regexp)}"
- end
-
- def check_file_md5checksum(file, expected)
- regexp = "^#{expected}"
- "md5sum #{escape(file)} | grep -iw -- #{escape(regexp)}"
- end
-
- def check_file_sha256checksum(file, expected)
- regexp = "^#{expected}"
- "sha256sum #{escape(file)} | grep -iw -- #{escape(regexp)}"
- end
-
- def check_file_contain_within(file, expected_pattern, from=nil, to=nil)
- from ||= '1'
- to ||= '$'
- sed = "sed -n #{escape(from)},#{escape(to)}p #{escape(file)}"
- checker_with_regexp = check_file_contain_with_regexp("-", expected_pattern)
- checker_with_fixed = check_file_contain_with_fixed_strings("-", expected_pattern)
- "#{sed} | #{checker_with_regexp} || #{sed} | #{checker_with_fixed}"
- end
-
- def check_file_contain_lines(file, expected_lines, from=nil, to=nil)
- require 'digest/md5'
- from ||= '1'
- to ||= '$'
- sed = "sed -n #{escape(from)},#{escape(to)}p #{escape(file)}"
- head_line = expected_lines.first.chomp
- lines_checksum = Digest::MD5.hexdigest(expected_lines.map(&:chomp).join("\n") + "\n")
- afterwards_length = expected_lines.length - 1
- "#{sed} | grep -A #{escape(afterwards_length)} -F -- #{escape(head_line)} | md5sum | grep -qiw -- #{escape(lines_checksum)}"
- end
-
- def check_mode(file, mode)
- regexp = "^#{mode}$"
- "stat -c %a #{escape(file)} | grep -- #{escape(regexp)}"
- end
-
- def check_owner(file, owner)
- regexp = "^#{owner}$"
- "stat -c %U #{escape(file)} | grep -- #{escape(regexp)}"
- end
-
- def check_grouped(file, group)
- regexp = "^#{group}$"
- "stat -c %G #{escape(file)} | grep -- #{escape(regexp)}"
- end
-
- def check_cron_entry(user, entry)
- entry_escaped = entry.gsub(/\*/, '\\*').gsub(/\[/, '\\[').gsub(/\]/, '\\]')
- if user.nil?
- "crontab -l | grep -v \"#\" -- | grep -- #{escape(entry_escaped)}"
- else
- "crontab -u #{escape(user)} -l | grep -v \"#\" | grep -- #{escape(entry_escaped)}"
- end
- end
-
- def check_link(link, target)
- "stat -c %N #{escape(link)} | egrep -e \"-> .#{escape(target)}.\""
- end
-
- def check_installed_by_gem(name, version=nil)
- regexp = "^#{name}"
- cmd = "gem list --local | grep -w -- #{escape(regexp)}"
- cmd = "#{cmd} | grep -w -- #{escape(version)}" if version
- cmd
- end
-
- def check_installed_by_npm(name, version=nil)
- cmd = "npm ls #{escape(name)} -g"
- cmd = "#{cmd} | grep -w -- #{escape(version)}" if version
- cmd
- end
-
- def check_installed_by_pecl(name, version=nil)
- regexp = "^#{name}"
- cmd = "pecl list | grep -w -- #{escape(regexp)}"
- cmd = "#{cmd} | grep -w -- #{escape(version)}" if version
- cmd
- end
-
- def check_installed_by_pear(name, version=nil)
- regexp = "^#{name}"
- cmd = "pear list | grep -w -- #{escape(regexp)}"
- cmd = "#{cmd} | grep -w -- #{escape(version)}" if version
- cmd
- end
-
- def check_installed_by_pip(name, version=nil)
- regexp = "^#{name}"
- cmd = "pip list | grep -w -- #{escape(regexp)}"
- cmd = "#{cmd} | grep -w -- #{escape(version)}" if version
- cmd
- end
-
- def check_installed_by_cpan(name, version=nil)
- regexp = "^#{name}"
- cmd = "cpan -l | grep -w -- #{escape(regexp)}"
- cmd = "#{cmd} | grep -w -- #{escape(version)}" if version
- cmd
- end
-
- def check_belonging_group(user, group)
- "id #{escape(user)} | awk '{print $3}' | grep -- #{escape(group)}"
- end
-
- def check_gid(group, gid)
- regexp = "^#{group}"
- "getent group | grep -w -- #{escape(regexp)} | cut -f 3 -d ':' | grep -w -- #{escape(gid)}"
- end
-
- def check_uid(user, uid)
- regexp = "^uid=#{uid}("
- "id #{escape(user)} | grep -- #{escape(regexp)}"
- end
-
- def check_login_shell(user, path_to_shell)
- "getent passwd #{escape(user)} | cut -f 7 -d ':' | grep -w -- #{escape(path_to_shell)}"
- end
-
- def check_home_directory(user, path_to_home)
- "getent passwd #{escape(user)} | cut -f 6 -d ':' | grep -w -- #{escape(path_to_home)}"
- end
-
- def check_authorized_key(user, key)
- key.sub!(/\s+\S*$/, '') if key.match(/^\S+\s+\S+\s+\S*$/)
- "grep -w -- #{escape(key)} ~#{escape(user)}/.ssh/authorized_keys"
- end
-
- def check_iptables_rule(rule, table=nil, chain=nil)
- raise NotImplementedError.new
- end
-
- def check_zfs(zfs, property=nil, value=nil)
- raise NotImplementedError.new
- end
-
- def get_mode(file)
- "stat -c %a #{escape(file)}"
- end
-
- def check_ipfilter_rule(rule)
- raise NotImplementedError.new
- end
-
- def check_ipnat_rule(rule)
- raise NotImplementedError.new
- end
-
- def check_svcprop(svc, property, value)
- raise NotImplementedError.new
- end
-
- def check_svcprops(svc, property)
- raise NotImplementedError.new
- end
-
- def check_selinux(mode)
- raise NotImplementedError.new
- end
-
- def check_access_by_user(file, user, access)
- raise NotImplementedError.new
- end
-
- def check_kernel_module_loaded(name)
- raise NotImplementedError.new
- end
-
- def check_ipv4_address(interface, ip_address)
- raise NotImplementedError.new
- end
-
- def check_mail_alias(recipient, target)
- target = "[[:space:]]#{target}"
- "getent aliases #{escape(recipient)} | grep -- #{escape(target)}$"
- end
-
- def get_file_content(file)
- "cat #{file} 2> /dev/null || echo -n"
- end
-
- def check_container(container)
- raise NotImplementedError.new
- end
-
- def check_cotainer_running(container)
- raise NotImplementedError.new
- end
-
- def get_package_version(package, opts=nil)
- raise NotImplementedError.new
- end
-
- def get_ipaddress_of_host(name)
- "getent hosts #{escape(name)} | awk '{print $1}'"
- end
+ @types.uniq!
end
+ @types
end
end
+
+
+