sct 0.1.17 → 0.1.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sct +3 -4
  3. data/{.DS_Store → cluster/lib/.DS_Store} +0 -0
  4. data/cluster/lib/cluster.rb +6 -0
  5. data/cluster/lib/cluster/commands_generator.rb +109 -0
  6. data/cluster/lib/cluster/module.rb +7 -0
  7. data/{lib/sct → cluster/lib/cluster/resources}/.DS_Store +0 -0
  8. data/{resources → cluster/lib/cluster/resources}/corefile.yml +0 -0
  9. data/{lib/sct/commands/cluster.rb → cluster/lib/cluster/runner.rb} +160 -145
  10. data/{lib → sct/lib}/.DS_Store +0 -0
  11. data/sct/lib/sct.rb +17 -0
  12. data/sct/lib/sct/.DS_Store +0 -0
  13. data/sct/lib/sct/cli_tools_distributor.rb +50 -0
  14. data/{lib → sct/lib}/sct/command.rb +0 -0
  15. data/{lib → sct/lib}/sct/commands/hostfile.rb +7 -23
  16. data/sct/lib/sct/commands/init.rb +37 -0
  17. data/sct/lib/sct/commands/mysqlproxy.rb +20 -0
  18. data/sct/lib/sct/commands_generator.rb +56 -0
  19. data/sct/lib/sct/tools.rb +12 -0
  20. data/sct/lib/sct/version.rb +3 -0
  21. data/sct_core/lib/.DS_Store +0 -0
  22. data/sct_core/lib/sct_core.rb +14 -0
  23. data/sct_core/lib/sct_core/.DS_Store +0 -0
  24. data/sct_core/lib/sct_core/command_executor.rb +104 -0
  25. data/{lib/sct → sct_core/lib/sct_core}/config.rb +3 -3
  26. data/sct_core/lib/sct_core/core_ext/string.rb +9 -0
  27. data/{lib/sct/setup/helpers.rb → sct_core/lib/sct_core/helper.rb} +2 -2
  28. data/sct_core/lib/sct_core/module.rb +0 -0
  29. data/sct_core/lib/sct_core/sct_pty.rb +53 -0
  30. data/sct_core/lib/sct_core/ui/implementations/shell.rb +129 -0
  31. data/sct_core/lib/sct_core/ui/interface.rb +120 -0
  32. data/sct_core/lib/sct_core/ui/ui.rb +26 -0
  33. data/sct_core/lib/sct_core/update_checker/update_checker.rb +76 -0
  34. data/shell/README.md +0 -0
  35. data/shell/lib/shell.rb +3 -0
  36. data/{lib/sct → shell/lib/shell}/ClassLevelInheritableAttributes.rb +0 -0
  37. data/shell/lib/shell/commands_generator.rb +14 -0
  38. data/{lib/sct → shell/lib/shell}/docker/composer.rb +4 -3
  39. data/{lib/sct → shell/lib/shell}/docker/docker.rb +7 -10
  40. data/{lib/sct → shell/lib/shell}/docker/php.rb +3 -2
  41. data/{lib/sct → shell/lib/shell}/docker/yarn.rb +4 -3
  42. data/shell/lib/shell/module.rb +9 -0
  43. data/shell/lib/shell/runner.rb +34 -0
  44. data/shell/lib/shell/tools.rb +7 -0
  45. metadata +126 -53
  46. data/.gitignore +0 -12
  47. data/.gitlab/merge_request_templates/DefinitionOfDone.md +0 -14
  48. data/.rspec +0 -3
  49. data/.travis.yml +0 -7
  50. data/CODE_OF_CONDUCT.md +0 -74
  51. data/Gemfile +0 -4
  52. data/Gemfile.lock +0 -44
  53. data/LICENSE.txt +0 -21
  54. data/README.md +0 -134
  55. data/Rakefile +0 -6
  56. data/lib/sct.rb +0 -61
  57. data/lib/sct/command_interface.rb +0 -18
  58. data/lib/sct/command_option.rb +0 -14
  59. data/lib/sct/commands/composer.rb +0 -29
  60. data/lib/sct/commands/init.rb +0 -51
  61. data/lib/sct/commands/mysqlproxy.rb +0 -38
  62. data/lib/sct/commands/php.rb +0 -37
  63. data/lib/sct/commands/yarn.rb +0 -26
  64. data/lib/sct/version.rb +0 -3
  65. data/sct.gemspec +0 -40
