Hitcher 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,6 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ <% dockerfile.each do |d| %>
3
+ <%= d.strip if not d.strip.empty? %>
4
+ <% end %>
5
+
6
+
@@ -0,0 +1,5 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ #!/bin/sh
3
+
4
+ # read Dockerfile and build
5
+ <%= command %>
@@ -0,0 +1,6 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ #!/bin/sh
3
+
4
+ # run container
5
+ <%= command %>
6
+
@@ -0,0 +1,6 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ #!/bin/sh
3
+
4
+ # read start container
5
+ <%= command %>
6
+
@@ -0,0 +1,6 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ #!/bin/sh
3
+
4
+ # drop to prompt of running container
5
+ <%= command %>
6
+
@@ -0,0 +1,6 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ #!/bin/sh
3
+
4
+ # read link to existing running console
5
+ docker
6
+
@@ -0,0 +1,6 @@
1
+ <%#-*- coding: utf-8 -*-%>
2
+ #!/bin/sh
3
+
4
+ # start new instance of docker
5
+ docker run -it --name <%= name %> <%= mount %> <%= port %> <%= image_name %>
6
+
@@ -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
@@ -0,0 +1,3 @@
1
+ module Hitcher
2
+ VERSION = "0.1.0"
3
+ 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: []