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