Hitcher 0.1.0
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 +8 -0
- data/.travis.yml +6 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +44 -0
- data/Rakefile +12 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cspec +27 -0
- data/exe/hitcher +46 -0
- data/hitcher.gemspec +41 -0
- data/lib/hitcher.rb +41 -0
- data/lib/hitcher/command_runner.rb +50 -0
- data/lib/hitcher/config.rb +78 -0
- data/lib/hitcher/dsl.rb +108 -0
- data/lib/hitcher/global.rb +24 -0
- data/lib/hitcher/providers/docker/command_builder.rb +206 -0
- data/lib/hitcher/providers/docker/command_runner.rb +156 -0
- data/lib/hitcher/providers/docker/dsl.rb +229 -0
- data/lib/hitcher/providers/docker/template.rb +74 -0
- data/lib/hitcher/providers/docker/templates/Dockerfile.erb +6 -0
- data/lib/hitcher/providers/docker/templates/linux_mac/1.build.sh.erb +5 -0
- data/lib/hitcher/providers/docker/templates/linux_mac/2.run_container.sh.erb +6 -0
- data/lib/hitcher/providers/docker/templates/linux_mac/3.start_container.sh.erb +6 -0
- data/lib/hitcher/providers/docker/templates/linux_mac/4.container_prompt.sh.erb +6 -0
- data/lib/hitcher/providers/docker/templates/linux_mac/console.sh.erb +6 -0
- data/lib/hitcher/providers/docker/templates/linux_mac/start_new.sh.erb +6 -0
- data/lib/hitcher/run_ops.rb +129 -0
- data/lib/hitcher/terminal_utils.rb +22 -0
- data/lib/hitcher/user_prompt.rb +36 -0
- data/lib/hitcher/version.rb +3 -0
- metadata +187 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
require 'toolrack'
|
3
|
+
|
4
|
+
require 'erb'
|
5
|
+
require_relative 'command_builder'
|
6
|
+
|
7
|
+
module Hitcher
|
8
|
+
module Docker
|
9
|
+
class TemplateEngine
|
10
|
+
include Hitcher::Docker::CommandBuilder
|
11
|
+
|
12
|
+
def build_template(temp, val)
|
13
|
+
dest_root = Dir.getwd if val[:dest_root].nil? or val[:dest_root].empty?
|
14
|
+
|
15
|
+
case temp
|
16
|
+
when :dockerfile
|
17
|
+
path = File.join(File.dirname(__FILE__),"templates","Dockerfile.erb")
|
18
|
+
bind_template(path, File.join(dest_root,"Dockerfile"), val)
|
19
|
+
else
|
20
|
+
if Antrapol::ToolRack::RuntimeUtils.on_windows?
|
21
|
+
raise Hitcher::Error, "Not ready yet"
|
22
|
+
else
|
23
|
+
case temp
|
24
|
+
when :build_container, :build
|
25
|
+
path = File.join(File.dirname(__FILE__),"templates","linux_mac","1.build.sh.erb")
|
26
|
+
opts = {}
|
27
|
+
opts.merge!(val)
|
28
|
+
cmd = build_image(opts[:image_name], opts)
|
29
|
+
bind_template(path,File.join(dest_root,"1.build.sh"), { command: cmd })
|
30
|
+
|
31
|
+
|
32
|
+
when :run_container, :run
|
33
|
+
path = File.join(File.dirname(__FILE__),"templates","linux_mac","2.run_container.sh.erb")
|
34
|
+
opts = {}
|
35
|
+
opts.merge!(val)
|
36
|
+
cmd = run_container_from_image(opts[:image], opts)
|
37
|
+
bind_template(path,File.join(dest_root,"2.run_container.sh"), { command: cmd })
|
38
|
+
|
39
|
+
when :start_container, :start
|
40
|
+
path = File.join(File.dirname(__FILE__),"templates","linux_mac","3.start_container.sh.erb")
|
41
|
+
opts = {}
|
42
|
+
opts.merge!(val)
|
43
|
+
cmd = start_container(opts[:container_name], opts)
|
44
|
+
bind_template(path,File.join(dest_root,"3.start_container.sh"), { command: cmd })
|
45
|
+
|
46
|
+
when :container_prompt, :prompt
|
47
|
+
path = File.join(File.dirname(__FILE__),"templates","linux_mac","4.container_prompt.sh.erb")
|
48
|
+
opts = {}
|
49
|
+
opts.merge!(val)
|
50
|
+
cmd = container_prompt(opts[:container_name], opts)
|
51
|
+
bind_template(path,File.join(dest_root,"4.container_prompt.sh"), { command: cmd })
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def bind_template(source,dest, val)
|
59
|
+
File.open(source,"r") do |f|
|
60
|
+
cont = f.read
|
61
|
+
b = binding
|
62
|
+
val.each do |k,v|
|
63
|
+
b.local_variable_set(k,v)
|
64
|
+
end
|
65
|
+
|
66
|
+
File.open(dest,"w") do |ff|
|
67
|
+
ff.write ERB.new(cont).result(b)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end # TemplateEngine
|
73
|
+
end # Docker
|
74
|
+
end # Hitcher
|
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
require 'toolrack'
|
3
|
+
require_relative "user_prompt"
|
4
|
+
|
5
|
+
module Hitcher
|
6
|
+
module CliOps
|
7
|
+
module RunOps
|
8
|
+
include Hitcher::UserPrompt
|
9
|
+
include Antrapol::ToolRack::ConditionUtils
|
10
|
+
|
11
|
+
class RunCommandException < StandardError; end
|
12
|
+
|
13
|
+
#### HERE IS THE FINAL METHOD SIGNATURE
|
14
|
+
def run(inst, opts = { })
|
15
|
+
raise Exception, "Parameter must be a Hash object" if not opts.is_a?(Hash)
|
16
|
+
|
17
|
+
opts[:interactive] = inst.interactive_mode || true
|
18
|
+
opts[:tty] = inst.tty_mode || true
|
19
|
+
|
20
|
+
run_container(inst, opts)
|
21
|
+
end # run
|
22
|
+
|
23
|
+
def run_prompt(inst, opts = { })
|
24
|
+
|
25
|
+
raise Exception, "Parameter must be a Hash object" if not opts.is_a?(Hash)
|
26
|
+
|
27
|
+
op = { }
|
28
|
+
op.merge!(opts)
|
29
|
+
|
30
|
+
command = opts[:command] || "/bin/bash --login"
|
31
|
+
if command == "/bin/bash --login"
|
32
|
+
op[:interactive] = true
|
33
|
+
op[:tty] = true
|
34
|
+
else
|
35
|
+
op[:interactive] = inst.interactive_mode
|
36
|
+
op[:tty] = inst.tty_mode
|
37
|
+
end
|
38
|
+
|
39
|
+
run_container(inst, op)
|
40
|
+
|
41
|
+
end # run_prompt
|
42
|
+
|
43
|
+
def run_new_prompt(inst, opts = { })
|
44
|
+
raise Exception, "Parameter must be a Hash object" if not opts.is_a?(Hash)
|
45
|
+
#nname = "#{inst.cName}_#{Time.zone.local.strftime("%Y%m%d_%H%M%S_%L%N")}"
|
46
|
+
opt = { }
|
47
|
+
opt.merge!(opts)
|
48
|
+
opt[:new_instance] = true
|
49
|
+
|
50
|
+
command = opts[:command] || "/bin/bash --login"
|
51
|
+
if command == "/bin/bash --login"
|
52
|
+
opt[:interactive] = true
|
53
|
+
opt[:tty] = true
|
54
|
+
else
|
55
|
+
opt[:interactive] = inst.interactive_mode
|
56
|
+
opt[:tty] = inst.tty_mode
|
57
|
+
end
|
58
|
+
|
59
|
+
run_container(inst, opt)
|
60
|
+
end # run_new_prompt
|
61
|
+
|
62
|
+
#######
|
63
|
+
def run_container(inst, opts = { })
|
64
|
+
|
65
|
+
loop do
|
66
|
+
|
67
|
+
res, st, id = inst.command_executor.container_exist?(opts)
|
68
|
+
|
69
|
+
if res
|
70
|
+
case st
|
71
|
+
when :stopped
|
72
|
+
STDOUT.puts "Container '#{inst.cName}' has stopped! Reviving the container..."
|
73
|
+
if not_empty?(opts[:command])
|
74
|
+
rmech, rval = inst.command_executor.run_command_in_container(opts[:command], opts)
|
75
|
+
break
|
76
|
+
else
|
77
|
+
# assuming the container is launching up something via the CMD or ENTRYPOINT or else the
|
78
|
+
# container will die back after startup...
|
79
|
+
rcst, rcout, rcerr = inst.command_executor.start_container(opts)
|
80
|
+
if not rcst
|
81
|
+
raise RunCommandException, "Failed to run container '#{name}'. Error was : #{rcerr.join("\n")}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
when :running
|
85
|
+
STDOUT.puts "Container '#{inst.cName}' is running!"
|
86
|
+
# break the loop
|
87
|
+
rmech, rval = inst.command_executor.run_command_in_container(opts[:command], opts)
|
88
|
+
case rmech
|
89
|
+
when :file, :term
|
90
|
+
break
|
91
|
+
else
|
92
|
+
raise RunCommandException, "Run command in container failed with mechanism '#{rmech}'"
|
93
|
+
end
|
94
|
+
else
|
95
|
+
raise RunCommandException, "Container found but neither in running or stopped status"
|
96
|
+
end
|
97
|
+
else
|
98
|
+
# container not exist!
|
99
|
+
iest, ieout, ieerr = inst.command_executor.image_exist?(opts)
|
100
|
+
if not_empty?(ieout)
|
101
|
+
STDOUT.puts "Image '#{inst.image}' exist! Creating container..."
|
102
|
+
mech, v = inst.command_executor.create_container(opts)
|
103
|
+
case mech
|
104
|
+
when :file
|
105
|
+
break
|
106
|
+
when :term
|
107
|
+
break
|
108
|
+
else
|
109
|
+
raise RunCommandException, "Create container command failed with mechanism '#{mech}'"
|
110
|
+
end
|
111
|
+
else
|
112
|
+
STDOUT.puts "Image '#{inst.image}' does not exist! Proceed to build image..."
|
113
|
+
bist, biout, bierr = inst.command_executor.build_image(opts)
|
114
|
+
if is_empty?(bierr)
|
115
|
+
STDOUT.puts "Image '#{inst.image}' built!"
|
116
|
+
# should loop back to run the container
|
117
|
+
else
|
118
|
+
raise RunCommandException, "Build image command failed. Error was : #{bierr.join("\n")}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end # run_container
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
require 'ptools'
|
3
|
+
|
4
|
+
module Hitcher
|
5
|
+
module TerminalUtils
|
6
|
+
attr_reader :found
|
7
|
+
# since integration is with docker CLI, terminal become essential part of the workflow
|
8
|
+
KNOWN = ["gnome-terminal","konsole","cmd.exe","tilix","terminator"]
|
9
|
+
|
10
|
+
def detect_known_terminal
|
11
|
+
found = {}
|
12
|
+
KNOWN.each do |t|
|
13
|
+
ft = File.which(t)
|
14
|
+
if not ft.nil?
|
15
|
+
found[t] = ft
|
16
|
+
end
|
17
|
+
end
|
18
|
+
found
|
19
|
+
end # detect_known
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
require 'tty/prompt'
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
module Hitcher
|
6
|
+
module UserPrompt
|
7
|
+
|
8
|
+
def tty
|
9
|
+
if @tty.nil?
|
10
|
+
@tty = TTY::Prompt.new
|
11
|
+
end
|
12
|
+
@tty
|
13
|
+
end
|
14
|
+
|
15
|
+
def question(str)
|
16
|
+
STDOUT.print(str)
|
17
|
+
end
|
18
|
+
|
19
|
+
def notice(str)
|
20
|
+
STDOUT.print(str.light_blue)
|
21
|
+
end
|
22
|
+
|
23
|
+
def yes(str)
|
24
|
+
STDOUT.puts(str.green)
|
25
|
+
end
|
26
|
+
|
27
|
+
def no(str)
|
28
|
+
STDOUT.puts(str.yellow)
|
29
|
+
end
|
30
|
+
|
31
|
+
def fatal(str)
|
32
|
+
STDERR.puts(str.red)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Hitcher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Liaw
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-01-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: toolrack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.5.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.5.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tlogger
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.25'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.25'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tty-prompt
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: tty-command
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: colorize
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ptools
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: devops_helper
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: " "
|
126
|
+
email:
|
127
|
+
- chrisliaw@antrapol.com
|
128
|
+
executables:
|
129
|
+
- hitcher
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- ".travis.yml"
|
135
|
+
- Gemfile
|
136
|
+
- LICENSE.txt
|
137
|
+
- README.md
|
138
|
+
- Rakefile
|
139
|
+
- bin/console
|
140
|
+
- bin/setup
|
141
|
+
- cspec
|
142
|
+
- exe/hitcher
|
143
|
+
- hitcher.gemspec
|
144
|
+
- lib/hitcher.rb
|
145
|
+
- lib/hitcher/command_runner.rb
|
146
|
+
- lib/hitcher/config.rb
|
147
|
+
- lib/hitcher/dsl.rb
|
148
|
+
- lib/hitcher/global.rb
|
149
|
+
- lib/hitcher/providers/docker/command_builder.rb
|
150
|
+
- lib/hitcher/providers/docker/command_runner.rb
|
151
|
+
- lib/hitcher/providers/docker/dsl.rb
|
152
|
+
- lib/hitcher/providers/docker/template.rb
|
153
|
+
- lib/hitcher/providers/docker/templates/Dockerfile.erb
|
154
|
+
- lib/hitcher/providers/docker/templates/linux_mac/1.build.sh.erb
|
155
|
+
- lib/hitcher/providers/docker/templates/linux_mac/2.run_container.sh.erb
|
156
|
+
- lib/hitcher/providers/docker/templates/linux_mac/3.start_container.sh.erb
|
157
|
+
- lib/hitcher/providers/docker/templates/linux_mac/4.container_prompt.sh.erb
|
158
|
+
- lib/hitcher/providers/docker/templates/linux_mac/console.sh.erb
|
159
|
+
- lib/hitcher/providers/docker/templates/linux_mac/start_new.sh.erb
|
160
|
+
- lib/hitcher/run_ops.rb
|
161
|
+
- lib/hitcher/terminal_utils.rb
|
162
|
+
- lib/hitcher/user_prompt.rb
|
163
|
+
- lib/hitcher/version.rb
|
164
|
+
homepage: ''
|
165
|
+
licenses:
|
166
|
+
- MIT
|
167
|
+
metadata: {}
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 2.3.0
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubygems_version: 3.1.2
|
184
|
+
signing_key:
|
185
|
+
specification_version: 4
|
186
|
+
summary: ''
|
187
|
+
test_files: []
|