wiz-teleport 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +134 -0
- data/Rakefile +8 -0
- data/lib/wiz-teleport/group.rb +34 -0
- data/lib/wiz-teleport/inventory.rb +59 -0
- data/lib/wiz-teleport/rake_dsl.rb +26 -0
- data/lib/wiz-teleport/server.rb +28 -0
- data/lib/wiz-teleport/shell.rb +26 -0
- data/lib/wiz-teleport/ssh_client.rb +56 -0
- data/lib/wiz-teleport/version.rb +5 -0
- data/lib/wiz-teleport.rb +19 -0
- data/sig/wiz-teleport.rbs +4 -0
- data/vendor/cache/minitest-5.25.1.gem +0 -0
- data/vendor/cache/mocha-2.7.1.gem +0 -0
- data/vendor/cache/net-scp-4.0.0.gem +0 -0
- data/vendor/cache/net-ssh-7.3.0.gem +0 -0
- data/vendor/cache/rake-13.0.6.gem +0 -0
- data/vendor/cache/ruby2_keywords-0.0.5.gem +0 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d1ff1cfcc0ac285e58b14056c9d12b30632aa08d925d7035cc74036771754de4
|
4
|
+
data.tar.gz: a679bec7f1d1fe9de10255075fd56b2da3cd8c41a938d4ab7926d1a04726fbcb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7a4ddc7a791b21a6b0143fc22765ed3515722cba703ab4b80a83bcb1adeef09ad9730cb3a4981719e06903d54a0355a81d1c95129bb6762158ba8b66476805ba
|
7
|
+
data.tar.gz: 6e406c036cdbc4b0865461f9fdeb91fc64c47a0c12adb44e10ed30da324e838aa31749117f6d2e6c25ab31f8495ece808d6b956ec558bb7fb49d4b6bc6ecca35
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 songgz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# WizTeleport
|
2
|
+
|
3
|
+
WizTeleport is a Ruby Gem that simplifies SSH connections and remote command execution. It is ideal for operational tasks and automated deployments.
|
4
|
+
|
5
|
+
WizTeleport is designed to execute shell commands remotely over SSH, with no agents to install on remote systems.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```bash
|
12
|
+
gem 'wiz-teleport'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
$ bundle
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
gem install wiz-teleport
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
WizTeleport is a powerful automation tool for configuration management, application deployment, task execution, and more. It is based on SSH, so there is no need to install the agent on the target host. Here are the basic steps and examples for using WizTeleport.
|
29
|
+
|
30
|
+
1. Create a project directory
|
31
|
+
|
32
|
+
First, create a new directory to save your Ruby project:
|
33
|
+
```bash
|
34
|
+
mkdir my_ruby_project
|
35
|
+
cd my_ruby_project
|
36
|
+
```
|
37
|
+
2. Install WizTeleport
|
38
|
+
|
39
|
+
Make sure you have Ruby installed. Then run the following command to install the WizTeleport:
|
40
|
+
```bash
|
41
|
+
gem install wiz-teleport
|
42
|
+
```
|
43
|
+
|
44
|
+
3. Create an WizTeleport manifest file
|
45
|
+
|
46
|
+
WizTeleport uses a manifest file to define hosts. Wiz-Teleport reads a list or group from Inventory.yml and can operate these controlled nodes or hosts simultaneously and concurrently, just like Ansible. Create a file called inventory.yml that looks like this:
|
47
|
+
```yaml
|
48
|
+
# inventory.yml
|
49
|
+
---
|
50
|
+
- name: web1
|
51
|
+
user: root
|
52
|
+
password: root
|
53
|
+
servers:
|
54
|
+
- host: 127.0.0.1
|
55
|
+
- name: data1
|
56
|
+
servers:
|
57
|
+
- host: db1.example.com
|
58
|
+
- host: db2.example.com
|
59
|
+
name: db1
|
60
|
+
user: root
|
61
|
+
password: root
|
62
|
+
children:
|
63
|
+
- web1
|
64
|
+
```
|
65
|
+
6. Build an WizTeleport script
|
66
|
+
|
67
|
+
WizTeleport script defines tasks by writing ruby scripts. Here is an example of a simple WizTeleport script:
|
68
|
+
```ruby
|
69
|
+
#example.rb
|
70
|
+
require 'wiz-teleport'
|
71
|
+
|
72
|
+
WizTeleport::Shell.run 'web1' do
|
73
|
+
# write ruby code
|
74
|
+
puts "Hello from Ruby Shell!"
|
75
|
+
|
76
|
+
# running linux command
|
77
|
+
uname "-a"
|
78
|
+
ls "-l"
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
```
|
83
|
+
7. Execute WizTeleport script
|
84
|
+
|
85
|
+
Run WizTeleport script using ruby command:
|
86
|
+
```bash
|
87
|
+
ruby example.rb
|
88
|
+
```
|
89
|
+
## Build WizTeleport task
|
90
|
+
Executing shell tasks in rakefiles is a common requirement. A shell task is actually a rake task. Here is a basic example of how to define and execute a shell task in a Rakefile.
|
91
|
+
|
92
|
+
1. Create Rakefile
|
93
|
+
```ruby
|
94
|
+
# Rakefile.rb
|
95
|
+
require 'rake'
|
96
|
+
require 'wiz-teleport'
|
97
|
+
|
98
|
+
namespace :custom do
|
99
|
+
desc "A custom shell task"
|
100
|
+
shell :example, 'web1' do
|
101
|
+
puts 'Hello from Ruby Shell!'
|
102
|
+
uname "-a"
|
103
|
+
ls "-l"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
```
|
107
|
+
2. Execute Rake tasks
|
108
|
+
```bash
|
109
|
+
rake custom:example
|
110
|
+
```
|
111
|
+
|
112
|
+
## File structure
|
113
|
+
|
114
|
+
The project structure looks like this:
|
115
|
+
```bash
|
116
|
+
my_ruby_project/
|
117
|
+
│
|
118
|
+
├── inventory.yml
|
119
|
+
├── Rakefile
|
120
|
+
├── example.rb
|
121
|
+
└── ... other file
|
122
|
+
```
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/songgz/wiz-teleport. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/songgz/wiz-teleport/blob/master/CODE_OF_CONDUCT.md).
|
127
|
+
|
128
|
+
## License
|
129
|
+
|
130
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
131
|
+
|
132
|
+
## Code of Conduct
|
133
|
+
|
134
|
+
Everyone interacting in the WizTeleport project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/wiz-teleport/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative './server'
|
3
|
+
|
4
|
+
module WizTeleport
|
5
|
+
class Group
|
6
|
+
attr_reader :name, :servers, :children, :user, :password, :port
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
options = options.transform_keys(&:to_sym)
|
10
|
+
@name = options[:name]
|
11
|
+
@children = options[:children] || []
|
12
|
+
@user = options[:user] || 'root'
|
13
|
+
@password = options[:password]
|
14
|
+
@port = options[:port] || 22
|
15
|
+
@servers = (options[:servers] || []).map do |server_data|
|
16
|
+
server_data[:user] ||= @user
|
17
|
+
server_data[:password] ||= @password
|
18
|
+
server_data[:port] ||= @port
|
19
|
+
Server.new(server_data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_h
|
24
|
+
h = {'name' => @name}
|
25
|
+
h['servers'] = @servers.map(&:to_h)
|
26
|
+
h['children'] = @children if @children
|
27
|
+
h['user'] = @user if @user
|
28
|
+
h['password'] = @password if @password
|
29
|
+
h['port'] = @port if @port
|
30
|
+
h
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'yaml'
|
3
|
+
require 'singleton'
|
4
|
+
require_relative './group'
|
5
|
+
require_relative './server'
|
6
|
+
require_relative './ssh_client'
|
7
|
+
|
8
|
+
module WizTeleport
|
9
|
+
class Inventory
|
10
|
+
include Singleton
|
11
|
+
attr_reader :groups
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@groups = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_host_group(group)
|
18
|
+
@groups.push(group)
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_group_by_name(name)
|
22
|
+
@groups.detect {|group| name == group.name}
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_groups_by_names(names)
|
26
|
+
@groups.select {|group| names.include?(group.name)}
|
27
|
+
end
|
28
|
+
|
29
|
+
def clients_from_group(group_name)
|
30
|
+
group = @groups.find { |g| g.name == group_name }
|
31
|
+
groups = group ? find_groups_by_names([group_name] + group.children) : @groups
|
32
|
+
|
33
|
+
groups.flat_map do |group|
|
34
|
+
group.servers&.map do |server|
|
35
|
+
server.user ||= group.user
|
36
|
+
server.password = group.password
|
37
|
+
server.port ||= group.port
|
38
|
+
SSHClient.new(server)
|
39
|
+
end || []
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_yaml(file_path = 'inventory.yml')
|
44
|
+
yaml_data = @groups.map(&:to_h)
|
45
|
+
File.write(file_path, YAML.dump(yaml_data))
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def from_yaml(file_path = 'inventory.yml')
|
50
|
+
yaml_data = YAML.load_file(file_path)
|
51
|
+
@groups = yaml_data.map { |group_data| Group.new(group_data) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def clear
|
55
|
+
@groups = []
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rake'
|
3
|
+
require_relative './shell'
|
4
|
+
|
5
|
+
module WizTeleport
|
6
|
+
module RakeDSL
|
7
|
+
|
8
|
+
def shell(task_name, group_name, &block)
|
9
|
+
Rake::Task.define_task(task_name) do
|
10
|
+
WizTeleport::Shell.run(group_name, &block) if block_given?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Rake::TaskManager.record_task_metadata do |t|
|
18
|
+
# t.instance_eval do
|
19
|
+
# extend Teleport::RakeDSL
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# if defined?(Rake)
|
23
|
+
# Rake.application.instance_eval do
|
24
|
+
# extend Teleport::RakeDSL
|
25
|
+
# end
|
26
|
+
# end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module WizTeleport
|
3
|
+
class Server
|
4
|
+
attr_reader :host, :name
|
5
|
+
attr_accessor :user, :password, :port
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
options = options.transform_keys(&:to_sym)
|
9
|
+
@name = options[:name]
|
10
|
+
@host = options[:host]
|
11
|
+
@user = options[:user]
|
12
|
+
@password = options[:password]
|
13
|
+
@port = options[:port]
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
h = {'host' => @host}
|
18
|
+
h['name'] = @name if @name
|
19
|
+
h['user'] = @user if @user
|
20
|
+
h['password'] = @password if @password
|
21
|
+
h['port'] = @port if @port
|
22
|
+
h
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative './inventory'
|
3
|
+
|
4
|
+
module WizTeleport
|
5
|
+
class Shell
|
6
|
+
def initialize(file_path = 'inventory.yml')
|
7
|
+
@inventory = WizTeleport::Inventory.instance
|
8
|
+
@inventory.from_yaml(file_path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(group_name, &block)
|
12
|
+
@clients = @inventory.clients_from_group(group_name)
|
13
|
+
@clients.each do |client|
|
14
|
+
client.instance_eval(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.run(group_name, &block)
|
19
|
+
shell = WizTeleport::Shell.new
|
20
|
+
shell.run(group_name, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'net/scp'
|
4
|
+
|
5
|
+
class SSHClient
|
6
|
+
attr_reader :server, :client
|
7
|
+
|
8
|
+
def initialize(server)
|
9
|
+
@server = server
|
10
|
+
@client = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(command, *args)
|
14
|
+
command_string = command.to_s
|
15
|
+
if run("command -v #{command_string}")
|
16
|
+
puts "Executing command: #{command} #{args.join(' ')}"
|
17
|
+
output = run("#{command} #{args.join(' ')}")
|
18
|
+
puts output
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def connect
|
25
|
+
@client = Net::SSH.start(@server.host, @server.user, password: @server.password)
|
26
|
+
rescue StandardError => e
|
27
|
+
puts "Error connecting to #{@server.host}: #{e.message}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def run1(command)
|
31
|
+
return unless @client
|
32
|
+
|
33
|
+
@client.exec!(command)
|
34
|
+
rescue StandardError => e
|
35
|
+
puts "Error executing command on #{@host}: #{e.message}"
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def run(command)
|
40
|
+
connect unless @client
|
41
|
+
output = ""
|
42
|
+
@client.exec!(command) do |channel, stream, data|
|
43
|
+
output = data
|
44
|
+
end
|
45
|
+
output
|
46
|
+
end
|
47
|
+
|
48
|
+
def put(local_file, remote_path)
|
49
|
+
connect unless @client
|
50
|
+
Net::SCP.upload!(@client.connection, local_file, remote_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def close
|
54
|
+
@client.close if @client
|
55
|
+
end
|
56
|
+
end
|
data/lib/wiz-teleport.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "wiz-teleport/version"
|
3
|
+
require_relative 'wiz-teleport/rake_dsl'
|
4
|
+
|
5
|
+
module WizTeleport
|
6
|
+
class Error < StandardError; end
|
7
|
+
# Your code goes here...
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
if defined?(Rake)
|
12
|
+
extend WizTeleport::RakeDSL
|
13
|
+
end
|
14
|
+
|
15
|
+
# if defined?(Rake)
|
16
|
+
# Rake.application.instance_eval do
|
17
|
+
# extend Teleport::RakeDSL
|
18
|
+
# end
|
19
|
+
# end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wiz-teleport
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- songgz
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: net-ssh
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.3.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.3.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: net-scp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
description: Teleport is designed to execute shell commands remotely over SSH, with
|
56
|
+
no agents to install on remote systems.
|
57
|
+
email:
|
58
|
+
- "'sgzhe@163.com'"
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- LICENSE.txt
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- lib/wiz-teleport.rb
|
67
|
+
- lib/wiz-teleport/group.rb
|
68
|
+
- lib/wiz-teleport/inventory.rb
|
69
|
+
- lib/wiz-teleport/rake_dsl.rb
|
70
|
+
- lib/wiz-teleport/server.rb
|
71
|
+
- lib/wiz-teleport/shell.rb
|
72
|
+
- lib/wiz-teleport/ssh_client.rb
|
73
|
+
- lib/wiz-teleport/version.rb
|
74
|
+
- sig/wiz-teleport.rbs
|
75
|
+
- vendor/cache/minitest-5.25.1.gem
|
76
|
+
- vendor/cache/mocha-2.7.1.gem
|
77
|
+
- vendor/cache/net-scp-4.0.0.gem
|
78
|
+
- vendor/cache/net-ssh-7.3.0.gem
|
79
|
+
- vendor/cache/rake-13.0.6.gem
|
80
|
+
- vendor/cache/ruby2_keywords-0.0.5.gem
|
81
|
+
homepage: https://github.com/songgz/wiz-teleport
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata:
|
85
|
+
allowed_push_host: https://rubygems.org
|
86
|
+
homepage_uri: https://github.com/songgz/wiz-teleport
|
87
|
+
source_code_uri: https://github.com/songgz/wiz-teleport
|
88
|
+
changelog_uri: https://github.com/songgz/wiz-teleport/releases
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 3.0.0
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubygems_version: 3.5.18
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: Teleport is a Ruby Gem that simplifies SSH connections and remote command
|
108
|
+
execution. It is ideal for operational tasks and automated deployments.
|
109
|
+
test_files: []
|