tastevin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +43 -0
- data/bin/tastevin +5 -0
- data/lib/tastevin.rb +5 -0
- data/lib/tastevin/agent.rb +97 -0
- data/lib/tastevin/cli.rb +117 -0
- data/lib/tastevin/config.rb +55 -0
- data/lib/tastevin/errors.rb +12 -0
- data/lib/tastevin/version.rb +3 -0
- metadata +183 -0
data/README.md
ADDED
@@ -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.
|
data/bin/tastevin
ADDED
data/lib/tastevin.rb
ADDED
@@ -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
|
data/lib/tastevin/cli.rb
ADDED
@@ -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
|
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: []
|