sct 0.1.18 → 0.1.23
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 +4 -4
- data/bin/sct +3 -4
- data/{.DS_Store → cluster/lib/.DS_Store} +0 -0
- data/cluster/lib/cluster.rb +6 -0
- data/cluster/lib/cluster/commands_generator.rb +109 -0
- data/cluster/lib/cluster/module.rb +7 -0
- data/{lib/sct → cluster/lib/cluster/resources}/.DS_Store +0 -0
- data/{resources → cluster/lib/cluster/resources}/corefile.yml +0 -0
- data/{lib/sct/commands/cluster.rb → cluster/lib/cluster/runner.rb} +137 -132
- data/{lib → sct/lib}/.DS_Store +0 -0
- data/sct/lib/sct.rb +17 -0
- data/sct/lib/sct/.DS_Store +0 -0
- data/sct/lib/sct/cli_tools_distributor.rb +50 -0
- data/{lib → sct/lib}/sct/command.rb +0 -0
- data/{lib → sct/lib}/sct/commands/hostfile.rb +7 -23
- data/sct/lib/sct/commands/init.rb +37 -0
- data/sct/lib/sct/commands/mysqlproxy.rb +20 -0
- data/sct/lib/sct/commands_generator.rb +56 -0
- data/sct/lib/sct/tools.rb +12 -0
- data/sct/lib/sct/version.rb +3 -0
- data/sct_core/lib/.DS_Store +0 -0
- data/sct_core/lib/sct_core.rb +14 -0
- data/sct_core/lib/sct_core/.DS_Store +0 -0
- data/sct_core/lib/sct_core/command_executor.rb +104 -0
- data/{lib/sct → sct_core/lib/sct_core}/config.rb +3 -3
- data/sct_core/lib/sct_core/core_ext/string.rb +9 -0
- data/{lib/sct/setup/helpers.rb → sct_core/lib/sct_core/helper.rb} +10 -2
- data/sct_core/lib/sct_core/module.rb +0 -0
- data/sct_core/lib/sct_core/sct_pty.rb +53 -0
- data/sct_core/lib/sct_core/ui/implementations/shell.rb +129 -0
- data/sct_core/lib/sct_core/ui/interface.rb +120 -0
- data/sct_core/lib/sct_core/ui/ui.rb +26 -0
- data/sct_core/lib/sct_core/update_checker/update_checker.rb +76 -0
- data/shell/README.md +0 -0
- data/shell/lib/shell.rb +3 -0
- data/{lib/sct → shell/lib/shell}/ClassLevelInheritableAttributes.rb +0 -0
- data/shell/lib/shell/commands_generator.rb +14 -0
- data/shell/lib/shell/docker/composer.rb +16 -0
- data/{lib/sct → shell/lib/shell}/docker/docker.rb +54 -38
- data/shell/lib/shell/docker/php.rb +52 -0
- data/shell/lib/shell/docker/yarn.rb +17 -0
- data/shell/lib/shell/module.rb +9 -0
- data/shell/lib/shell/runner.rb +34 -0
- data/shell/lib/shell/tools.rb +7 -0
- metadata +126 -53
- data/.gitignore +0 -12
- data/.gitlab/merge_request_templates/DefinitionOfDone.md +0 -14
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -48
- data/LICENSE.txt +0 -21
- data/README.md +0 -134
- data/Rakefile +0 -6
- data/lib/sct.rb +0 -61
- data/lib/sct/command_interface.rb +0 -18
- data/lib/sct/command_option.rb +0 -14
- data/lib/sct/commands/composer.rb +0 -29
- data/lib/sct/commands/init.rb +0 -51
- data/lib/sct/commands/mysqlproxy.rb +0 -38
- data/lib/sct/commands/php.rb +0 -37
- data/lib/sct/commands/yarn.rb +0 -26
- data/lib/sct/docker/composer.rb +0 -15
- data/lib/sct/docker/php.rb +0 -14
- data/lib/sct/docker/yarn.rb +0 -16
- data/lib/sct/version.rb +0 -3
- data/sct.gemspec +0 -40
File without changes
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class StandardError
|
2
|
+
def exit_status
|
3
|
+
return -1
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module SctCore
|
8
|
+
class SctPtyError < StandardError
|
9
|
+
attr_reader :exit_status
|
10
|
+
def initialize(e, exit_status)
|
11
|
+
super(e)
|
12
|
+
set_backtrace(e.backtrace) if e
|
13
|
+
@exit_status = exit_status
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class SctPty
|
18
|
+
def self.spawn(command)
|
19
|
+
require 'pty'
|
20
|
+
PTY.spawn(command) do |command_stdout, command_stdin, pid|
|
21
|
+
begin
|
22
|
+
yield(command_stdout, command_stdin, pid)
|
23
|
+
rescue Errno::EIO
|
24
|
+
# Exception ignored intentionally.
|
25
|
+
# https://stackoverflow.com/questions/10238298/ruby-on-linux-pty-goes-away-without-eof-raises-errnoeio
|
26
|
+
# This is expected on some linux systems, that indicates that the subcommand finished
|
27
|
+
# and we kept trying to read, ignore it
|
28
|
+
ensure
|
29
|
+
begin
|
30
|
+
Process.wait(pid)
|
31
|
+
rescue Errno::ECHILD, PTY::ChildExited
|
32
|
+
# The process might have exited.
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
$?.exitstatus
|
37
|
+
rescue LoadError
|
38
|
+
require 'open3'
|
39
|
+
Open3.popen2e(command) do |command_stdin, command_stdout, p| # note the inversion
|
40
|
+
yield(command_stdout, command_stdin, p.value.pid)
|
41
|
+
|
42
|
+
command_stdin.close
|
43
|
+
command_stdout.close
|
44
|
+
p.value.exitstatus
|
45
|
+
end
|
46
|
+
rescue StandardError => e
|
47
|
+
# Wrapping any error in SctPtyError to allow
|
48
|
+
# callers to see and use $?.exitstatus that
|
49
|
+
# would usually get returned
|
50
|
+
raise SctPtyError.new(e, $?.exitstatus)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require_relative '../interface'
|
2
|
+
|
3
|
+
module SctCore
|
4
|
+
# Shell is the terminal output of things
|
5
|
+
# For documentation for each of the methods open `interface.rb`
|
6
|
+
class Shell < Interface
|
7
|
+
require 'tty-screen'
|
8
|
+
|
9
|
+
def log
|
10
|
+
$stdout.sync = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def writeToUser(message)
|
14
|
+
puts message
|
15
|
+
end
|
16
|
+
|
17
|
+
def error(message)
|
18
|
+
writeToUser(message.to_s.red)
|
19
|
+
end
|
20
|
+
|
21
|
+
def important(message)
|
22
|
+
writeToUser(message.to_s.yellow)
|
23
|
+
end
|
24
|
+
|
25
|
+
def success(message)
|
26
|
+
writeToUser(message.to_s.green)
|
27
|
+
end
|
28
|
+
|
29
|
+
def message(message)
|
30
|
+
writeToUser(message.to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
def deprecated(message)
|
34
|
+
writeToUser(message.to_s.deprecated)
|
35
|
+
end
|
36
|
+
|
37
|
+
def command(message)
|
38
|
+
writeToUser("$ #{message}".cyan)
|
39
|
+
end
|
40
|
+
|
41
|
+
def command_output(message)
|
42
|
+
actual = (message.split("\r").last || "") # as clearing the line will remove the `>` and the time stamp
|
43
|
+
actual.split("\n").each do |msg|
|
44
|
+
# prefix = msg.include?("▸") ? "" : "▸ "
|
45
|
+
prefix = ""
|
46
|
+
writeToUser(prefix + "" + msg.magenta)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def verbose(message)
|
51
|
+
message.to_s if $verbose
|
52
|
+
end
|
53
|
+
|
54
|
+
def header(message)
|
55
|
+
format = format_string
|
56
|
+
if message.length + 8 < TTY::Screen.width - format.length
|
57
|
+
message = "--- #{message} ---"
|
58
|
+
i = message.length
|
59
|
+
else
|
60
|
+
i = TTY::Screen.width - format.length
|
61
|
+
end
|
62
|
+
success("-" * i)
|
63
|
+
success(message)
|
64
|
+
success("-" * i)
|
65
|
+
end
|
66
|
+
|
67
|
+
def content_error(content, error_line)
|
68
|
+
error_line = error_line.to_i
|
69
|
+
return unless error_line > 0
|
70
|
+
|
71
|
+
contents = content.split(/\r?\n/).map(&:chomp)
|
72
|
+
|
73
|
+
start_line = error_line - 2 < 1 ? 1 : error_line - 2
|
74
|
+
end_line = error_line + 2 < contents.length ? error_line + 2 : contents.length
|
75
|
+
|
76
|
+
Range.new(start_line, end_line).each do |line|
|
77
|
+
str = line == error_line ? " => " : " "
|
78
|
+
str << line.to_s.rjust(Math.log10(end_line) + 1)
|
79
|
+
str << ":\t#{contents[line - 1]}"
|
80
|
+
error(str)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
#####################################################
|
85
|
+
# @!group Errors: Inputs
|
86
|
+
#####################################################
|
87
|
+
|
88
|
+
def interactive?
|
89
|
+
interactive = true
|
90
|
+
interactive = false if $stdout.isatty == false
|
91
|
+
return interactive
|
92
|
+
end
|
93
|
+
|
94
|
+
def input(message)
|
95
|
+
verify_interactive!(message)
|
96
|
+
ask("#{format_string}#{message.to_s.yellow}").to_s.strip
|
97
|
+
end
|
98
|
+
|
99
|
+
def confirm(message)
|
100
|
+
verify_interactive!(message)
|
101
|
+
agree("#{format_string}#{message.to_s.yellow} (y/n)", true)
|
102
|
+
end
|
103
|
+
|
104
|
+
def select(message, options)
|
105
|
+
verify_interactive!(message)
|
106
|
+
|
107
|
+
important(message)
|
108
|
+
choose(*options)
|
109
|
+
end
|
110
|
+
|
111
|
+
def password(message)
|
112
|
+
verify_interactive!(message)
|
113
|
+
|
114
|
+
ask("#{format_string}#{message.to_s.yellow}") { |q| q.echo = "*" }
|
115
|
+
end
|
116
|
+
|
117
|
+
def user_error!(error_message, options = {})
|
118
|
+
writeToUser(error_message.yellow)
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def verify_interactive!(message)
|
124
|
+
return if interactive?
|
125
|
+
important(message)
|
126
|
+
crash!("Could not retrieve response as sct runs in non-interactive mode")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module SctCore
|
2
|
+
# Abstract super class
|
3
|
+
class Interface
|
4
|
+
#####################################################
|
5
|
+
# @!group Messaging: show text to the user
|
6
|
+
#####################################################
|
7
|
+
|
8
|
+
# Level Error: Can be used to show additional error
|
9
|
+
# information before actually raising an exception
|
10
|
+
# or can be used to just show an error from which
|
11
|
+
#
|
12
|
+
# By default those messages are shown in red
|
13
|
+
def error(_message)
|
14
|
+
not_implemented(__method__)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Level Important: Can be used to show warnings to the user
|
18
|
+
# not necessarily negative, but something the user should
|
19
|
+
# be aware of.
|
20
|
+
#
|
21
|
+
# By default those messages are shown in yellow
|
22
|
+
def important(_message)
|
23
|
+
not_implemented(__method__)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Level Success: Show that something was successful
|
27
|
+
#
|
28
|
+
# By default those messages are shown in green
|
29
|
+
def success(_message)
|
30
|
+
not_implemented(__method__)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Level Message: Show a neutral message to the user
|
34
|
+
#
|
35
|
+
# By default those messages shown in white/black
|
36
|
+
def message(_message)
|
37
|
+
not_implemented(__method__)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Level Deprecated: Show that a particular function is deprecated
|
41
|
+
#
|
42
|
+
# By default those messages shown in strong blue
|
43
|
+
def deprecated(_message)
|
44
|
+
not_implemented(__method__)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Level Command: Print out a terminal command that is being
|
48
|
+
# executed.
|
49
|
+
#
|
50
|
+
# By default those messages shown in cyan
|
51
|
+
def command(_message)
|
52
|
+
not_implemented(__method__)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Level Command Output: Print the output of a command with
|
56
|
+
# this method
|
57
|
+
#
|
58
|
+
# By default those messages shown in magenta
|
59
|
+
def command_output(_message)
|
60
|
+
not_implemented(__method__)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Level Verbose: Print out additional information for the
|
64
|
+
# users that are interested. Will only be printed when
|
65
|
+
#
|
66
|
+
# By default those messages are shown in white
|
67
|
+
def verbose(_message)
|
68
|
+
not_implemented(__method__)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Print a header = a text in a box
|
72
|
+
# use this if this message is really important
|
73
|
+
def header(_message)
|
74
|
+
not_implemented(__method__)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Print lines of content around specific line where
|
78
|
+
# failed to parse.
|
79
|
+
#
|
80
|
+
# This message will be shown as error
|
81
|
+
def content_error(content, error_line)
|
82
|
+
not_implemented(__method__)
|
83
|
+
end
|
84
|
+
|
85
|
+
#####################################################
|
86
|
+
# @!group Errors: Inputs
|
87
|
+
#####################################################
|
88
|
+
|
89
|
+
# Is is possible to ask the user questions?
|
90
|
+
def interactive?
|
91
|
+
not_implemented(__method__)
|
92
|
+
end
|
93
|
+
|
94
|
+
# get a standard text input (single line)
|
95
|
+
def input(_message)
|
96
|
+
not_implemented(__method__)
|
97
|
+
end
|
98
|
+
|
99
|
+
# A simple yes or no question
|
100
|
+
def confirm(_message)
|
101
|
+
not_implemented(__method__)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Let the user select one out of x items
|
105
|
+
# return value is the value of the option the user chose
|
106
|
+
def select(_message, _options)
|
107
|
+
not_implemented(__method__)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Password input for the user, text field shouldn't show
|
111
|
+
# plain text
|
112
|
+
def password(_message)
|
113
|
+
not_implemented(__method__)
|
114
|
+
end
|
115
|
+
|
116
|
+
def user_error!(error_message, options = {})
|
117
|
+
not_implemented(__method__)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SctCore
|
2
|
+
class UI
|
3
|
+
class << self
|
4
|
+
attr_accessor(:ui_object)
|
5
|
+
|
6
|
+
def ui_object
|
7
|
+
require_relative 'implementations/shell'
|
8
|
+
@ui_object ||= Shell.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method_sym, *args, &_block)
|
12
|
+
# not using `responds` because we don't care about methods like .to_s and so on
|
13
|
+
require_relative 'interface'
|
14
|
+
interface_methods = SctCore::Interface.instance_methods - Object.instance_methods
|
15
|
+
UI.user_error!("Unknown method '#{method_sym}', supported #{interface_methods}") unless interface_methods.include?(method_sym)
|
16
|
+
|
17
|
+
self.ui_object.send(method_sym, *args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Import all available implementations
|
24
|
+
Dir[File.dirname(__FILE__) + '/implementations/*.rb'].each do |file|
|
25
|
+
require_relative file
|
26
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
require 'excon'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module SctCore
|
6
|
+
class UpdateChecker
|
7
|
+
def self.start_looking_for_update(gem_name)
|
8
|
+
begin
|
9
|
+
server_results[gem_name] = fetch_latest(gem_name)
|
10
|
+
rescue => e
|
11
|
+
# ignore possible exceptions
|
12
|
+
UI.verbose("error occured fetching latest version #{e.message}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.server_results
|
17
|
+
@results ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.update_available?(gem_name, current_version)
|
21
|
+
latest = server_results[gem_name]
|
22
|
+
return (latest and Gem::Version.new(latest) > Gem::Version.new(current_version))
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.show_update_status(gem_name, current_version)
|
26
|
+
if update_available?(gem_name, current_version)
|
27
|
+
show_update_message(gem_name, current_version)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.show_update_message(gem_name, current_version)
|
32
|
+
available = server_results[gem_name]
|
33
|
+
puts("")
|
34
|
+
UI.important('#######################################################################')
|
35
|
+
if available
|
36
|
+
UI.important("# #{gem_name} #{available} is available. You are on #{current_version}.")
|
37
|
+
else
|
38
|
+
UI.important("# An update for #{gem_name} is available. You are on #{current_version}.")
|
39
|
+
end
|
40
|
+
UI.important("# You should use the latest version.")
|
41
|
+
UI.important("# Please update using `#{self.update_command(gem_name: gem_name)}`.")
|
42
|
+
|
43
|
+
UI.important('#######################################################################')
|
44
|
+
UI.important("# Run `sudo gem cleanup` from time to time to speed up sct.")
|
45
|
+
|
46
|
+
UI.important('#######################################################################')
|
47
|
+
|
48
|
+
ensure_rubygems_source
|
49
|
+
end
|
50
|
+
|
51
|
+
# Check if RubyGems is set as a gem source
|
52
|
+
# on some machines that might not be the case
|
53
|
+
# and then users can't find the update when
|
54
|
+
# running the specified command
|
55
|
+
def self.ensure_rubygems_source
|
56
|
+
return if `gem sources`.include?("https://rubygems.org")
|
57
|
+
puts("")
|
58
|
+
UI.error("RubyGems is not listed as your Gem source")
|
59
|
+
UI.error("You can run `gem sources` to see all your sources")
|
60
|
+
UI.error("Please run the following command to fix this:")
|
61
|
+
UI.command("gem sources --add https://rubygems.org")
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.update_command(gem_name: "sct")
|
65
|
+
"sudo gem install #{gem_name.downcase}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.fetch_latest(gem_name)
|
69
|
+
JSON.parse(Excon.get(generate_fetch_url(gem_name)).body)["version"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.generate_fetch_url(gem_name)
|
73
|
+
"https://rubygems.org/api/v1/gems/#{gem_name}.json"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/shell/README.md
ADDED
File without changes
|
data/shell/lib/shell.rb
ADDED
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "sct_core"
|
2
|
+
require_relative "docker"
|
3
|
+
|
4
|
+
module Shell
|
5
|
+
class Composer < Docker
|
6
|
+
|
7
|
+
# Configure the Yarn command
|
8
|
+
def self.config
|
9
|
+
self.set_image("eu.gcr.io/dev-pasc-vcdm/helpers-composer:latest", true)
|
10
|
+
self.set_pwd_as_volume("/app")
|
11
|
+
self.add_volume(SctCore::Helper.convertWSLToWindowsPath("#{SctCore::Helper.windowsHomePath || SctCore::Helper.homePath}/.composer") , "/tmp")
|
12
|
+
self.set_current_user_and_group()
|
13
|
+
self.set_entrypoint("composer")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|