train 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +71 -0
- data/CHANGELOG.md +308 -0
- data/Gemfile +30 -0
- data/LICENSE +201 -0
- data/README.md +156 -0
- data/Rakefile +148 -0
- data/lib/train.rb +117 -0
- data/lib/train/errors.rb +23 -0
- data/lib/train/extras.rb +17 -0
- data/lib/train/extras/command_wrapper.rb +148 -0
- data/lib/train/extras/file_aix.rb +20 -0
- data/lib/train/extras/file_common.rb +161 -0
- data/lib/train/extras/file_linux.rb +16 -0
- data/lib/train/extras/file_unix.rb +79 -0
- data/lib/train/extras/file_windows.rb +91 -0
- data/lib/train/extras/linux_lsb.rb +60 -0
- data/lib/train/extras/os_common.rb +136 -0
- data/lib/train/extras/os_detect_darwin.rb +32 -0
- data/lib/train/extras/os_detect_linux.rb +148 -0
- data/lib/train/extras/os_detect_unix.rb +99 -0
- data/lib/train/extras/os_detect_windows.rb +57 -0
- data/lib/train/extras/stat.rb +133 -0
- data/lib/train/options.rb +80 -0
- data/lib/train/plugins.rb +40 -0
- data/lib/train/plugins/base_connection.rb +86 -0
- data/lib/train/plugins/transport.rb +49 -0
- data/lib/train/transports/docker.rb +103 -0
- data/lib/train/transports/local.rb +52 -0
- data/lib/train/transports/local_file.rb +90 -0
- data/lib/train/transports/local_os.rb +51 -0
- data/lib/train/transports/mock.rb +147 -0
- data/lib/train/transports/ssh.rb +163 -0
- data/lib/train/transports/ssh_connection.rb +225 -0
- data/lib/train/transports/winrm.rb +184 -0
- data/lib/train/transports/winrm_connection.rb +194 -0
- data/lib/train/version.rb +7 -0
- data/test/integration/.kitchen.yml +43 -0
- data/test/integration/Berksfile +3 -0
- data/test/integration/bootstrap.sh +17 -0
- data/test/integration/chefignore +1 -0
- data/test/integration/cookbooks/test/metadata.rb +1 -0
- data/test/integration/cookbooks/test/recipes/default.rb +100 -0
- data/test/integration/cookbooks/test/recipes/prep_files.rb +47 -0
- data/test/integration/docker_run.rb +153 -0
- data/test/integration/docker_test.rb +24 -0
- data/test/integration/docker_test_container.rb +24 -0
- data/test/integration/helper.rb +61 -0
- data/test/integration/sudo/customcommand.rb +15 -0
- data/test/integration/sudo/nopasswd.rb +16 -0
- data/test/integration/sudo/passwd.rb +21 -0
- data/test/integration/sudo/reqtty.rb +17 -0
- data/test/integration/sudo/run_as.rb +12 -0
- data/test/integration/test-travis-1.yaml +13 -0
- data/test/integration/test-travis-2.yaml +13 -0
- data/test/integration/test_local.rb +19 -0
- data/test/integration/test_ssh.rb +39 -0
- data/test/integration/tests/path_block_device_test.rb +74 -0
- data/test/integration/tests/path_character_device_test.rb +74 -0
- data/test/integration/tests/path_file_test.rb +79 -0
- data/test/integration/tests/path_folder_test.rb +90 -0
- data/test/integration/tests/path_missing_test.rb +77 -0
- data/test/integration/tests/path_pipe_test.rb +78 -0
- data/test/integration/tests/path_symlink_test.rb +95 -0
- data/test/integration/tests/run_command_test.rb +28 -0
- data/test/unit/extras/command_wrapper_test.rb +78 -0
- data/test/unit/extras/file_common_test.rb +180 -0
- data/test/unit/extras/linux_file_test.rb +167 -0
- data/test/unit/extras/os_common_test.rb +269 -0
- data/test/unit/extras/os_detect_linux_test.rb +189 -0
- data/test/unit/extras/os_detect_windows_test.rb +99 -0
- data/test/unit/extras/stat_test.rb +148 -0
- data/test/unit/extras/windows_file_test.rb +44 -0
- data/test/unit/helper.rb +7 -0
- data/test/unit/plugins/connection_test.rb +44 -0
- data/test/unit/plugins/transport_test.rb +111 -0
- data/test/unit/plugins_test.rb +22 -0
- data/test/unit/train_test.rb +156 -0
- data/test/unit/transports/local_file_test.rb +184 -0
- data/test/unit/transports/local_test.rb +87 -0
- data/test/unit/transports/mock_test.rb +87 -0
- data/test/unit/transports/ssh_test.rb +109 -0
- data/test/unit/version_test.rb +8 -0
- data/test/windows/local_test.rb +46 -0
- data/test/windows/winrm_test.rb +52 -0
- data/train.gemspec +38 -0
- metadata +295 -0
data/README.md
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
# Train - Transport Interface
|
2
|
+
|
3
|
+
Train lets you talk to your local or remote operating systems with a unified interface.
|
4
|
+
|
5
|
+
It allows you to:
|
6
|
+
|
7
|
+
* execute commands via `run_command`
|
8
|
+
* interact with files via `file`
|
9
|
+
* identify the target operating system via `os`
|
10
|
+
|
11
|
+
Train supports:
|
12
|
+
|
13
|
+
* Local execution
|
14
|
+
* SSH
|
15
|
+
* WinRM
|
16
|
+
* Docker
|
17
|
+
* Mock (for testing and debugging)
|
18
|
+
|
19
|
+
# Examples
|
20
|
+
|
21
|
+
## Setup
|
22
|
+
|
23
|
+
**Local**
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'train'
|
27
|
+
train = Train.create('local')
|
28
|
+
```
|
29
|
+
|
30
|
+
**SSH**
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require 'train'
|
34
|
+
train = Train.create('ssh',
|
35
|
+
host: '1.2.3.4', port: 22, user: 'root', key_files: '/vagrant')
|
36
|
+
```
|
37
|
+
|
38
|
+
**WinRM**
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
require 'train'
|
42
|
+
train = Train.create('winrm',
|
43
|
+
host: '1.2.3.4', user: 'Administrator', password: '...', ssl: true, self_signed: true)
|
44
|
+
```
|
45
|
+
|
46
|
+
**Docker**
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'train'
|
50
|
+
train = Train.create('docker', host: 'container_id...')
|
51
|
+
```
|
52
|
+
|
53
|
+
## Configuration
|
54
|
+
|
55
|
+
To get a list of available options for a plugin:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
puts Train.options('ssh')
|
59
|
+
```
|
60
|
+
This will provide all configuration options:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
{
|
64
|
+
:host => { :required => true},
|
65
|
+
:port => { :default => 22, :required => true},
|
66
|
+
:user => { :default => "root", :required => true},
|
67
|
+
:keys => { :default => nil},
|
68
|
+
:password => { :default => nil},
|
69
|
+
...
|
70
|
+
```
|
71
|
+
|
72
|
+
## Usage
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
# start or reuse a connection
|
76
|
+
conn = train.connection
|
77
|
+
|
78
|
+
# run a command on Linux/Unix/Mac
|
79
|
+
puts conn.run_command('whoami').stdout
|
80
|
+
|
81
|
+
# get OS info
|
82
|
+
puts conn.os[:family]
|
83
|
+
puts conn.os[:release]
|
84
|
+
|
85
|
+
# access files
|
86
|
+
puts conn.file('/proc/version').content
|
87
|
+
|
88
|
+
# close the connection
|
89
|
+
conn.close
|
90
|
+
```
|
91
|
+
|
92
|
+
# Testing
|
93
|
+
|
94
|
+
We perform `unit`, `integration` and `windows` tests.
|
95
|
+
|
96
|
+
* `unit` tests ensure the intended behaviour of the implementation
|
97
|
+
* `integration` tests run against VMs and docker containers
|
98
|
+
* `windows` tests that run on appveyor for windows integration tests
|
99
|
+
|
100
|
+
## Windows
|
101
|
+
|
102
|
+
```
|
103
|
+
# run windows tests
|
104
|
+
bundle exec rake test:windows
|
105
|
+
|
106
|
+
# run single tests
|
107
|
+
bundle exec ruby -I .\test\windows\ .\test\windows\local_test.rb
|
108
|
+
```
|
109
|
+
|
110
|
+
|
111
|
+
# Kudos and Contributors
|
112
|
+
|
113
|
+
Train is heavily based on the work of:
|
114
|
+
|
115
|
+
* [test-kitchen](https://github.com/test-kitchen/test-kitchen)
|
116
|
+
|
117
|
+
by [Fletcher Nichol](fnichol@nichol.ca)
|
118
|
+
and [a great community of contributors](https://github.com/test-kitchen/test-kitchen/graphs/contributors)
|
119
|
+
|
120
|
+
* [ohai](https://github.com/chef/ohai)
|
121
|
+
|
122
|
+
by Adam Jacob, Chef Software Inc.
|
123
|
+
and [a great community of contributors](https://github.com/chef/ohai/graphs/contributors)
|
124
|
+
|
125
|
+
|
126
|
+
## Contributing
|
127
|
+
|
128
|
+
1. Fork it
|
129
|
+
1. Create your feature branch (git checkout -b my-new-feature)
|
130
|
+
1. Commit your changes (git commit -am 'Add some feature')
|
131
|
+
1. Push to the branch (git push origin my-new-feature)
|
132
|
+
1. Create new Pull Request
|
133
|
+
|
134
|
+
## License
|
135
|
+
|
136
|
+
| **Author:** | Dominik Richter (<drichter@chef.io>)
|
137
|
+
|
138
|
+
| **Author:** | Christoph Hartmann (<chartmann@chef.io>)
|
139
|
+
|
140
|
+
| **Copyright:** | Copyright (c) 2015 Chef Software Inc.
|
141
|
+
|
142
|
+
| **Copyright:** | Copyright (c) 2015 Vulcano Security GmbH.
|
143
|
+
|
144
|
+
| **License:** | Apache License, Version 2.0
|
145
|
+
|
146
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
147
|
+
you may not use this file except in compliance with the License.
|
148
|
+
You may obtain a copy of the License at
|
149
|
+
|
150
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
151
|
+
|
152
|
+
Unless required by applicable law or agreed to in writing, software
|
153
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
154
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
155
|
+
See the License for the specific language governing permissions and
|
156
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'bundler'
|
5
|
+
require 'bundler/gem_tasks'
|
6
|
+
require 'rake/testtask'
|
7
|
+
require 'rubocop/rake_task'
|
8
|
+
|
9
|
+
# Rubocop
|
10
|
+
desc 'Run Rubocop lint checks'
|
11
|
+
task :rubocop do
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# lint the project
|
16
|
+
desc 'Run robocop linter'
|
17
|
+
task lint: [:rubocop]
|
18
|
+
|
19
|
+
# run tests
|
20
|
+
task default: [:test, :lint]
|
21
|
+
|
22
|
+
Rake::TestTask.new do |t|
|
23
|
+
t.libs << 'test/unit'
|
24
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
25
|
+
t.warning = true
|
26
|
+
t.verbose = true
|
27
|
+
t.ruby_opts = ['--dev'] if defined?(JRUBY_VERSION)
|
28
|
+
end
|
29
|
+
|
30
|
+
namespace :test do
|
31
|
+
task :docker do
|
32
|
+
path = File.join(File.dirname(__FILE__), 'test', 'integration')
|
33
|
+
sh('sh', '-c', "cd #{path} && ruby -I ../../lib docker_test.rb tests/*")
|
34
|
+
end
|
35
|
+
|
36
|
+
task :windows do
|
37
|
+
Dir.glob('test/windows/*_test.rb').all? do |file|
|
38
|
+
sh(Gem.ruby, '-w', '-I .\test\windows', file)
|
39
|
+
end or fail 'Failures'
|
40
|
+
end
|
41
|
+
|
42
|
+
task :vm do
|
43
|
+
concurrency = ENV['CONCURRENCY'] || 4
|
44
|
+
path = File.join(File.dirname(__FILE__), 'test', 'integration')
|
45
|
+
sh('sh', '-c', "cd #{path} && kitchen test -c #{concurrency}")
|
46
|
+
end
|
47
|
+
|
48
|
+
# Target required:
|
49
|
+
# rake "test:ssh[user@server]"
|
50
|
+
# sh -c cd /home/foobarbam/src/gems/train/test/integration \
|
51
|
+
# && target=user@server ruby -I ../../lib test_ssh.rb tests/*
|
52
|
+
# ...
|
53
|
+
# Turn debug logging back on:
|
54
|
+
# debug=1 rake "test:ssh[user@server]"
|
55
|
+
# Use a different ssh key:
|
56
|
+
# key_files=/home/foobarbam/.ssh/id_rsa2 rake "test:ssh[user@server]"
|
57
|
+
# Run with a specific test:
|
58
|
+
# test=path_block_device_test.rb rake "test:ssh[user@server]"
|
59
|
+
task :ssh, [:target] do |t, args|
|
60
|
+
path = File.join(File.dirname(__FILE__), 'test', 'integration')
|
61
|
+
key_files = ENV['key_files'] || File.join(ENV['HOME'], '.ssh', 'id_rsa')
|
62
|
+
|
63
|
+
sh_cmd = "cd #{path} && target=#{args[:target]} key_files=#{key_files}"
|
64
|
+
|
65
|
+
sh_cmd += " debug=#{ENV['debug']}" if ENV['debug']
|
66
|
+
sh_cmd += ' ruby -I ../../lib test_ssh.rb tests/'
|
67
|
+
sh_cmd += ENV['test'] || '*'
|
68
|
+
|
69
|
+
sh('sh', '-c', sh_cmd)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Print the current version of this gem or update it.
|
74
|
+
#
|
75
|
+
# @param [Type] target the new version you want to set, or nil if you only want to show
|
76
|
+
def train_version(target = nil)
|
77
|
+
path = 'lib/train/version.rb'
|
78
|
+
require_relative path.sub(/.rb$/, '')
|
79
|
+
|
80
|
+
nu_version = target.nil? ? '' : " -> #{target}"
|
81
|
+
puts "Train: #{Train::VERSION}#{nu_version}"
|
82
|
+
|
83
|
+
unless target.nil?
|
84
|
+
raw = File.read(path)
|
85
|
+
nu = raw.sub(/VERSION.*/, "VERSION = '#{target}'.freeze")
|
86
|
+
File.write(path, nu)
|
87
|
+
load(path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Check if a command is available
|
92
|
+
#
|
93
|
+
# @param [Type] x the command you are interested in
|
94
|
+
# @param [Type] msg the message to display if the command is missing
|
95
|
+
def require_command(x, msg = nil)
|
96
|
+
return if system("command -v #{x} || exit 1")
|
97
|
+
msg ||= 'Please install it first!'
|
98
|
+
puts "\033[31;1mCan't find command #{x.inspect}. #{msg}\033[0m"
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
|
102
|
+
# Check if a required environment variable has been set
|
103
|
+
#
|
104
|
+
# @param [String] x the variable you are interested in
|
105
|
+
# @param [String] msg the message you want to display if the variable is missing
|
106
|
+
def require_env(x, msg = nil)
|
107
|
+
exists = `env | grep "^#{x}="`
|
108
|
+
return unless exists.empty?
|
109
|
+
puts "\033[31;1mCan't find environment variable #{x.inspect}. #{msg}\033[0m"
|
110
|
+
exit 1
|
111
|
+
end
|
112
|
+
|
113
|
+
# Check the requirements for running an update of this repository.
|
114
|
+
def check_update_requirements
|
115
|
+
require_command 'git'
|
116
|
+
require_command 'github_changelog_generator', "\n"\
|
117
|
+
"For more information on how to install it see:\n"\
|
118
|
+
" https://github.com/skywinder/github-changelog-generator\n"
|
119
|
+
require_env 'CHANGELOG_GITHUB_TOKEN', "\n"\
|
120
|
+
"Please configure this token to make sure you can run all commands\n"\
|
121
|
+
"against GitHub.\n\n"\
|
122
|
+
"See github_changelog_generator homepage for more information:\n"\
|
123
|
+
" https://github.com/skywinder/github-changelog-generator\n"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Show the current version of this gem.
|
127
|
+
desc 'Show the version of this gem'
|
128
|
+
task :version do
|
129
|
+
train_version
|
130
|
+
end
|
131
|
+
|
132
|
+
desc 'Generate the changelog'
|
133
|
+
task :changelog do
|
134
|
+
require_relative 'lib/train/version'
|
135
|
+
system "github_changelog_generator -u chef -p train --future-release #{Train::VERSION}"
|
136
|
+
end
|
137
|
+
|
138
|
+
# Update the version of this gem and create an updated
|
139
|
+
# changelog. It covers everything short of actually releasing
|
140
|
+
# the gem.
|
141
|
+
desc 'Bump the version of this gem'
|
142
|
+
task :bump_version, [:version] do |_, args|
|
143
|
+
v = args[:version] || ENV['to']
|
144
|
+
fail "You must specify a target version! rake bump_version to=1.2.3" if v.empty?
|
145
|
+
check_update_requirements
|
146
|
+
train_version(v)
|
147
|
+
Rake::Task['changelog'].invoke
|
148
|
+
end
|
data/lib/train.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
4
|
+
|
5
|
+
require 'train/version'
|
6
|
+
require 'train/plugins'
|
7
|
+
require 'train/errors'
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
module Train
|
11
|
+
# Create a new transport instance, with the plugin indicated by the
|
12
|
+
# given name.
|
13
|
+
#
|
14
|
+
# @param [String] name of the plugin
|
15
|
+
# @param [Array] *args list of arguments for the plugin
|
16
|
+
# @return [Transport] instance of the new transport or nil
|
17
|
+
def self.create(name, *args)
|
18
|
+
cls = load_transport(name)
|
19
|
+
cls.new(*args) unless cls.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Retrieve the configuration options of a transport plugin.
|
23
|
+
#
|
24
|
+
# @param [String] name of the plugin
|
25
|
+
# @return [Hash] map of default options
|
26
|
+
def self.options(name)
|
27
|
+
cls = load_transport(name)
|
28
|
+
cls.default_options unless cls.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
# Load the transport plugin indicated by name. If the plugin is not
|
32
|
+
# yet found in the plugin registry, it will be attempted to load from
|
33
|
+
# `train/transports/plugin_name`.
|
34
|
+
#
|
35
|
+
# @param [String] name of the plugin
|
36
|
+
# @return [Train::Transport] the transport plugin
|
37
|
+
def self.load_transport(name)
|
38
|
+
res = Train::Plugins.registry[name.to_s]
|
39
|
+
return res unless res.nil?
|
40
|
+
|
41
|
+
# if the plugin wasnt loaded yet:
|
42
|
+
require 'train/transports/' + name.to_s
|
43
|
+
Train::Plugins.registry[name.to_s]
|
44
|
+
rescue LoadError => _
|
45
|
+
raise Train::UserError,
|
46
|
+
"Can't find train plugin #{name.inspect}. Please install it first."
|
47
|
+
end
|
48
|
+
|
49
|
+
# Resolve target configuration in URI-scheme into
|
50
|
+
# all respective fields and merge with existing configuration.
|
51
|
+
# e.g. ssh://bob@remote => backend: ssh, user: bob, host: remote
|
52
|
+
def self.target_config(config = nil) # rubocop:disable Metrics/AbcSize
|
53
|
+
conf = config.nil? ? {} : config.dup
|
54
|
+
|
55
|
+
# symbolize keys
|
56
|
+
conf = conf.each_with_object({}) do |(k, v), acc|
|
57
|
+
acc[k.to_sym] = v
|
58
|
+
acc
|
59
|
+
end
|
60
|
+
|
61
|
+
group_keys_and_keyfiles(conf)
|
62
|
+
|
63
|
+
return conf if conf[:target].to_s.empty?
|
64
|
+
|
65
|
+
# split up the target's host/scheme configuration
|
66
|
+
uri = URI.parse(conf[:target].to_s)
|
67
|
+
unless uri.host.nil? and uri.scheme.nil?
|
68
|
+
conf[:backend] ||= uri.scheme
|
69
|
+
conf[:host] ||= uri.host
|
70
|
+
conf[:port] ||= uri.port
|
71
|
+
conf[:user] ||= uri.user
|
72
|
+
conf[:password] ||= uri.password
|
73
|
+
conf[:path] ||= uri.path
|
74
|
+
end
|
75
|
+
|
76
|
+
# ensure path is nil, if its empty; e.g. required to reset defaults for winrm
|
77
|
+
conf[:path] = nil if !conf[:path].nil? && conf[:path].to_s.empty?
|
78
|
+
|
79
|
+
# return the updated config
|
80
|
+
conf
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.validate_backend(conf, default = :local)
|
84
|
+
return default if conf.nil?
|
85
|
+
res = conf[:backend]
|
86
|
+
return res if !res.nil?
|
87
|
+
|
88
|
+
if !conf[:target].nil?
|
89
|
+
fail Train::UserError, 'Cannot determine backend from target '\
|
90
|
+
"configuration #{conf[:target].inspect}. Valid example: ssh://192.168.0.1."
|
91
|
+
end
|
92
|
+
|
93
|
+
if !conf[:host].nil?
|
94
|
+
fail Train::UserError, 'Host configured, but no backend was provided. Please '\
|
95
|
+
'specify how you want to connect. Valid example: ssh://192.168.0.1.'
|
96
|
+
end
|
97
|
+
|
98
|
+
conf[:backend] = default
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.group_keys_and_keyfiles(conf)
|
102
|
+
# in case the user specified a key-file, register it that way
|
103
|
+
# we will clear the list of keys and put keys and key_files separately
|
104
|
+
keys_mixed = conf[:keys]
|
105
|
+
return if keys_mixed.nil?
|
106
|
+
|
107
|
+
conf[:key_files] = []
|
108
|
+
conf[:keys] = []
|
109
|
+
keys_mixed.each do |key|
|
110
|
+
if !key.nil? and File.file?(key)
|
111
|
+
conf[:key_files].push(key)
|
112
|
+
else
|
113
|
+
conf[:keys].push(key)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/train/errors.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
5
|
+
# Author:: Christoph Hartmann (<chris@lollyrock.com>)
|
6
|
+
#
|
7
|
+
# Copyright (C) 2013, Fletcher Nichol
|
8
|
+
#
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
10
|
+
|
11
|
+
module Train
|
12
|
+
# Base exception class for all exceptions that are caused by user input
|
13
|
+
# errors.
|
14
|
+
class UserError < ::StandardError; end
|
15
|
+
|
16
|
+
# Base exception class for all exceptions that are caused by incorrect use
|
17
|
+
# of an API.
|
18
|
+
class ClientError < ::StandardError; end
|
19
|
+
|
20
|
+
# Base exception class for all exceptions that are caused by other failures
|
21
|
+
# in the transport layer.
|
22
|
+
class TransportError < ::StandardError; end
|
23
|
+
end
|
data/lib/train/extras.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
4
|
+
|
5
|
+
module Train::Extras
|
6
|
+
autoload :CommandWrapper, 'train/extras/command_wrapper'
|
7
|
+
autoload :FileCommon, 'train/extras/file_common'
|
8
|
+
autoload :AixFile, 'train/extras/file_aix'
|
9
|
+
autoload :UnixFile, 'train/extras/file_unix'
|
10
|
+
autoload :LinuxFile, 'train/extras/file_linux'
|
11
|
+
autoload :WindowsFile, 'train/extras/file_windows'
|
12
|
+
autoload :OSCommon, 'train/extras/os_common'
|
13
|
+
autoload :Stat, 'train/extras/stat'
|
14
|
+
|
15
|
+
CommandResult = Struct.new(:stdout, :stderr, :exit_status)
|
16
|
+
LoginCommand = Struct.new(:command, :arguments)
|
17
|
+
end
|