File without changes
@@ -0,0 +1,17 @@
1
+ require 'sct_core'
2
+
3
+ require 'sct/version'
4
+ require 'sct/tools'
5
+
6
+ module Sct
7
+
8
+ Helper = SctCore::Helper
9
+ UI = SctCore::UI
10
+
11
+ class << self
12
+ def load_actions
13
+ # we should load actions here. Something like:
14
+ # Sct::Actions.load_default_actions
15
+ end
16
+ end
17
+ end
Binary file
@@ -0,0 +1,50 @@
1
+ module Sct
2
+ class CLIToolsDistributor
3
+ class << self
4
+ def take_off
5
+ require 'sct'
6
+
7
+ tool_name = ARGV.first ? ARGV.first.downcase : nil
8
+
9
+ if tool_name && Sct::TOOLS.include?(tool_name.to_sym)
10
+ # Triggering a specific tool
11
+
12
+ require tool_name
13
+ begin
14
+ # First, remove the tool's name from the arguments
15
+ # Since it will be parsed by the `commander` at a later point
16
+ # and it must not contain the binary name
17
+ ARGV.shift
18
+
19
+ # Import the CommandsGenerator class, which is used to parse
20
+ # the user input
21
+ require File.join(tool_name, "commands_generator")
22
+
23
+ # Call the tool's CommandsGenerator class and let it do its thing
24
+ commands_generator = Object.const_get(tool_name.sct_module)::CommandsGenerator
25
+ rescue LoadError
26
+ # This will only happen if the tool we call here, doesn't provide
27
+ # a CommandsGenerator class yet
28
+ # When we launch this feature, this should never be the case
29
+ abort("#{tool_name} can't be called via `sct #{tool_name}`, run '#{tool_name}' directly instead".red)
30
+ end
31
+
32
+ # Some of the tools might use other actions so need to load all
33
+ # actions before we start the tool generator here in the future
34
+ Sct.load_actions
35
+
36
+ # trigger start on tool
37
+ commands_generator.start
38
+
39
+ else
40
+ require "sct/commands_generator"
41
+ Sct::CommandsGenerator.start
42
+ end
43
+ ensure
44
+ SctCore::UpdateChecker.start_looking_for_update('sct')
45
+ SctCore::UpdateChecker.show_update_status('sct', Sct::VERSION)
46
+ end
47
+
48
+ end
49
+ end
50
+ end
File without changes
@@ -1,28 +1,14 @@
1
- require 'sct/command_interface'
2
-
3
1
  module Sct
4
2
  class HostfileCommand
5
3
 
6
- IS_PUBLIC_COMMAND = true
7
- SYNTAX = 'sct hostfile'
8
- SUMMARY = 'adds the ingress url to the users hostfile'
9
- DESCRIPTION = ""
10
- EXAMPLE = "sct hostfile"
11
- EXAMPLE_DESCRIPTION = ""
12
-
13
- OPTIONS = []
14
-
15
- def self.options
16
- end
17
-
18
4
  def execute(args, options)
19
- return puts "SCT has not been initialized. Run 'sct init' first.".red unless Sct::Config.exists
20
-
21
- return puts "This command needs to be run with sudo.".red unless Sct::Helpers.isSudo
5
+ return UI.error("SCT has not been initialized. Run 'sct init' first.") unless SctCore::Config.exists
22
6
 
23
- return unless Sct::Helpers.ingressAddress
7
+ return UI.error("This command needs to be run with sudo.") unless SctCore::Helper.isSudo
24
8
 
25
- ingressAddress = Sct::Helpers.ingressAddress
9
+ return unless SctCore::Helper.ingressAddress
10
+
11
+ ingressAddress = SctCore::Helper.ingressAddress
26
12
 
