redipress 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +27 -0
- data/LICENSE +21 -0
- data/bin/redipress +5 -0
- data/lib/redipress/cli/configurations.rb +208 -0
- data/lib/redipress/cli/helper.rb +66 -0
- data/lib/redipress/cli.rb +35 -0
- data/lib/redipress/configuration/base.rb +118 -0
- data/lib/redipress/configuration.rb +182 -0
- data/lib/redipress/errors.rb +27 -0
- data/lib/redipress/parameter.rb +87 -0
- data/lib/redipress/ssh.rb +42 -0
- data/lib/redipress/variables.rb +9 -0
- data/lib/redipress.rb +29 -0
- data/redipress.gemspec +25 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 334430a1b5392e8f64578983c67f730f15dd6568
|
4
|
+
data.tar.gz: 4cb222821ad1d2a23119fe3b86bbe0bcd7b5fbf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0a6306c82ee19388a7efa95ee32a87198a0d4fb13188f972cdd02c676f6694ac205c5aaa1f19540027dad67d91045e5ca1514eab45006345edf1568488a49305
|
7
|
+
data.tar.gz: 5bb990692836f024d2a30253901180b61bce4955a1e2eee2691fc841da7829794ed2dcdbff9db4bf6f6b4d272d7f4f18a21195e0ccb242d7341f00a4bbf3995c
|
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Packages #
|
2
|
+
############
|
3
|
+
*.7z
|
4
|
+
*.dmg
|
5
|
+
*.gz
|
6
|
+
*.iso
|
7
|
+
*.jar
|
8
|
+
*.rar
|
9
|
+
*.tar
|
10
|
+
*.zip
|
11
|
+
|
12
|
+
# Logs #
|
13
|
+
########
|
14
|
+
*.log
|
15
|
+
|
16
|
+
# Databases #
|
17
|
+
#############
|
18
|
+
*.sql
|
19
|
+
*.sqlite
|
20
|
+
|
21
|
+
# OS Files #
|
22
|
+
############
|
23
|
+
.DS_Store
|
24
|
+
.Trashes
|
25
|
+
ehthumbs.db
|
26
|
+
Icon?
|
27
|
+
Thumbs.db
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Nialto Services
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/bin/redipress
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
unless defined?(RediPress) && RediPress.cli?
|
2
|
+
raise "You can't load this file. Please load the redipress/cli file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
module RediPress
|
6
|
+
module CLI
|
7
|
+
class Configurations < Thor
|
8
|
+
desc "execute", "Execute a configuration against a server"
|
9
|
+
def execute
|
10
|
+
# Prepare
|
11
|
+
prepare
|
12
|
+
|
13
|
+
# Print a hello message
|
14
|
+
prompt.ok("Hello, let's configure a server!")
|
15
|
+
|
16
|
+
# Get the server host
|
17
|
+
host = prompt_for_host
|
18
|
+
|
19
|
+
# Print a new line
|
20
|
+
new_line
|
21
|
+
|
22
|
+
# Get the configuration
|
23
|
+
configuration = prompt_for_configuration
|
24
|
+
|
25
|
+
# Print a new line
|
26
|
+
new_line
|
27
|
+
|
28
|
+
# Get the configuration's options
|
29
|
+
options = prompt_for_configuration_options(configuration)
|
30
|
+
|
31
|
+
# Print a new line
|
32
|
+
new_line
|
33
|
+
|
34
|
+
# Prompt to continue
|
35
|
+
exit(1) unless prompt.yes?("Proceed with the above settings?")
|
36
|
+
|
37
|
+
# Print a new line
|
38
|
+
new_line
|
39
|
+
|
40
|
+
begin
|
41
|
+
# Check if the configuration is compatible with the host
|
42
|
+
compatible = configuration.compatible?(host, options)
|
43
|
+
rescue => error
|
44
|
+
new_line
|
45
|
+
prompt.error("The configuration raised an error.")
|
46
|
+
prompt.error("See the error report below for more information:")
|
47
|
+
prompt.error("--------------------------------------------------")
|
48
|
+
|
49
|
+
raise error
|
50
|
+
end
|
51
|
+
|
52
|
+
# Check if the server is not compatible with the configuration
|
53
|
+
unless compatible
|
54
|
+
prompt.error("The configuration '#{configuration}' is not compatible with #{host.username}@#{host.hostname}")
|
55
|
+
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
# Perform the configuration on the server
|
61
|
+
result = configuration.configure(host, options)
|
62
|
+
rescue => error
|
63
|
+
new_line
|
64
|
+
prompt.error("The configuration raised an error.")
|
65
|
+
prompt.error("See the error report below for more information:")
|
66
|
+
prompt.error("--------------------------------------------------")
|
67
|
+
|
68
|
+
raise error
|
69
|
+
end
|
70
|
+
|
71
|
+
# Check if the result is nil
|
72
|
+
if result.nil?
|
73
|
+
# The server failed to configure
|
74
|
+
prompt.error("Oh dear. It looks like something went wrong whilst configuring the server.")
|
75
|
+
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
|
79
|
+
# The server has been configured
|
80
|
+
prompt.ok("Woo hoo! Your server has been configured.")
|
81
|
+
|
82
|
+
# Print a new line
|
83
|
+
new_line
|
84
|
+
|
85
|
+
# Check if there are any results to Show
|
86
|
+
unless result.empty?
|
87
|
+
# Print a table containing the results
|
88
|
+
puts TTY::Table.new(rows: result.map { |k, v| [" #{k} ", " #{v} "] }).render(:ascii)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Set the default task to execute
|
93
|
+
default_task :execute
|
94
|
+
|
95
|
+
no_tasks do
|
96
|
+
# Prompt the user for the server host
|
97
|
+
#
|
98
|
+
# Example:
|
99
|
+
# >> prompt_for_host
|
100
|
+
# => #<SSHKit::Host:0x00000000000000>
|
101
|
+
#
|
102
|
+
def prompt_for_host
|
103
|
+
# Print a short message to explain why we need the following information
|
104
|
+
prompt.ok("We need the following to be able to login to your server:")
|
105
|
+
|
106
|
+
# Prompt for the server's hostname or IP address
|
107
|
+
hostname = prompt.ask("Hostname/IP:") do |q|
|
108
|
+
q.required(true)
|
109
|
+
q.validate(/^(([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$/)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Prompt for the server's username
|
113
|
+
username = prompt.ask("Username:") do |q|
|
114
|
+
q.required(true)
|
115
|
+
q.validate(/^[a-z]+$/)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Prompt for the server's password
|
119
|
+
password = prompt.ask("Password (leave blank to use ssh keys):") do |q|
|
120
|
+
q.required(false)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Create an SSHKit::Host object
|
124
|
+
host = SSHKit::Host.new("#{username}@#{hostname}")
|
125
|
+
|
126
|
+
# Check if a password was provided
|
127
|
+
if password
|
128
|
+
# Set the password on the host
|
129
|
+
host.password = password
|
130
|
+
end
|
131
|
+
|
132
|
+
host
|
133
|
+
end
|
134
|
+
|
135
|
+
# Prompt the user for the configuration to use.
|
136
|
+
#
|
137
|
+
# Example:
|
138
|
+
# >> prompt_for_configuration
|
139
|
+
# => [#<Test:0x00000000000000>, { "username" => "test" }]
|
140
|
+
#
|
141
|
+
def prompt_for_configuration
|
142
|
+
# Print a short message to explain why we need the following information
|
143
|
+
prompt.ok("Pick the configuration you'd like to use:")
|
144
|
+
|
145
|
+
begin
|
146
|
+
# Load the actual configuration classes
|
147
|
+
configurations = RediPress::Configuration.all
|
148
|
+
rescue error
|
149
|
+
prompt.error("Unable to load one or more configurations.")
|
150
|
+
prompt.error("See the error report below for more information:")
|
151
|
+
prompt.error("--------------------------------------------------")
|
152
|
+
|
153
|
+
raise error
|
154
|
+
end
|
155
|
+
|
156
|
+
# Prompt for the configuration to use
|
157
|
+
configuration = prompt.select("Configuration:", configurations.values)
|
158
|
+
|
159
|
+
configuration
|
160
|
+
end
|
161
|
+
|
162
|
+
# Prompt the user for all options required by the specified configuration.
|
163
|
+
#
|
164
|
+
# Example:
|
165
|
+
# >> prompt_for_configuration_options(configuration)
|
166
|
+
# => { "username" => "test" }
|
167
|
+
#
|
168
|
+
def prompt_for_configuration_options(configuration)
|
169
|
+
return nil unless configuration.parameters && configuration.parameters.count > 0
|
170
|
+
|
171
|
+
# Print a short message to explain why we need the following information
|
172
|
+
prompt.ok("These options are required by the configuration you chose:")
|
173
|
+
|
174
|
+
# Create an empty hash to store the configuration's options
|
175
|
+
options = Hash.new
|
176
|
+
|
177
|
+
# Loop through each parameter on the configuration
|
178
|
+
configuration.parameters.each do |parameter|
|
179
|
+
if :text == parameter.type
|
180
|
+
options[parameter.slug] = prompt.ask("#{parameter.name}:") do |q|
|
181
|
+
q.required(true)
|
182
|
+
q.validate(parameter.validation) if parameter.validation
|
183
|
+
q.default(parameter.default) if parameter.default
|
184
|
+
end
|
185
|
+
elsif :yesno == parameter.type
|
186
|
+
options[parameter.slug] = prompt.yes?("#{parameter.name}:")
|
187
|
+
elsif :select == parameter.type
|
188
|
+
options[parameter.slug] = prompt.select("#{parameter.name}:", parameter.options)
|
189
|
+
elsif :multi_select == parameter.type
|
190
|
+
options[parameter.slug] = prompt.multi_select("#{parameter.name}:", parameter.options)
|
191
|
+
else
|
192
|
+
prompt.error("The configuration requested an unknown parameter type.")
|
193
|
+
exit 1
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
options
|
198
|
+
end
|
199
|
+
|
200
|
+
# Define taskless functionality
|
201
|
+
no_tasks do
|
202
|
+
# Include the helper functionality
|
203
|
+
include RediPress::CLI::Helper
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
unless defined?(RediPress) && RediPress.cli?
|
2
|
+
raise "You can't load this file. Please load the redipress/cli file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
module RediPress
|
6
|
+
module CLI
|
7
|
+
module Helper
|
8
|
+
# Prepare before running a task
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
# >> prepare
|
12
|
+
# => nil
|
13
|
+
#
|
14
|
+
def prepare
|
15
|
+
# Load all ssh keys
|
16
|
+
RediPress::SSHKeys.load_ssh_keys
|
17
|
+
|
18
|
+
# Set the SSH Kit output verbosity to debug if verbose is enabled
|
19
|
+
SSHKit.config.output_verbosity = Logger::DEBUG if options[:verbose]
|
20
|
+
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
# Show a spinner while the block equates to true
|
25
|
+
#
|
26
|
+
# Example:
|
27
|
+
# >> spin_while("Doing something") { true }
|
28
|
+
# => nil
|
29
|
+
#
|
30
|
+
def spin_while(message, &block)
|
31
|
+
return nil unless block_given?
|
32
|
+
|
33
|
+
spinner = TTY::Spinner.new("#{message} ", format: :spin_1)
|
34
|
+
|
35
|
+
while yield do
|
36
|
+
spinner.spin
|
37
|
+
sleep(0.1)
|
38
|
+
end
|
39
|
+
|
40
|
+
spinner.stop("\u2713\n\n")
|
41
|
+
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Print a new line
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# >> new_line
|
49
|
+
# => "\n"
|
50
|
+
#
|
51
|
+
def new_line
|
52
|
+
puts ""
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get a prompt
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
# >> prompt
|
59
|
+
# => #<TTY::Prompt:0x00000000000000>
|
60
|
+
#
|
61
|
+
def prompt
|
62
|
+
@prompt ||= TTY::Prompt.new
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'yaml'
|
3
|
+
require 'securerandom'
|
4
|
+
require 'tty-prompt'
|
5
|
+
require 'tty-table'
|
6
|
+
require 'tty-spinner'
|
7
|
+
require 'sshkey'
|
8
|
+
|
9
|
+
REDIPRESS_CLI=true
|
10
|
+
|
11
|
+
require 'redipress'
|
12
|
+
require 'redipress/cli/helper'
|
13
|
+
require 'redipress/cli/configurations'
|
14
|
+
|
15
|
+
module RediPress
|
16
|
+
module CLI
|
17
|
+
class Main < Thor
|
18
|
+
# Whether or not to use verbose logging
|
19
|
+
class_option :verbose, type: :boolean
|
20
|
+
|
21
|
+
# Add the configurations subcommand
|
22
|
+
desc "configurations SUBCOMMAND ...ARGS", "Tools for working with configurations"
|
23
|
+
subcommand "configurations", RediPress::CLI::Configurations
|
24
|
+
|
25
|
+
# Set the default task to configurations
|
26
|
+
default_task :configurations
|
27
|
+
|
28
|
+
# Define taskless functionality
|
29
|
+
no_tasks do
|
30
|
+
# Include the helper functionality
|
31
|
+
include RediPress::CLI::Helper
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
unless defined?(RediPress)
|
2
|
+
raise "You can't load this file. Please load the redipress file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'sshkit'
|
6
|
+
require 'sshkit/dsl'
|
7
|
+
|
8
|
+
module RediPress
|
9
|
+
module Configuration
|
10
|
+
# This class is the basis of a configuration
|
11
|
+
#
|
12
|
+
class Base
|
13
|
+
# Add class level functionality
|
14
|
+
#
|
15
|
+
class << self
|
16
|
+
# Set a name for the configuration
|
17
|
+
#
|
18
|
+
# Arguments:
|
19
|
+
# name: (String)
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# >> class Test < RediPress::Configuration
|
23
|
+
# >> name "Test"
|
24
|
+
# >> end
|
25
|
+
#
|
26
|
+
def name(name = nil)
|
27
|
+
name.nil? ? @name : @name = name
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add a parameter
|
31
|
+
#
|
32
|
+
# Arguments:
|
33
|
+
# slug: (String)
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
# >> class Test < RediPress::Configuration
|
37
|
+
# >> parameter :username do
|
38
|
+
# >> name 'Username'
|
39
|
+
# >> validation /^[a-z]{4,}$/
|
40
|
+
# >> end
|
41
|
+
# >> end
|
42
|
+
#
|
43
|
+
def parameter(slug = nil, &block)
|
44
|
+
@parameters ||= []
|
45
|
+
|
46
|
+
return @parameters if slug.nil?
|
47
|
+
|
48
|
+
parameter = RediPress::Parameter.new(slug)
|
49
|
+
parameter.instance_eval(&block) if block_given?
|
50
|
+
|
51
|
+
@parameters << parameter
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the name of the configuration
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
# >> configuration.name
|
59
|
+
# => "Test"
|
60
|
+
#
|
61
|
+
def name
|
62
|
+
self.class.name
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get the parameters for the configuration
|
66
|
+
#
|
67
|
+
# Example:
|
68
|
+
# >> configuration.parameters
|
69
|
+
# => nil
|
70
|
+
#
|
71
|
+
def parameters
|
72
|
+
self.class.parameter
|
73
|
+
end
|
74
|
+
|
75
|
+
# Convert the class to a string
|
76
|
+
#
|
77
|
+
# Example:
|
78
|
+
# >> configuration.to_s
|
79
|
+
# => 'Test'
|
80
|
+
#
|
81
|
+
def to_s
|
82
|
+
name
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
# Check if the configuration is compatible with the server
|
88
|
+
#
|
89
|
+
# Arguments:
|
90
|
+
# host: (SSHKit::Host)
|
91
|
+
# options: (Hash)
|
92
|
+
#
|
93
|
+
# Example:
|
94
|
+
# >> configuration.compatible?(host, options)
|
95
|
+
# => true
|
96
|
+
#
|
97
|
+
def compatible?(host, options)
|
98
|
+
true
|
99
|
+
end
|
100
|
+
|
101
|
+
# Configure the server
|
102
|
+
# This method should return a hash (either empty or with info to display) on
|
103
|
+
# success and nil if an error occurs.
|
104
|
+
#
|
105
|
+
# Arguments:
|
106
|
+
# host: (SSHKit::Host)
|
107
|
+
# options: (Hash)
|
108
|
+
#
|
109
|
+
# Example:
|
110
|
+
# >> configuration.configure(host, options)
|
111
|
+
# => {}
|
112
|
+
#
|
113
|
+
def configure(host, options)
|
114
|
+
raise RediPress::SetupNotImplemented
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
unless defined?(RediPress)
|
2
|
+
raise "You can't load this file. Please load the redipress file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'sshkit'
|
6
|
+
require 'sshkit/dsl'
|
7
|
+
|
8
|
+
module RediPress
|
9
|
+
# This module contains all configurations
|
10
|
+
#
|
11
|
+
module Configuration
|
12
|
+
# Returns a Hash of all available configurations.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# >> RediPress::Configuration.all
|
16
|
+
# => { "test" => #<RediPress::Configuration::Test:0x00000000000000> }
|
17
|
+
#
|
18
|
+
def self.all
|
19
|
+
instances_of(*slugs)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a Hash containing instances of the specified configurations.
|
23
|
+
#
|
24
|
+
# Arguments:
|
25
|
+
# slugs: (Splat)
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# >> RediPress::Configuration.instances_of :test
|
29
|
+
# => { "test" => #<RediPress::Configuration::Test:0x00000000000000> }
|
30
|
+
#
|
31
|
+
def self.instances_of(*slugs)
|
32
|
+
slugs.sort_by! { |slug| slug }
|
33
|
+
slugs.map! { |slug| [slug.to_s, instance_of(slug.to_s)] }
|
34
|
+
|
35
|
+
Hash[*slugs.flatten]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns an instance of the specified configuration.
|
39
|
+
#
|
40
|
+
# Arguments:
|
41
|
+
# slug: (Symbol|String)
|
42
|
+
#
|
43
|
+
# Example:
|
44
|
+
# >> RediPress::Configuration.instance_of :test
|
45
|
+
# => #<RediPress::Configuration::Test:0x00000000000000>
|
46
|
+
#
|
47
|
+
def self.instance_of(slug)
|
48
|
+
load_by_slugs(slug)
|
49
|
+
|
50
|
+
klass = class_for(slug)
|
51
|
+
klass = Object.const_get(klass)
|
52
|
+
klass.new
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the class name for a configuration.
|
56
|
+
#
|
57
|
+
# Arguments:
|
58
|
+
# slug: (Symbol|String)
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
# >> RediPress::Configuration.class_for :test
|
62
|
+
# => "RediPress::Configuration::Test"
|
63
|
+
#
|
64
|
+
def self.class_for(slug)
|
65
|
+
klass = slug.to_s.capitalize
|
66
|
+
klass.gsub!(/[-_.\s]([a-zA-Z0-9])/) { $1.upcase }
|
67
|
+
klass.tr!("+", "x")
|
68
|
+
"RediPress::Configuration::#{klass}"
|
69
|
+
end
|
70
|
+
|
71
|
+
# Load a configuration from the configurations directory.
|
72
|
+
#
|
73
|
+
# Arguments:
|
74
|
+
# slugs: (Splat)
|
75
|
+
#
|
76
|
+
# Example:
|
77
|
+
# >> RediPress::Configuration.load_by_slugs :test
|
78
|
+
# => nil
|
79
|
+
#
|
80
|
+
def self.load_by_slugs(*slugs)
|
81
|
+
ensure_available!(*slugs)
|
82
|
+
|
83
|
+
slugs.each do |slug|
|
84
|
+
require gems[slug.to_s]
|
85
|
+
end
|
86
|
+
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
# Ensure that the specified configurations are available.
|
91
|
+
#
|
92
|
+
# Arguments:
|
93
|
+
# slugs: (Splat)
|
94
|
+
#
|
95
|
+
# Example:
|
96
|
+
# >> RediPress::Configuration.ensure_available! :test
|
97
|
+
# => nil
|
98
|
+
#
|
99
|
+
# Raises:
|
100
|
+
# RediPress::ConfigurationNotAvailable: If one or more of the specified configurations are not available.
|
101
|
+
#
|
102
|
+
def self.ensure_available!(*slugs)
|
103
|
+
slugs.each do |slug|
|
104
|
+
raise RediPress::ConfigurationNotAvailable.new(slug) unless available?(slug)
|
105
|
+
end
|
106
|
+
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
110
|
+
# Check that the specified configurations are available.
|
111
|
+
#
|
112
|
+
# Arguments:
|
113
|
+
# slugs: (Splat)
|
114
|
+
#
|
115
|
+
# Example:
|
116
|
+
# >> RediPress::Configuration.available? :test
|
117
|
+
# => true
|
118
|
+
#
|
119
|
+
def self.available?(*slugs)
|
120
|
+
slugs.each do |slug|
|
121
|
+
return false unless self.slugs.include?(slug.to_s)
|
122
|
+
end
|
123
|
+
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get the slugs of all configurations
|
128
|
+
#
|
129
|
+
# Example:
|
130
|
+
# >> RediPress::Configuration.slugs
|
131
|
+
# => ["test"]
|
132
|
+
#
|
133
|
+
def self.slugs
|
134
|
+
gems.keys
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get the all gems related to configurations
|
138
|
+
#
|
139
|
+
# Example:
|
140
|
+
# >> RediPress::Configuration.gems
|
141
|
+
# => { "test" => "redipress/configuration/test" }
|
142
|
+
#
|
143
|
+
def self.gems
|
144
|
+
all_gems = Gem::Specification.select do |gem|
|
145
|
+
gem.name.downcase =~ /^redipress-configuration-[a-z0-9-]+$/
|
146
|
+
end
|
147
|
+
|
148
|
+
gems = Hash.new
|
149
|
+
|
150
|
+
all_gems.each do |gem|
|
151
|
+
slug = gem.name.downcase.sub("redipress-configuration-", "").gsub("-", "_")
|
152
|
+
|
153
|
+
gems[slug] = "redipress/configuration/#{slug}"
|
154
|
+
end
|
155
|
+
|
156
|
+
gems
|
157
|
+
end
|
158
|
+
|
159
|
+
# Set the paths to the private SSH Keys to use
|
160
|
+
#
|
161
|
+
# Arguments:
|
162
|
+
# keys: (Splat)
|
163
|
+
#
|
164
|
+
# Example:
|
165
|
+
# >> RediPress::Configuration.set_ssh_key_paths('/home/rediwebhosting/.ssh/id_rsa')
|
166
|
+
# => nil
|
167
|
+
#
|
168
|
+
def self.set_ssh_key_paths(*keys)
|
169
|
+
SSHKit::Backend::Netssh.configure do |ssh|
|
170
|
+
ssh.connection_timeout = 60
|
171
|
+
ssh.ssh_options = {
|
172
|
+
keys: keys,
|
173
|
+
forward_agent: false,
|
174
|
+
auth_methods: %w(publickey password)
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Mark certain class methods as private
|
180
|
+
private_class_method :load_by_slugs
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
unless defined?(RediPress)
|
2
|
+
raise "You can't load this file. Please load the redipress file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
module RediPress
|
6
|
+
# A RuntimeError subclass for when a configuration is not available.
|
7
|
+
#
|
8
|
+
class ConfigurationNotAvailable < RuntimeError
|
9
|
+
attr_reader :slug
|
10
|
+
|
11
|
+
def initialize(slug)
|
12
|
+
@slug = slug
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"The configuration '#{@slug}' is not available."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# A RuntimeError subclass for when the setup function has not been implemented.
|
21
|
+
#
|
22
|
+
class SetupNotImplemented < RuntimeError
|
23
|
+
def to_s
|
24
|
+
"The setup function has not been implemented by the configuration."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
unless defined?(RediPress)
|
2
|
+
raise "You can't load this file. Please load the redipress file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
module RediPress
|
6
|
+
# This class holds all paramaters required by a configuration.
|
7
|
+
#
|
8
|
+
class Parameter
|
9
|
+
attr_reader :slug, :options
|
10
|
+
|
11
|
+
# Setup an instance of the parameters class.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# >> RediPress::Parameter.new(:username)
|
15
|
+
# => #<RediPress::Parameter:0x00000000000000 @slug=:username, @name="username">
|
16
|
+
#
|
17
|
+
def initialize(slug)
|
18
|
+
@slug = slug
|
19
|
+
@name = slug.to_s
|
20
|
+
@type = :text
|
21
|
+
end
|
22
|
+
|
23
|
+
# Set the name of the parameter
|
24
|
+
#
|
25
|
+
# Example:
|
26
|
+
# >> parameter.name("Username")
|
27
|
+
# => "Username"
|
28
|
+
#
|
29
|
+
def name(name = nil)
|
30
|
+
name.nil? ? @name : @name = name
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set the type of the parameter
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
# >> parameter.type(:text)
|
37
|
+
# => :text
|
38
|
+
#
|
39
|
+
def type(type = nil)
|
40
|
+
type.nil? ? @type : @type = type
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set the default value
|
44
|
+
#
|
45
|
+
# Available With types:
|
46
|
+
# :text
|
47
|
+
#
|
48
|
+
# Example:
|
49
|
+
# >> parameter.default('rediwebhosting')
|
50
|
+
# => "rediwebhosting"
|
51
|
+
#
|
52
|
+
def default(default = nil)
|
53
|
+
default.nil? ? @default : @default = default
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set the validation regex
|
57
|
+
#
|
58
|
+
# Available With types:
|
59
|
+
# :text
|
60
|
+
#
|
61
|
+
# Example:
|
62
|
+
# >> parameter.validation(/^[a-z]{4,}$/)
|
63
|
+
# => /^[a-z]{4,}$/
|
64
|
+
#
|
65
|
+
def validation(validation = nil)
|
66
|
+
validation.nil? ? @validation : @validation = validation
|
67
|
+
end
|
68
|
+
|
69
|
+
# Add an option
|
70
|
+
#
|
71
|
+
# Available With types:
|
72
|
+
# :select
|
73
|
+
# :multi_select
|
74
|
+
#
|
75
|
+
# Example:
|
76
|
+
# >> parameter.option('rediweb')
|
77
|
+
# => nil
|
78
|
+
# >> parameter.option('rediwebhosting')
|
79
|
+
# => nil
|
80
|
+
#
|
81
|
+
def option(option)
|
82
|
+
@options ||= []
|
83
|
+
@options << option
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
unless defined?(RediPress)
|
2
|
+
raise "You can't load this file. Please load the redipress file instead."
|
3
|
+
end
|
4
|
+
|
5
|
+
module RediPress
|
6
|
+
# This class contains stuff related to SSH Keys
|
7
|
+
#
|
8
|
+
class SSHKeys
|
9
|
+
# Load all SSH Keys stored in the user's SSH directory
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
# >> RediPress::SSHKeys.load_ssh_keys
|
13
|
+
# => nil
|
14
|
+
#
|
15
|
+
def self.load_ssh_keys
|
16
|
+
# Get the path to the user's personal SSH directory
|
17
|
+
ssh_directory = File.join(Dir.home, ".ssh")
|
18
|
+
|
19
|
+
# Return unless the SSH directory exists
|
20
|
+
return nil unless File.directory?(ssh_directory)
|
21
|
+
|
22
|
+
# Get the paths of all SSH Keys
|
23
|
+
ssh_keys = Dir.glob(File.join(Dir.home, ".ssh", "*.pub")).map do |key|
|
24
|
+
File.join(File.dirname(key), File.basename(key, ".pub"))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Adjust the configuration options for SSH Kit
|
28
|
+
SSHKit::Backend::Netssh.configure do |ssh|
|
29
|
+
# Set the SSH options
|
30
|
+
ssh.ssh_options = {
|
31
|
+
# Set the SSH Keys to use when attempting to login to the remote host
|
32
|
+
keys: ssh_keys,
|
33
|
+
|
34
|
+
# Set the authentication methods
|
35
|
+
auth_methods: %w(publickey password)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/redipress.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# This module contains the core RediPress functionality
|
2
|
+
module RediPress
|
3
|
+
# This will use the ruby 'require' method to require
|
4
|
+
# all files bundled with this gem.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# >> RediPress.require_tree!
|
8
|
+
# => nil
|
9
|
+
#
|
10
|
+
def self.require_tree!
|
11
|
+
require 'redipress/variables'
|
12
|
+
require 'redipress/errors'
|
13
|
+
require 'redipress/configuration'
|
14
|
+
require 'redipress/configuration/base'
|
15
|
+
require 'redipress/parameter'
|
16
|
+
require 'redipress/ssh'
|
17
|
+
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns a boolean value of whether or not
|
22
|
+
# we are running by the CLI.
|
23
|
+
#
|
24
|
+
def self.cli?
|
25
|
+
defined?(REDIPRESS_CLI) && true == REDIPRESS_CLI
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
RediPress.require_tree!
|
data/redipress.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
lib_path = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
3
|
+
require 'redipress/variables'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'redipress'
|
7
|
+
s.version = RediPress::VERSION
|
8
|
+
s.date = Time.now.strftime("%Y-%m-%d")
|
9
|
+
s.summary = 'RediPress'
|
10
|
+
s.description = 'Automated server configuration!'
|
11
|
+
s.authors = ['Rediweb Hosting']
|
12
|
+
s.email = 'support@rediwebhosting.uk'
|
13
|
+
s.files = `git ls-files`.split($/)
|
14
|
+
s.homepage = 'https://rediwebhosting.uk/premium-wordpress-hosting'
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
s.executables << 'redipress'
|
18
|
+
|
19
|
+
s.add_runtime_dependency "thor", "~> 0.19", "0.19.1"
|
20
|
+
s.add_runtime_dependency "tty-prompt", "~> 0.3", "0.3.0"
|
21
|
+
s.add_runtime_dependency "tty-table", "~> 0.4", "0.4.0"
|
22
|
+
s.add_runtime_dependency "tty-spinner", "~> 0.1", "0.1.0"
|
23
|
+
s.add_runtime_dependency "sshkey", "~> 1.8", "1.8.0"
|
24
|
+
s.add_runtime_dependency "sshkit", "~> 1.8", "1.8.1"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redipress
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rediweb Hosting
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.19'
|
20
|
+
- - '='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.19.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.19'
|
30
|
+
- - '='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.19.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: tty-prompt
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ~>
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.3'
|
40
|
+
- - '='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.3.0
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.3'
|
50
|
+
- - '='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.3.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: tty-table
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.4'
|
60
|
+
- - '='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.4.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.4'
|
70
|
+
- - '='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 0.4.0
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: tty-spinner
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ~>
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0.1'
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.1.0
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.1'
|
90
|
+
- - '='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 0.1.0
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: sshkey
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ~>
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '1.8'
|
100
|
+
- - '='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.8.0
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.8'
|
110
|
+
- - '='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 1.8.0
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: sshkit
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ~>
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.8'
|
120
|
+
- - '='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.8.1
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ~>
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.8'
|
130
|
+
- - '='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.8.1
|
133
|
+
description: Automated server configuration!
|
134
|
+
email: support@rediwebhosting.uk
|
135
|
+
executables:
|
136
|
+
- redipress
|
137
|
+
extensions: []
|
138
|
+
extra_rdoc_files: []
|
139
|
+
files:
|
140
|
+
- .gitignore
|
141
|
+
- LICENSE
|
142
|
+
- bin/redipress
|
143
|
+
- lib/redipress.rb
|
144
|
+
- lib/redipress/cli.rb
|
145
|
+
- lib/redipress/cli/configurations.rb
|
146
|
+
- lib/redipress/cli/helper.rb
|
147
|
+
- lib/redipress/configuration.rb
|
148
|
+
- lib/redipress/configuration/base.rb
|
149
|
+
- lib/redipress/errors.rb
|
150
|
+
- lib/redipress/parameter.rb
|
151
|
+
- lib/redipress/ssh.rb
|
152
|
+
- lib/redipress/variables.rb
|
153
|
+
- redipress.gemspec
|
154
|
+
homepage: https://rediwebhosting.uk/premium-wordpress-hosting
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
metadata: {}
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
require_paths:
|
161
|
+
- lib
|
162
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 2.5.1
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: RediPress
|
178
|
+
test_files: []
|