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.
@@ -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: []