27
13
  entries = [
28
14
  {
@@ -52,7 +38,7 @@ module Sct
52
38
  else
53
39
  hosts_paths = ["/etc/hosts"]
54
40
 
55
- if Sct::Helpers.operatingSystem == Sct::Helpers::WINDOWS
41
+ if SctCore::Helper.operatingSystem == SctCore::Helper::WINDOWS
56
42
  hosts_paths << "/mnt/c/Windows/System32/drivers/etc/hosts"
57
43
  end
58
44
  end
@@ -72,13 +58,11 @@ module Sct
72
58
 
73
59
  File.write hosts_path, lines.join
74
60
 
75
- puts "Patched #{hosts_path} with #{ingressAddress}".green
61
+ UI.success("Patched #{hosts_path} with #{ingressAddress}")
76
62
  end
77
63
 
78
64
  end
79
65
 
80
- implements CommandInterface
81
-
82
66
  end
83
67
 
84
68
  end
@@ -0,0 +1,37 @@
1
+ require 'sct_core/ui/ui'
2
+ require 'sct_core/config'
3
+
4
+ module Sct
5
+
6
+ class InitCommand
7
+
8
+ def execute(args, options)
9
+
10
+ dir = SctCore::Config.dir
11
+
12
+ cli = HighLine.new
13
+
14
+ email = cli.ask("What is your email address?") { |q|
15
+ q.validate = URI::MailTo::EMAIL_REGEXP
16
+ }
17
+
18
+ cloud_proxy_path = cli.ask("What is the path of your cloud proxy json credentials?") { |q|
19
+ q.default = "~/.config/gcloud/application_default_credentials.json"
20
+ }
21
+
22
+ contents = ""
23
+ contents << "email=#{email}\n"
24
+ contents << "cloud-proxy-path=#{File.expand_path(cloud_proxy_path)}\n"
25
+
26
+ if !File.directory?(dir)
27
+ FileUtils.mkdir_p(dir)
28
+ end
29
+
30
+ File.write(SctCore::Config.path, contents)
31
+
32
+ puts "Generated config file at #{SctCore::Config.path}"
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,20 @@
1
+ module Sct
2
+ class MysqlproxyCommand
3
+
4
+ DEFAULT_SECRET_NAME = "gcloud-credentials"
5
+
6
+ def execute(args, options)
7
+
8
+ return UI.error("SCT has not been initialized. Run 'sct init' first.") unless SctCore::Config.exists
9
+
10
+ path = SctCore::Config.get('cloud-proxy-path')
11
+
12
+ system("kubectl delete secret gcloud-credentials")
13
+ system("kubectl create secret generic gcloud-credentials --from-file=#{path}")
14
+
15
+ UI.success("Authenticated with secret-name: '#{DEFAULT_SECRET_NAME}'")
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,56 @@
1
+ require 'commander'
2
+ require 'sct/command'
3
+
4
+ module Sct
5
+ class CommandsGenerator
6
+ include Commander::Methods
7
+
8
+ def self.start
9
+ self.new.run
10
+ end
11
+
12
+ def run
13
+ program :name, 'sct'
14
+ program :version, Sct::VERSION
15
+ program :summary, 'CLI helper tool for local SCT development'
16
+ program :description, 'SCT is a CLI tool for developers using the Visma Continuous Deployment Model in conjunction with the Google Cloud Platform (GCP). It provides multiple command to set up and maintain a kubernetes cluster on a machine for local development'
17
+
18
+ global_option('--verbose') { $verbose = true }
19
+
20
+ command :init do |c|
21
+ c.syntax = 'sct init'
22
+ c.description = 'setup sct'
23
+
24
+ c.action do |args, options|
25
+ UI.important("setting up sct")
26
+ Sct::InitCommand.new.execute(args, options)
27
+ end
28
+ end
29
+
30
+ command :hostfile do |c|
31
+
32
+ c.syntax = 'sct hostfile'
33
+ c.description = 'patch hostfile with kubernetes ip'
34
+
35
+ c.action do |args, options|
36
+ UI.important("Trying to patch hostfile")
37
+ Sct::HostfileCommand.new.execute(args, options)
38
+ end
39
+ end
40
+
41
+ command :'mysql proxy' do |c|
42
+
43
+ c.syntax = 'sct mysql proxy'
44
+ c.description = 'setup google mysql proxy'
45
+
46
+ c.action do |args, options|
47
+ UI.important("Trying to setup mysql proxy")
48
+ Sct::MysqlproxyCommand.new.execute(args, options)
49
+ end
50
+
51
+ end
52
+
53
+ run!
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,12 @@
1
+ module Sct
2
+ TOOLS = [
3
+ :sct,
4
+ :shell,
5
+ :cluster
6
+ ]
7
+
8
+ # a list of all the config files we currently expect
9
+ TOOL_CONFIG_FILES = [
10
+
11
+ ]
12
+ end
@@ -0,0 +1,3 @@
1
+ module Sct
2
+ VERSION = "0.1.22"
3
+ end
Binary file
@@ -0,0 +1,14 @@
1
+ require_relative 'sct_core/core_ext/string'
2
+ require_relative 'sct_core/config'
3
+ require_relative 'sct_core/helper'
4
+ require_relative 'sct_core/update_checker/update_checker'
5
+ require_relative 'sct_core/command_executor'
6
+ require_relative 'sct_core/ui/ui'
7
+ require_relative 'sct_core/sct_pty'
8
+
9
+ # third party code
10
+ require 'colored'
11
+ require 'commander'
12
+
13
+ # these need to be imported after commander
14
+ require_relative 'sct_core/module'
@@ -0,0 +1,104 @@
1
+ require_relative 'ui/ui'
2
+ require_relative 'sct_pty'
3
+
4
+ module SctCore
5
+ # Executes commands and takes care of error handling and more
6
+ class CommandExecutor
7
+ class << self
8
+ # Cross-platform way of finding an executable in the $PATH. Respects the $PATHEXT, which lists
9
+ # valid file extensions for executables on Windows.
10
+ #
11
+ # which('ruby') #=> /usr/bin/ruby
12
+ #
13
+ # Derived from https://stackoverflow.com/a/5471032/3005
14
+ def which(cmd)
15
+ # PATHEXT contains the list of file extensions that Windows considers executable, semicolon separated.
16
+ # e.g. ".COM;.EXE;.BAT;.CMD"
17
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : []
18
+ exts << '' # Always have an empty string (= no file extension)
19
+
20
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
21
+ exts.each do |ext|
22
+ cmd_path = File.join(path, "#{cmd}#{ext}")
23
+ return cmd_path if Helper.executable?(cmd_path)
24
+ end
25
+ end
26
+
27
+ return nil
28
+ end
29
+
30
+ # @param command [String] The command to be executed
31
+ # @param print_all [Boolean] Do we want to print out the command output while running?
32
+ # @param print_command [Boolean] Should we print the command that's being executed
33
+ # @param error [Block] A block that's called if an error occurs
34
+ # @param prefix [Array] An array containing a prefix + block which might get applied to the output
35
+ # @param loading [String] A loading string that is shown before the first output
36
+ # @param suppress_output [Boolean] Should we print the command's output?
37
+ # @return [String] All the output as string
38
+ def execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, loading: nil, suppress_output: false)
39
+ print_all = true if $verbose
40
+ prefix ||= {}
41
+
42
+ output = []
43
+ command = command.join(" ") if command.kind_of?(Array)
44
+ command = self.escape_characters_in_string(command)
45
+ UI.command(command) if print_command
46
+
47
+ if print_all && loading # this is only used to show the "Loading text"...
48
+ UI.command_output(loading)
49
+ end
50
+
51
+ begin
52
+ status = SctCore::SctPty.spawn(command) do |command_stdout, command_stdin, pid|
53
+ command_stdout.each do |l|
54
+ line = l.chomp
55
+ output << line
56
+
57
+ next unless print_all
58
+
59
+ # Prefix the current line with a string
60
+ prefix.each do |element|
61
+ line = element[:prefix] + line if element[:block] && element[:block].call(line)
62
+ end
63
+
64
+ UI.command_output(line) unless suppress_output
65
+ end
66
+ end
67
+ rescue => ex
68
+ # SctPty adds exit_status on to StandardError so every error will have a status code
69
+ status = ex.exit_status
70
+
71
+ # This could happen when the environment is wrong:
72
+ # > invalid byte sequence in US-ASCII (ArgumentError)
73
+ output << ex.to_s
74
+ o = output.join("\n")
75
+ puts(o)
76
+ if error
77
+ error.call(o, nil)
78
+ else
79
+ raise ex
80
+ end
81
+ end
82
+
83
+ # Exit status for build command, should be 0 if build succeeded
84
+ if status != 0
85
+ o = output.join("\n")
86
+ puts(o) unless suppress_output # the user has the right to see the raw output
87
+ UI.error("Exit status: #{status}")
88
+ if error
89
+ error.call(o, status)
90
+ else
91
+ UI.user_error!("Exit status: #{status}")
92
+ end
93
+ end
94
+
95
+ return output.join("\n")
96
+ end
97
+
98
+ def escape_characters_in_string(string)
99
+ pattern = /(\'|\"|\.|\*|\/|\-|\\|\)|\$|\+|\(|\^|\?|\!|\~|\`)/
100
+ string.gsub(pattern){|match|"\\" + match}
101
+ end
102
+ end
103
+ end
104
+ end
@@ -1,8 +1,8 @@
1
- module Sct
1
+ module SctCore
2
2
  class Config
3
3
 
4
4
  def self.dir
5
- return "#{Sct::Helpers.homePath}/.config/sct"
5
+ return "#{SctCore::Helper.homePath}/.config/sct"
6
6
  end
7
7
 
8
8
  def self.path
@@ -30,7 +30,7 @@ module Sct
30
30
 
31
31
  contents = File.read(self.path)
32
32
 
33
- return Sct::Helpers.to_hash(contents)
33
+ return SctCore::Helper.to_hash(contents)
34
34
  end
35
35
  end
36
36
  end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def sct_class
3
+ split('_').collect!(&:capitalize).join
4
+ end
5
+
6
+ def sct_module
7
+ self.sct_class
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
- module Sct
2
- class Helpers
1
+ module SctCore
2
+ class Helper
3
3
 
4
4
  WINDOWS = "Windows"
5
5
  MAC_OS = "MacOS"
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