sct 0.1.18 → 0.1.23
Sign up to get free protection for your applications and to get access to all the features.
- 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
|