tastevin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ Tastevin
2
+ ========
3
+
4
+ > **tastevin** |ˌtæstəˈvã|
5
+ > a small, shallow silver cup for tasting wines, of a type used in France.
6
+ > (New Oxford American Dictionary)
7
+
8
+ Tastevin is a command line utility for configuring and monitoring agents. It
9
+ uses the Wine protocol, of which there exist implementations [for JVM][] and
10
+ [for Ruby][].
11
+
12
+ [for JVM]: http://github.com/valotrading/wine-java
13
+ [for Ruby]: http://github.com/valotrading/wine-ruby
14
+
15
+
16
+ Installation
17
+ ------------
18
+
19
+ Install Tastevin:
20
+
21
+ gem install tastevin
22
+
23
+
24
+ Development
25
+ -----------
26
+
27
+ Install the dependencies:
28
+
29
+ bundle install
30
+
31
+ Run the tests:
32
+
33
+ bundle exec rake
34
+
35
+ Run the development version:
36
+
37
+ bundle exec bin/tastevin
38
+
39
+
40
+ License
41
+ -------
42
+
43
+ Tastevin is released under the Apache License, Version 2.0.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tastevin'
4
+
5
+ Tastevin::CLI.start(ARGV)
@@ -0,0 +1,5 @@
1
+ require 'tastevin/agent'
2
+ require 'tastevin/cli'
3
+ require 'tastevin/config'
4
+ require 'tastevin/errors'
5
+ require 'tastevin/version'
@@ -0,0 +1,97 @@
1
+ require 'wine'
2
+
3
+ module Tastevin
4
+ class Agent
5
+
6
+ def self.status(config)
7
+ begin
8
+ contact(config).release
9
+
10
+ :online
11
+ rescue Error
12
+ :offline
13
+ end
14
+ end
15
+
16
+ def self.get(config, key)
17
+ contact(config) { |agent| agent.get(key) }
18
+ end
19
+
20
+ def self.set(config, key, value)
21
+ contact(config) { |agent| agent.set(key, value) }
22
+ end
23
+
24
+ attr_accessor :host, :port
25
+
26
+ def get(key)
27
+ @session.get(key)
28
+ end
29
+
30
+ def set(key, value)
31
+ @session.set(key, value)
32
+ end
33
+
34
+ def release
35
+ @session.close
36
+ end
37
+
38
+ private
39
+
40
+ def initialize(host, port, session)
41
+ @host = host
42
+ @port = port
43
+
44
+ @session = session
45
+ end
46
+
47
+ def self.contact(config)
48
+ host = config['host']
49
+ port = config['port']
50
+ username = config['username']
51
+ password = config['password']
52
+
53
+ session = connect(host, port)
54
+ login(session, username, password)
55
+
56
+ agent = new(host, port, session)
57
+
58
+ if block_given?
59
+ begin
60
+ yield agent
61
+ ensure
62
+ agent.release
63
+ end
64
+ else
65
+ agent
66
+ end
67
+ end
68
+
69
+ private_class_method :contact
70
+
71
+ def self.connect(host, port)
72
+ begin
73
+ Wine::Session.connect(host, port)
74
+ rescue Wine::ConnectionRefused
75
+ raise ConnectionError
76
+ end
77
+ end
78
+
79
+ private_class_method :connect
80
+
81
+ def self.login(session, username, password)
82
+ begin
83
+ unless session.login(username, password)
84
+ session.close
85
+ raise LoginError
86
+ end
87
+ rescue Wine::ProtocolError
88
+ raise Error, "Protocol error"
89
+ rescue Wine::ResponseTimeout
90
+ raise Error, "Response timeout"
91
+ end
92
+ end
93
+
94
+ private_class_method :login
95
+
96
+ end
97
+ end
@@ -0,0 +1,117 @@
1
+ require 'highline'
2
+ require 'rainbow'
3
+ require 'tastevin/agent'
4
+ require 'tastevin/config'
5
+ require 'thor'
6
+
7
+ module Tastevin
8
+ class CLI < Thor
9
+
10
+ default_task :usage
11
+
12
+ desc "usage", "Describe application usage", :hide => true
13
+ def usage
14
+ puts <<-EOF
15
+
16
+ Tastevin is a command line utility for configuring and monitoring agents.
17
+
18
+ EOF
19
+ help
20
+ end
21
+
22
+ desc "add <AGENT> <HOST> <PORT>", "Add an agent"
23
+ def add(agent, host, port)
24
+ highline = HighLine.new
25
+
26
+ username = highline.ask("Username: ")
27
+ password = highline.ask("Password: ") { |q| q.echo = '*' }
28
+
29
+ config = Config.load
30
+
31
+ config.add(agent, host, port, username, password)
32
+ config.save
33
+ end
34
+
35
+ desc "rm <AGENT>", "Remove an agent"
36
+ def rm(agent)
37
+ config = Config.load
38
+ check_agent_exists(agent, config)
39
+
40
+ config.remove(agent)
41
+ config.save
42
+ end
43
+
44
+ desc "ls [-s|--status]", "List the agents"
45
+ option :status, :aliases => :s, :type => :boolean, :desc => "Show agent status"
46
+ def ls
47
+ config = Config.load
48
+
49
+ config.list.each do |name|
50
+ if options[:status]
51
+ username = config[name]['username']
52
+ host = config[name]['host']
53
+ port = config[name]['port']
54
+
55
+ text = "%-10s %s@%s:%s" % [name, username, host, port ]
56
+
57
+ status = Agent.status(config[name])
58
+ if status == :offline
59
+ puts "#{text} (#{'offline'.color(:red)})"
60
+ else
61
+ puts text
62
+ end
63
+ else
64
+ puts name
65
+ end
66
+ end
67
+ end
68
+
69
+ desc "set <AGENT> <KEY> <VALUE>", "Set a configuration value"
70
+ def set(agent, key, value)
71
+ config = Config.load
72
+ check_agent_exists(agent, config)
73
+
74
+ communicate(agent) do
75
+ Agent.set(config[agent], key, value)
76
+ end
77
+ end
78
+
79
+ desc "get <AGENT> <KEY>", "Get a configuration value"
80
+ def get(agent, key)
81
+ config = Config.load
82
+ check_agent_exists(agent, config)
83
+
84
+ communicate(agent) do
85
+ value = Agent.get(config[agent], key)
86
+ if value.length > 0
87
+ puts value
88
+ else
89
+ error("No such key '#{key}' in agent '#{agent}'")
90
+ end
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def communicate(agent, &block)
97
+ begin
98
+ block.call
99
+ rescue ConnectionError
100
+ error("Connection to agent '#{agent}' failed")
101
+ rescue LoginError
102
+ error("Logging into agent '#{agent}' failed")
103
+ rescue Error => e
104
+ error("Operation failed: #{e}")
105
+ end
106
+ end
107
+
108
+ def check_agent_exists(agent, config)
109
+ error("No such agent '#{agent}'") unless config.exists? agent
110
+ end
111
+
112
+ def error(message)
113
+ abort "tastevin: error: #{message}"
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,55 @@
1
+ require 'inifile'
2
+
3
+ module Tastevin
4
+ class Config
5
+
6
+ def self.load
7
+ FileUtils.mkdir_p(path)
8
+
9
+ filename = File.join(path, 'agents')
10
+ inifile = IniFile.new(:filename => filename)
11
+
12
+ Config.new(inifile)
13
+ end
14
+
15
+ def self.path
16
+ File.join(ENV['HOME'], '.tastevin')
17
+ end
18
+
19
+ def [](name)
20
+ @inifile[name]
21
+ end
22
+
23
+ def exists?(agent)
24
+ @inifile.has_section? agent
25
+ end
26
+
27
+ def list
28
+ @inifile.sections
29
+ end
30
+
31
+ def add(agent, host, port, username, password)
32
+ @inifile[agent] = {
33
+ 'host' => host,
34
+ 'port' => port,
35
+ 'username' => username,
36
+ 'password' => password
37
+ }
38
+ end
39
+
40
+ def remove(agent)
41
+ @inifile.delete_section agent
42
+ end
43
+
44
+ def save
45
+ @inifile.write
46
+ end
47
+
48
+ private
49
+
50
+ def initialize(inifile)
51
+ @inifile = inifile
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,12 @@
1
+ module Tastevin
2
+
3
+ class Error < StandardError
4
+ end
5
+
6
+ class ConnectionError < Error
7
+ end
8
+
9
+ class LoginError < Error
10
+ end
11
+
12
+ end
@@ -0,0 +1,3 @@
1
+ module Tastevin
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tastevin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pekka Enberg
9
+ - Jussi Virtanen
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-05-16 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: highline
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '1.6'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '1.6'
31
+ - !ruby/object:Gem::Dependency
32
+ name: inifile
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '2.0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rainbow
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.1'
63
+ - !ruby/object:Gem::Dependency
64
+ name: thor
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: '0.18'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: '0.18'
79
+ - !ruby/object:Gem::Dependency
80
+ name: wine
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: '0.1'
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: '0.1'
95
+ - !ruby/object:Gem::Dependency
96
+ name: aruba
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: '0.5'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '0.5'
111
+ - !ruby/object:Gem::Dependency
112
+ name: cucumber
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ~>
117
+ - !ruby/object:Gem::Version
118
+ version: '1.3'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ~>
125
+ - !ruby/object:Gem::Version
126
+ version: '1.3'
127
+ - !ruby/object:Gem::Dependency
128
+ name: rake
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ~>
133
+ - !ruby/object:Gem::Version
134
+ version: '10.0'
135
+ type: :development
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ~>
141
+ - !ruby/object:Gem::Version
142
+ version: '10.0'
143
+ description: Tastevin is a command line utility for configuring and monitoring agents.
144
+ email: engineering@valotrading.com
145
+ executables:
146
+ - tastevin
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - README.md
151
+ - bin/tastevin
152
+ - lib/tastevin/version.rb
153
+ - lib/tastevin/agent.rb
154
+ - lib/tastevin/config.rb
155
+ - lib/tastevin/cli.rb
156
+ - lib/tastevin/errors.rb
157
+ - lib/tastevin.rb
158
+ homepage: http://github.com/valotrading/tastevin
159
+ licenses:
160
+ - Apache License, Version 2.0
161
+ post_install_message:
162
+ rdoc_options: []
163
+ require_paths:
164
+ - lib
165
+ required_ruby_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ! '>='
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ none: false
173
+ requirements:
174
+ - - ! '>='
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 1.8.23
180
+ signing_key:
181
+ specification_version: 3
182
+ summary: Configure and monitor agents from the command line
183
+ test_files: []