rubicante 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,7 @@
1
+ === 0.0.1 / 2009-04-08
2
+
3
+ * Initial alpha release
4
+ * Support adding hosts with
5
+ * ports
6
+ * websites
7
+ * Report 'what is wrong'
data/Manifest.txt ADDED
@@ -0,0 +1,26 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ README.txt
5
+ Rakefile
6
+ bin/rubicante
7
+ lib/rubicante.rb
8
+ lib/rubicante/cli.rb
9
+ lib/rubicante/environment.rb
10
+ lib/rubicante/host.rb
11
+ lib/rubicante/host_error.rb
12
+ lib/rubicante/host_group.rb
13
+ lib/rubicante/type.rb
14
+ lib/rubicante/type_group.rb
15
+ lib/rubicante/website.rb
16
+ lib/rubicante/website_error.rb
17
+ spec/environment_spec.rb
18
+ spec/helper.rb
19
+ spec/host_error_spec.rb
20
+ spec/host_group_spec.rb
21
+ spec/host_spec.rb
22
+ spec/type_group_spec.rb
23
+ spec/type_spec.rb
24
+ spec/website_error_spec.rb
25
+ spec/website_spec.rb
26
+ test/test_rubicante.rb
data/README.rdoc ADDED
@@ -0,0 +1,118 @@
1
+ = rubicante
2
+
3
+ * RubyForge http://rubicante.rubyforge.org
4
+ * GitHub http://github.com/avanderhook/rubicante
5
+
6
+ == DESCRIPTION:
7
+
8
+ Rubicante is a business natural language (BNL) for System Administrators (SAs).
9
+ It allows SAs to define their networks in terms of servers, what those servers
10
+ provide (websites, Win32 services), and what ports they listen on. Once the
11
+ network is defined, SAs can type in natural language questions about the network
12
+ and receive answers.
13
+
14
+ == FEATURES/PROBLEMS:
15
+
16
+ * Describe a network of computer systems
17
+ * Hosts
18
+ * Ports it should be listening on
19
+ * Critical web sites hosted
20
+ * Query the network
21
+ * What is wrong: returns items (hosts, websites) that are not functioning
22
+
23
+ == SYNOPSIS:
24
+
25
+ There are several ways that you can run Rubicante:
26
+ * An interactive shell
27
+ * An interactive shell with source file
28
+ * Cron mode
29
+ * All of the above in DEBUG mode
30
+
31
+ === Interactive Shell:
32
+
33
+ Interactive shell mode allows you to specify hosts and run Rubicante queries against them.
34
+
35
+ $ rubicante
36
+ rubicante> Host webserver provides website www.my-intranet.com
37
+ rubicante> Host webserver provides website www.good-website.com, website www.bad-website.com
38
+ rubicante> What is wrong?
39
+ [webserver] is returning code 500 for website www.bad-website.com
40
+
41
+ === Interactive Shell with Source File
42
+
43
+ Interactive shell mode with files allows you to define your network's resources
44
+ in a file, load them in to rubicante, and obtain the interactive shell prompt
45
+ so you can use Rubicante queries to examine the network.
46
+
47
+ $ cat 'my-network.bnl'
48
+ Host webserver listens on port 80, provides website www.example.com
49
+ Host shellserver listens on port 22
50
+ $ rubicante -r my-network.bnl
51
+ rubicante> What is wrong?
52
+ [shellserver] port 22 is closed.
53
+
54
+ === Cron Mode
55
+
56
+ Cron mode reads in the specified file and then asks Rubicante
57
+ "what is wrong?". Any problems discovered will be logged to STDOUT
58
+ (making this ideal for calling periodically with cron), and then exiting.
59
+
60
+ $ cat 'my-network.bnl'
61
+ host web1 website www.mycompany.com
62
+ host web2 website intranet.mycompany.com
63
+ host web3 website wiki.mycompnay.com
64
+ $ rubicante -c my-network.bnl
65
+ [web2] is returning code 500 for website intranet.mycompany.com
66
+ $
67
+
68
+ === DEBUG mode
69
+
70
+ Use the '-d' flag when executing Rubicante to obtain debug output.
71
+
72
+ == BASIC LANGUAGE SPECIFICATION:
73
+
74
+ === Conventions used
75
+ * <parameter> is a required parameter
76
+ * [optional] is an optional word (i.e., a "bubble" word for readability)
77
+
78
+ === HOST language
79
+
80
+ * Host <hostname> [provides] website <fqdn>
81
+ * Defines host <hostname> (if not previously defined) and registers the website a <fqdn> with it
82
+ * Example:
83
+ host www provides website www.example.com
84
+ * Host <hostname> [listens] [on] port <port #>
85
+ * Defined host <hostname> (if not previously defined) and registers the port <port #> to it
86
+ * Example:
87
+ host www listens on port 80"
88
+ * COMBINE HOST SUBCOMMANDS IN ONE LINE
89
+ * Example:
90
+ host www listens on port 80, port 443, provides website www.mycompany.com, website intranet.mycompany.com
91
+
92
+ === WHAT language
93
+
94
+ * What [is] wrong[?]
95
+ * checks all defined hosts for problems and reports them
96
+
97
+ == REQUIREMENTS:
98
+
99
+ * Ruby 1.8+
100
+ * logging (>= 0.9.7)
101
+ * trollop (>= 1.13)
102
+
103
+ == INSTALL:
104
+
105
+ * sudo gem install rubicante
106
+
107
+ == LICENSE:
108
+
109
+ Copyright (c) 2009, Adam VanderHook
110
+ All rights reserved.
111
+
112
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
113
+
114
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
115
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
116
+ * Neither the name of the Rubicante nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
117
+
118
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.txt ADDED
@@ -0,0 +1,118 @@
1
+ = rubicante
2
+
3
+ * RubyForge http://rubicante.rubyforge.org
4
+ * GitHub http://github.com/avanderhook/rubicante
5
+
6
+ == DESCRIPTION:
7
+
8
+ Rubicante is a business natural language (BNL) for System Administrators (SAs).
9
+ It allows SAs to define their networks in terms of servers, what those servers
10
+ provide (websites, Win32 services), and what ports they listen on. Once the
11
+ network is defined, SAs can type in natural language questions about the network
12
+ and receive answers.
13
+
14
+ == FEATURES/PROBLEMS:
15
+
16
+ * Describe a network of computer systems
17
+ * Hosts
18
+ * Ports it should be listening on
19
+ * Critical web sites hosted
20
+ * Query the network
21
+ * What is wrong: returns items (hosts, websites) that are not functioning
22
+
23
+ == SYNOPSIS:
24
+
25
+ There are several ways that you can run Rubicante:
26
+ * An interactive shell
27
+ * An interactive shell with source file
28
+ * Cron mode
29
+ * All of the above in DEBUG mode
30
+
31
+ === Interactive Shell:
32
+
33
+ Interactive shell mode allows you to specify hosts and run Rubicante queries against them.
34
+
35
+ $ rubicante
36
+ rubicante> Host webserver provides website www.my-intranet.com
37
+ rubicante> Host webserver provides website www.good-website.com, website www.bad-website.com
38
+ rubicante> What is wrong?
39
+ [webserver] is returning code 500 for website www.bad-website.com
40
+
41
+ === Interactive Shell with Source File
42
+
43
+ Interactive shell mode with files allows you to define your network's resources
44
+ in a file, load them in to rubicante, and obtain the interactive shell prompt
45
+ so you can use Rubicante queries to examine the network.
46
+
47
+ $ cat 'my-network.bnl'
48
+ Host webserver listens on port 80, provides website www.example.com
49
+ Host shellserver listens on port 22
50
+ $ rubicante -r my-network.bnl
51
+ rubicante> What is wrong?
52
+ [shellserver] port 22 is closed.
53
+
54
+ === Cron Mode
55
+
56
+ Cron mode reads in the specified file and then asks Rubicante
57
+ "what is wrong?". Any problems discovered will be logged to STDOUT
58
+ (making this ideal for calling periodically with cron), and then exiting.
59
+
60
+ $ cat 'my-network.bnl'
61
+ host web1 website www.mycompany.com
62
+ host web2 website intranet.mycompany.com
63
+ host web3 website wiki.mycompnay.com
64
+ $ rubicante -c my-network.bnl
65
+ [web2] is returning code 500 for website intranet.mycompany.com
66
+ $
67
+
68
+ === DEBUG mode
69
+
70
+ Use the '-d' flag when executing Rubicante to obtain debug output.
71
+
72
+ == BASIC LANGUAGE SPECIFICATION:
73
+
74
+ === Conventions used
75
+ * <parameter> is a required parameter
76
+ * [optional] is an optional word (i.e., a "bubble" word for readability)
77
+
78
+ === HOST language
79
+
80
+ * Host <hostname> [provides] website <fqdn>
81
+ * Defines host <hostname> (if not previously defined) and registers the website a <fqdn> with it
82
+ * Example:
83
+ host www provides website www.example.com
84
+ * Host <hostname> [listens] [on] port <port #>
85
+ * Defined host <hostname> (if not previously defined) and registers the port <port #> to it
86
+ * Example:
87
+ host www listens on port 80"
88
+ * COMBINE HOST SUBCOMMANDS IN ONE LINE
89
+ * Example:
90
+ host www listens on port 80, port 443, provides website www.mycompany.com, website intranet.mycompany.com
91
+
92
+ === WHAT language
93
+
94
+ * What [is] wrong[?]
95
+ * checks all defined hosts for problems and reports them
96
+
97
+ == REQUIREMENTS:
98
+
99
+ * Ruby 1.8+
100
+ * logging (>= 0.9.7)
101
+ * trollop (>= 1.13)
102
+
103
+ == INSTALL:
104
+
105
+ * sudo gem install rubicante
106
+
107
+ == LICENSE:
108
+
109
+ Copyright (c) 2009, Adam VanderHook
110
+ All rights reserved.
111
+
112
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
113
+
114
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
115
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
116
+ * Neither the name of the Rubicante nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
117
+
118
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/rubicante.rb'
6
+
7
+ Hoe.new('rubicante', Rubicante::VERSION) do |p|
8
+ p.remote_rdoc_dir = '' # Release to root
9
+ p.developer('Adam VanderHook', 'avanderhook@gmail.com')
10
+ p.extra_deps << ['logging', '>= 0.9.7']
11
+ p.extra_deps << ['trollop', '>= 1.13']
12
+ end
13
+
14
+ # vim: syntax=Ruby
data/bin/rubicante ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubicante/cli'
4
+
5
+ require 'trollop'
6
+
7
+ opts = Trollop::options do
8
+ banner <<-EOS
9
+ A business natural language for Systems Administrators
10
+
11
+ Usage:
12
+ rubicante [options]
13
+ where [options] are:
14
+ EOS
15
+
16
+ opt :cron, "Check the network described in the specified file and exit", :type => :string
17
+ opt :debug, "Turn debugging ON", :default => false
18
+ opt :read, "Read in and process a file", :type => :string
19
+ end
20
+
21
+ # Create the CLI interface with requested debug options
22
+ app = Rubicante::CLI.new(opts[:debug])
23
+
24
+ # If requested, load in the specified file
25
+ app.load(opts[:read]) if opts[:read]
26
+
27
+ # Validate the current network if cron mode is used
28
+ if opts[:cron]
29
+ app.load opts[:cron]
30
+ app.handle("what wrong")
31
+ end
32
+
33
+ # Display the command line unless cron mode has been turned on
34
+ app.run if not opts[:cron]
data/lib/rubicante.rb ADDED
@@ -0,0 +1,6 @@
1
+ #require 'rubicante/type'
2
+ #require 'rubicante/type_group'
3
+
4
+ class Rubicante
5
+ VERSION = '0.0.1'
6
+ end
@@ -0,0 +1,89 @@
1
+ require 'rubicante/environment'
2
+
3
+ require 'logging'
4
+
5
+ module Rubicante
6
+ # A command-line interface for Rubicante
7
+ class CLI
8
+ def initialize(debug = false)
9
+ # Set up the logger for this CLI session
10
+ @log = Logging::Logger['rubicante']
11
+ @log.add_appenders(Logging::Appender.stdout)
12
+ @log.level = debug ? :debug : :info
13
+
14
+ # Set up logger for Environment
15
+ Logging::Appender['rubicante'] = Logging::Appender.stdout
16
+ Logging::Logger['Rubicante::Environment'].add_appenders(Logging::Appender['rubicante'])
17
+ Logging::Logger['Rubicante::Environment'].level = @log.level
18
+
19
+ # Prepare Environment
20
+ @env = Environment.new
21
+ end
22
+
23
+ def process(resp)
24
+ if resp.kind_of? HostError
25
+ process_host_error(resp)
26
+ end
27
+ end
28
+
29
+ def process_host_error(resp)
30
+ if not resp.ping
31
+ puts_error(resp.hostname, "is unreachable.")
32
+ else
33
+ process_port_errors(resp)
34
+ process_website_errors(resp)
35
+ end
36
+ end
37
+
38
+ def process_port_errors(resp)
39
+ resp.bad_ports.each do |bad_port|
40
+ puts_error(resp.hostname, "port #{bad_port} is closed.")
41
+ end
42
+ end
43
+
44
+ def process_website_errors(resp)
45
+ resp.website_errors.each do |website_error|
46
+ puts_error(resp.hostname, "is returning code #{website_error.code} for website #{website_error.url}.")
47
+ end
48
+ end
49
+
50
+ def puts_error(hostname, error)
51
+ @log.info "[#{hostname}] #{error}"
52
+ end
53
+
54
+ # Load in a file, executing each line
55
+ def load(file)
56
+ cmds = File.new(file)
57
+ cmds.each_line { |cmd| handle(cmd) }
58
+ end
59
+
60
+ # Handles sending the command to the Environment and dealing
61
+ # with any return values that require output to the user
62
+ def handle(cmd)
63
+ exit if cmd == "exit"
64
+
65
+ begin
66
+ result = @env.eval_command(cmd)
67
+ rescue NotImplementedError
68
+ @log.error "Unrecognized command '#{cmd.split[0]}'."
69
+ end
70
+
71
+ # 'what' commands return Arrays
72
+ if result.kind_of? Array
73
+ result.each do |response|
74
+ process(response)
75
+ end
76
+ end
77
+ end
78
+
79
+ def run
80
+ while true do
81
+ print 'rubicante> '
82
+
83
+ cmd = gets.downcase.strip
84
+
85
+ handle(cmd)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,78 @@
1
+ require 'rubicante/host_group'
2
+
3
+ require 'logging'
4
+
5
+ module Rubicante
6
+ class Environment
7
+ attr_accessor :host
8
+
9
+ def initialize
10
+ @host = HostGroup.instance
11
+
12
+ @log = Logging::Logger[self]
13
+
14
+ # Prepare Host logger
15
+ @appender = Logging::Appender['rubicante']
16
+ Logging::Logger['Rubicante::Host'].add_appenders(Logging::Appender['rubicante']) if not @appender.nil?
17
+ Logging::Logger['Rubicante::Host'].level = @log.level
18
+ end
19
+
20
+ # Evaluate a command, sending it off to the appropriate
21
+ # 'eval_*' method. Otherwise, through a NotImplementedError
22
+ def eval_command(cmd)
23
+ @log.debug "Received command: #{cmd}"
24
+
25
+ cmd_root = 'eval_' + cmd.split[0].downcase
26
+ @log.debug "Determined command root to be: #{cmd_root}"
27
+
28
+ if self.respond_to?(cmd_root)
29
+ self.send(cmd_root, cmd)
30
+ else
31
+ raise NotImplementedError
32
+ end
33
+ end
34
+
35
+ # Perform polish on a command starting with 'host' and
36
+ # evaluate it
37
+ def eval_host(cmd)
38
+ @log.debug "Polishing 'host' command"
39
+ cmd.gsub!(/^[Hh]ost\s([\S]+)\s/, 'host["\1"]')
40
+ cmd.gsub!(/website\s([^,]+)/, '.website("\1")')
41
+ cmd.gsub!(/port\s([^,]+)/, '.port(\1)')
42
+
43
+ # Clean up some bubble words
44
+ cmd.gsub!(/listens\son\s/, '')
45
+ cmd.gsub!(/provides\s/, '')
46
+ cmd.gsub!(/,/, '') # clean up commas
47
+ cmd.gsub!(/[\s]/, '') # clean up white space
48
+
49
+ @log.debug "Evaluating polished 'host' command: #{cmd}"
50
+ instance_eval cmd
51
+ end
52
+
53
+ # Perform polish on a command starting with 'what' and
54
+ # evaluate it
55
+ def eval_what(cmd)
56
+ @log.debug "Polishing 'what' command"
57
+ # Clean up some bubble words
58
+ cmd.gsub!(/^[Ww]hat\s/, '')
59
+ cmd.gsub!(/is\s/, '')
60
+
61
+ @log.debug "Evaluating polished 'what' command: #{cmd}"
62
+ instance_eval cmd
63
+ end
64
+
65
+ def wrong?
66
+ @log.debug "Checking environment for things that are wrong"
67
+ result = []
68
+
69
+ host.hosts.keys.each do |key|
70
+ @log.debug "Checking host #{host[key].name}..."
71
+ result << host[key].wrong?
72
+ end
73
+
74
+ return result
75
+ end
76
+ alias_method :wrong, :wrong?
77
+ end
78
+ end