apocalypse-client 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour -f progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in apocalypse-reporter.gemspec
4
+ gemspec
@@ -0,0 +1,82 @@
1
+ # Apocalypse Client
2
+
3
+ Apocalypse Client is a ruby gem that can be installed on a remote
4
+ server.
5
+
6
+ ## Installation
7
+
8
+ Apocalypse Client currently focusses on Debian/Ubuntu systems only.
9
+
10
+ There is only one dependency to the operating system, namely the
11
+ `sysstat` package. This package is used to gather information about disk
12
+ utilisation and performance.
13
+
14
+ sudo apt-get install sysstat
15
+
16
+ Next install the ruby gem.
17
+
18
+ sudo gem install apocalypse-client
19
+
20
+ Now you can create the file `/etc/cron.d/apocalypse` with the following
21
+ content:
22
+
23
+ * * * * * root PATH=$PATH:/sbin:/usr/sbin /usr/bin/env apocalypse-client report --server SERVER --port PORT --hostid HOSTID > /dev/null
24
+
25
+ This will send metrics data every minute to your Apocalypse server. If
26
+ you require different intervals, refer to `man 5 crontab` for details on
27
+ how to schedule reporting.
28
+
29
+ You need to replace the placeholders with actual data:
30
+
31
+ * `SERVER` - The ip or hostname for your Apocalypse server. E.g.
32
+ apocalyse.example.org
33
+ * `PORT` - The port number the Apocalypse server is listening on.
34
+ Default: 80
35
+ * `HOSTID` - An ID identifying this server. You are free to choose
36
+ whatever you want. But be careful not to chose a duplicate hostid,
37
+ because it will mess up you statistics.
38
+
39
+ If an error occurs cron will try to notify you by email. This depends on
40
+ how your systems cron is configured.
41
+
42
+ ## Choosing a proper hostid
43
+
44
+ Choosing a proper hostid is important, because it can be arbitrarily
45
+ chosen. There are several options:
46
+
47
+ * Use the format `appname-role-number`. E.g. `ariejannet-db-01` or
48
+ `reddis-memcached-42`.
49
+ * IP Address of the server, this guarantees some level of uniqueness
50
+
51
+ Note: at this time, there is not convention for picking hostids.
52
+ However, the first method is likely to become the convention and will
53
+ allow logical grouping of servers by role and application.
54
+
55
+ ## Authors
56
+
57
+ * Ariejan de Vroom <ariejan@ariejan.net>
58
+ * Kabisa ICT - http://kabisa.nl
59
+
60
+ ## License
61
+
62
+ Copyright (c) 2011 Ariejan de Vroom
63
+
64
+ Permission is hereby granted, free of charge, to any person obtaining
65
+ a copy of this software and associated documentation files (the
66
+ "Software"), to deal in the Software without restriction, including
67
+ without limitation the rights to use, copy, modify, merge, publish,
68
+ distribute, sublicense, and/or sell copies of the Software, and to
69
+ permit persons to whom the Software is furnished to do so, subject to
70
+ the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be
73
+ included in all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
76
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
77
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
78
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
79
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
80
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
81
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
82
+
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ task :default => :spec
4
+
5
+ desc "Run all specs"
6
+ task "spec" do
7
+ exec "bundle exec rspec spec"
8
+ end
9
+
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "apocalypse-client/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "apocalypse-client"
7
+ s.version = Apocalypse::Client::VERSION
8
+ s.authors = ["Ariejan de Vroom"]
9
+ s.email = ["ariejan@ariejan.net"]
10
+ s.homepage = ""
11
+ s.summary = %q{Watch out for the apocalypse}
12
+ s.description = %q{Server monitoring made easy}
13
+
14
+ s.rubyforge_project = "apocalypse-client"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency("json", ["~> 1.5.3"])
22
+ s.add_dependency("trollop", ["~> 1.16.2"])
23
+
24
+ s.add_development_dependency("rspec", ["~> 2.6.0"])
25
+ end
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+
6
+ require "apocalypse-client"
7
+ require 'trollop'
8
+
9
+ SUB_COMMANDS = %w(report install check)
10
+
11
+ global_opts = Trollop::options do
12
+ banner "Apocalypse Reporter"
13
+ stop_on SUB_COMMANDS
14
+ end
15
+
16
+ cmd = ARGV.shift
17
+ cmd_opts = case cmd
18
+ when "report"
19
+ Trollop::options do
20
+ opt :server, "Hostname of the Apocalypse Server", :type => :string, :short => "-s"
21
+ opt :port, "Port the Apocalypse Server is listening on. Default: 80", :type => :string, :default => '80', :short => "-p"
22
+ opt :hostid, "Identifier for this server", :type => :string, :short => "-i"
23
+ end
24
+ when "install"
25
+ Trollop::options do
26
+ # TODO
27
+ end
28
+ when "check"
29
+ Trollop::options do
30
+ # TODO
31
+ end
32
+ else
33
+ Trollop::die "unknown command #{cmd.inspect}"
34
+ end
35
+
36
+ reporter = Apocalypse::Client.new
37
+ reporter.send(cmd, cmd_opts)
@@ -0,0 +1,133 @@
1
+ require 'rubygems'
2
+ require 'net/http'
3
+ require 'json'
4
+
5
+ class Hash
6
+ #
7
+ # Create a hash from an array of keys and corresponding values.
8
+ def self.zip(keys, values, default=nil, &block)
9
+ hsh = block_given? ? Hash.new(&block) : Hash.new(default)
10
+ keys.zip(values) { |k,v| hsh[k]=v }
11
+ hsh
12
+ end
13
+ end
14
+
15
+ module Apocalypse
16
+ class Client
17
+ ## Commands
18
+
19
+ # Report metrics
20
+ def report(options)
21
+ puts options.inspect
22
+ request = Net::HTTP::Post.new("/api/metrics/#{options[:hostid]}", initheader = {'Content-Type' =>'application/json'})
23
+ request.body = gather_metrics.to_json
24
+ response = Net::HTTP.new(options[:server], options[:port]).start {|http| http.request(request) }
25
+ puts "Response #{response.code} #{response.message}: #{response.body}"
26
+ end
27
+
28
+ # Check if all local deps are available
29
+ def check(options)
30
+ errors = []
31
+ [
32
+ ["/usr/bin/iostat", "sysstat"]
33
+ ].each do |filename, package|
34
+ errors << "Cannot find `#{filename}`. Please run `apt-get install #{package}` to resolve this." if !File.exists?(filename)
35
+ end
36
+
37
+ if errors.empty?
38
+ puts "Everything seems to be in place. You're good to go."
39
+ else
40
+ errors.each { |error| puts errors }
41
+ end
42
+ end
43
+
44
+ def install(options)
45
+ puts <<-EOF
46
+ Sorry, no automated installation yet. Installation is, however, quite easy.
47
+
48
+ Simply create the file `/etc/cron.d/apocalypse` and put the following line in it:
49
+
50
+ * * * * * root PATH=$PATH:/sbin:/usr/sbin /usr/bin/env apocalypse-reporter report --server APOCALYPSE_SERVER --hostid SERVER_ID > /dev/null
51
+
52
+ Make sure to replace the server and hostid placeholders with something more useful.
53
+ EOF
54
+ end
55
+
56
+ # Gather metrics
57
+ def gather_metrics
58
+ {
59
+ 'cpu' => {
60
+ 'cores' => cpu_cores.strip,
61
+ 'loadavg' => cpu_loadavg
62
+ },
63
+ 'memory' => memory_metrics,
64
+ 'swap' => swap_metrics,
65
+ 'blockdevices' => blockdevice_metrics,
66
+ 'network' => network_metrics
67
+ }
68
+ end
69
+
70
+ # Returns the number of CPU Cores for this system
71
+ def cpu_cores
72
+ `cat /proc/cpuinfo | grep bogomips | wc -l`.strip
73
+ end
74
+
75
+ # Gather load average data
76
+ def cpu_loadavg
77
+ `cat /proc/loadavg`.split
78
+ end
79
+
80
+ def blockdevice_metrics
81
+ columns = ["tps", "rps", "wps", "size", "used", "available", "usage", "mount"]
82
+
83
+ io_data = `/usr/bin/env iostat -dk | tail -n+4`.split("\n").map { |line| line.split[0...-2] }
84
+ usage_data = `df -l --block-size=M | grep -i ^/dev/[sh]`.split("\n").map { |line| line.split }
85
+
86
+ io_data.collect do |device_data|
87
+ device_name = device_data.shift
88
+ device_usage = usage_data.select { |x| x[0].include? device_name }.flatten
89
+
90
+ unless device_usage.empty?
91
+ device_data += device_usage[1..-1]
92
+ end
93
+
94
+ { device_name => Hash.zip(columns, device_data) }
95
+ end
96
+ end
97
+
98
+ def memory_metrics
99
+ {
100
+ 'free' => `cat /proc/meminfo | grep MemFree | awk '{print $2}'`.strip,
101
+ 'total' => `cat /proc/meminfo | grep MemTotal | awk '{print $2}'`.strip
102
+ }
103
+ end
104
+
105
+ def swap_metrics
106
+ {
107
+ 'free' => `cat /proc/meminfo | grep SwapFree | awk '{print $2}'`.strip,
108
+ 'total' => `cat /proc/meminfo | grep SwapTotal | awk '{print $2}'`.strip
109
+ }
110
+ end
111
+
112
+ def network_metrics
113
+ devices = `/usr/bin/env ifconfig | egrep 'Link encap' | grep -v 'lo' | awk '{print $1}'`.split
114
+
115
+ devices.collect do |device_name|
116
+ { device_name => {
117
+ 'hwaddr' => `/usr/bin/env ifconfig #{device_name} | egrep -o 'HWaddr \([0-9a-fA-F]\{2\}\:*\){6}' | awk '{print $2}'`.strip,
118
+ 'mtu' => `/usr/bin/env ifconfig #{device_name} | egrep -o MTU\:[0-9]+ | tr -s ':' ' ' | awk '{print $2}'`.strip,
119
+ 'metric' => `/usr/bin/env ifconfig #{device_name} | egrep -o Metric\:[0-9]+ | tr -s ':' ' ' | awk '{print $2}'`.strip,
120
+ 'encapsulation' => `/usr/bin/env ifconfig #{device_name} | egrep -o 'Link encap\:[a-zA-Z]+' | cut -d":" -f2`.strip,
121
+ 'rxbytes' => `/usr/bin/env ifconfig #{device_name} | grep bytes | awk '/RX/ {print $2}' | tr -s ':' ' ' | awk '{print $2}'`.strip,
122
+ 'txbytes' => `/usr/bin/env ifconfig #{device_name} | grep bytes | awk '/TX/ {print $6}' | tr -s ':' ' ' | awk '{print $2}'`.strip,
123
+ 'ipv4address' => `/usr/bin/env ifconfig #{device_name} | egrep -o 'inet addr\:[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | tr -s ':' ' ' | awk '{print $3}'`.strip,
124
+ 'broadcast' => `/usr/bin/env ifconfig #{device_name} | egrep -o Bcast\:[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\} | tr -s ':' ' ' | awk '{print $2}'`.strip,
125
+ 'netmask' => `/usr/bin/env ifconfig #{device_name} | egrep -o Mask\:[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\} | tr -s ':' ' ' | awk '{print $2}'`.strip,
126
+ 'gateway' => `netstat -rn | grep ^0.0.0.0 | grep UG | grep #{device_name} | awk '{print $2}' | head -n1`.strip,
127
+ 'ipv6addr' => `/usr/bin/env ifconfig #{device_name} | egrep -o 'inet6 addr\:\ \([a-fA-F0-9]\{1,4}\:\{1,2\}[a-fA-F0-9]\{1,4}\:\{1,2\}\)+[A-Fa-f0-9\/^\ ]+' | awk '{print $3}'`.strip,
128
+ 'ipv6scope' => `/usr/bin/env ifconfig #{device_name} | egrep -o Scope\:[a-zA-Z]+ | cut -d":" -f2`.strip
129
+ }}
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,5 @@
1
+ module Apocalypse
2
+ class Client
3
+ VERSION = "0.0.2"
4
+ end
5
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ describe Apocalypse::Client do
4
+ before(:each) do
5
+ @reporter = Apocalypse::Client.new
6
+ end
7
+
8
+ describe "cpu cores" do
9
+ it "should return the correct number of cores" do
10
+ @reporter.should_receive(:`).with("cat /proc/cpuinfo | grep bogomips | wc -l").and_return("4")
11
+ @reporter.cpu_cores.should eql("4")
12
+ end
13
+ end
14
+
15
+ describe "cpu loadavg" do
16
+ it "should return the correct loadavg values" do
17
+ @reporter.should_receive(:`).with("cat /proc/loadavg").and_return("0.89 0.92 1.12 1/124 28786")
18
+ @reporter.cpu_loadavg.should eql(["0.89", "0.92", "1.12", "1/124", "28786"])
19
+ end
20
+ end
21
+
22
+ describe "memory" do
23
+ it "should gather free and used memory" do
24
+ @reporter.should_receive(:`).with("cat /proc/meminfo | grep MemFree | awk '{print $2}'").and_return("998452")
25
+ @reporter.should_receive(:`).with("cat /proc/meminfo | grep MemTotal | awk '{print $2}'").and_return("7864548")
26
+
27
+ memory_metrics = @reporter.memory_metrics
28
+ memory_metrics["free"].should eql("998452")
29
+ memory_metrics["total"].should eql("7864548")
30
+ end
31
+ end
32
+
33
+ describe "swap" do
34
+ it "should gather free and used swap" do
35
+ @reporter.should_receive(:`).with("cat /proc/meminfo | grep SwapFree | awk '{print $2}'").and_return("934452")
36
+ @reporter.should_receive(:`).with("cat /proc/meminfo | grep SwapTotal | awk '{print $2}'").and_return("15728632")
37
+
38
+ swap_metrics = @reporter.swap_metrics
39
+ swap_metrics["free"].should eql("934452")
40
+ swap_metrics["total"].should eql("15728632")
41
+ end
42
+ end
43
+
44
+ describe "networking" do
45
+ it "should get network metrics" do
46
+ {
47
+ "/usr/bin/env ifconfig | egrep 'Link encap' | grep -v 'lo' | awk '{print $1}'" => "eth0",
48
+ "/usr/bin/env ifconfig eth0 | egrep -o 'HWaddr \([0-9a-fA-F]\{2\}\:*\){6}' | awk '{print $2}'" => "bc:de:12:ba:38:b3",
49
+ "/usr/bin/env ifconfig eth0 | egrep -o MTU\:[0-9]+ | tr -s ':' ' ' | awk '{print $2}'" => "1500",
50
+ "/usr/bin/env ifconfig eth0 | egrep -o Metric\:[0-9]+ | tr -s ':' ' ' | awk '{print $2}'" => "1",
51
+ "/usr/bin/env ifconfig eth0 | egrep -o 'Link encap\:[a-zA-Z]+' | cut -d\":\" -f2" => "Ethernet",
52
+ "/usr/bin/env ifconfig eth0 | grep bytes | awk '/RX/ {print $2}' | tr -s ':' ' ' | awk '{print $2}'" => "384735745",
53
+ "/usr/bin/env ifconfig eth0 | grep bytes | awk '/TX/ {print $6}' | tr -s ':' ' ' | awk '{print $2}'" => "3575372573",
54
+ "/usr/bin/env ifconfig eth0 | egrep -o 'inet addr\:[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | tr -s ':' ' ' | awk '{print $3}'" => "10.187.234.18",
55
+ "/usr/bin/env ifconfig eth0 | egrep -o Bcast\:[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\} | tr -s ':' ' ' | awk '{print $2}'" => "10.187.234.254",
56
+ "/usr/bin/env ifconfig eth0 | egrep -o Mask\:[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\} | tr -s ':' ' ' | awk '{print $2}'" => "255.0.0.0",
57
+ "netstat -rn | grep ^0.0.0.0 | grep UG | grep eth0 | awk '{print $2}' | head -n1" => "10.187.234.1",
58
+ "/usr/bin/env ifconfig eth0 | egrep -o 'inet6 addr\:\ \([a-fA-F0-9]\{1,4}\:\{1,2\}[a-fA-F0-9]\{1,4}\:\{1,2\}\)+[A-Fa-f0-9\/^\ ]+' | awk '{print $3}'" => "fe80::1031:3cff:fe00:bde1/64",
59
+ "/usr/bin/env ifconfig eth0 | egrep -o Scope\:[a-zA-Z]+ | cut -d\":\" -f2" => "Link"
60
+ }.each do |command, result|
61
+ @reporter.should_receive(:`).with(command).and_return(result)
62
+ end
63
+
64
+ network_metrics = @reporter.network_metrics.first["eth0"]
65
+
66
+ network_metrics["hwaddr"].should eql("bc:de:12:ba:38:b3")
67
+ network_metrics["mtu"].should eql("1500")
68
+ network_metrics["metric"].should eql("1")
69
+ network_metrics["encapsulation"].should eql("Ethernet")
70
+ network_metrics["rxbytes"].should eql("384735745")
71
+ network_metrics["txbytes"].should eql("3575372573")
72
+ network_metrics["ipv4address"].should eql("10.187.234.18")
73
+ network_metrics["broadcast"].should eql("10.187.234.254")
74
+ network_metrics["netmask"].should eql("255.0.0.0")
75
+ network_metrics["gateway"].should eql("10.187.234.1")
76
+ network_metrics["ipv6addr"].should eql("fe80::1031:3cff:fe00:bde1/64")
77
+ network_metrics["ipv6scope"].should eql("Link")
78
+ end
79
+ end
80
+
81
+ describe "block devices" do
82
+ it "should gather the correct block device info" do
83
+ iostat = <<-EOF
84
+ sda1 0.21 1.95 2.35 157872 189884
85
+ sda2 5.74 18.53 22.08 1496597 1783516
86
+
87
+ EOF
88
+
89
+ df = <<-EOF
90
+ /dev/sda2 29529M 7506M 20524M 27% /
91
+ EOF
92
+
93
+ @reporter.should_receive(:`).with("/usr/bin/env iostat -dk | tail -n+4").and_return(iostat)
94
+ @reporter.should_receive(:`).with("df -l --block-size=M | grep -i ^/dev/[sh]").and_return(df)
95
+
96
+ result = @reporter.blockdevice_metrics
97
+
98
+ result.size.should eql(2)
99
+
100
+ # sda1
101
+ sda1 = result.select{ |a| a.keys.include?("sda1") }.first["sda1"]
102
+
103
+ sda1["tps"].should eql("0.21")
104
+ sda1["rps"].should eql("1.95")
105
+ sda1["wps"].should eql("2.35")
106
+ sda1["size"].should be_nil
107
+ sda1["usage"].should be_nil
108
+ sda1["used"].should be_nil
109
+ sda1["available"].should be_nil
110
+ sda1["mount"].should be_nil
111
+
112
+ # sda2
113
+ sda2 = result.select{ |a| a.keys.include?("sda2") }.first["sda2"]
114
+
115
+ sda2["tps"].should eql("5.74")
116
+ sda2["rps"].should eql("18.53")
117
+ sda2["wps"].should eql("22.08")
118
+ sda2["size"].should eql("29529M")
119
+ sda2["usage"].should eql("27%")
120
+ sda2["used"].should eql("7506M")
121
+ sda2["available"].should eql("20524M")
122
+ sda2["mount"].should eql("/")
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,4 @@
1
+ require 'apocalypse-client'
2
+
3
+ require 'rspec'
4
+ require 'json'
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apocalypse-client
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Ariejan de Vroom
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-06 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 1
32
+ - 5
33
+ - 3
34
+ version: 1.5.3
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: trollop
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 83
46
+ segments:
47
+ - 1
48
+ - 16
49
+ - 2
50
+ version: 1.16.2
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 23
62
+ segments:
63
+ - 2
64
+ - 6
65
+ - 0
66
+ version: 2.6.0
67
+ type: :development
68
+ version_requirements: *id003
69
+ description: Server monitoring made easy
70
+ email:
71
+ - ariejan@ariejan.net
72
+ executables:
73
+ - apocalypse-client
74
+ extensions: []
75
+
76
+ extra_rdoc_files: []
77
+
78
+ files:
79
+ - .gitignore
80
+ - .rspec
81
+ - Gemfile
82
+ - README.md
83
+ - Rakefile
84
+ - apocalypse-client.gemspec
85
+ - bin/apocalypse-client
86
+ - lib/apocalypse-client.rb
87
+ - lib/apocalypse-client/version.rb
88
+ - spec/client_spec.rb
89
+ - spec/spec_helper.rb
90
+ has_rdoc: true
91
+ homepage: ""
92
+ licenses: []
93
+
94
+ post_install_message:
95
+ rdoc_options: []
96
+
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project: apocalypse-client
120
+ rubygems_version: 1.5.0
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Watch out for the apocalypse
124
+ test_files:
125
+ - spec/client_spec.rb
126
+ - spec/spec_helper.rb