docker-cli 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,203 @@
1
+
2
+ require 'securerandom'
3
+ require 'tty/prompt'
4
+ require_relative '../dockerfile'
5
+
6
+ module Docker
7
+ module Cli
8
+ module Operations
9
+
10
+ # Normal run by finding Dockerfile
11
+ # By default is interactive
12
+ class Run
13
+
14
+ def initialize
15
+ @pmt = TTY::Prompt.new
16
+ end
17
+
18
+ def run
19
+
20
+ # find dockerfile to build an image
21
+ df = Dockerfile.find_available
22
+ raise NoDockerfileFound, "No Dockerfile found. Please create one and re-run this operation" if df.length == 0
23
+
24
+ if df.length > 1
25
+ @selDf = @pmt.select(" Please select one of the Dockerfile to execute : ") do |m|
26
+ df.each do |f|
27
+ m.choice f, f
28
+ end
29
+ end
30
+ else
31
+ @selDf = df.first
32
+ end
33
+
34
+ @mount_root = @pmt.ask(" Please provide a root for folder mount into Docker env : ", default: "/opt", required: true)
35
+
36
+ df = Dockerfile.new(@selDf)
37
+ # parameter pass in is to build the template
38
+ # e.g. docker_root is to build the dup_gem_bundler_env directive
39
+ ndf = df.render_dockerfile(docker_root: @mount_root)
40
+
41
+ @dev_gems = {}
42
+ devGems = Cli.find_dev_gems
43
+ if devGems.length > 0
44
+ devGems.each do |k,v|
45
+ @dev_gems[v] = File.join(@mount_root, File.basename(v))
46
+ end
47
+ end
48
+
49
+ dfName = @pmt.ask(" Please provide the new name for the generated Dockerfile : ", required: true, default: "Dockerfile.docli")
50
+ dfPath = File.join(Dir.getwd, dfName)
51
+ File.open(dfPath,"w") do |f|
52
+ f.write ndf
53
+ end
54
+
55
+ if Dockerfile.run_before?(dfPath)
56
+ proceed = @pmt.yes?(" Given dockerfile '#{@selDf}' seems already run before. Do you want to use existing image instead? ")
57
+ if proceed
58
+ img = Dockerfile.images(dfPath)
59
+ if img.length > 1
60
+ @selImg = @pmt.select(" There are multiple images being run from the same Dockerfile. Please select one of them : ") do |m|
61
+ img.each do |i|
62
+ m.choice i, i
63
+ end
64
+ end
65
+ elsif img.length > 0
66
+ @selImg = img.first
67
+ end
68
+
69
+ else
70
+ # not using existing image.. built one
71
+ #@df, @selImg = build_image_from_dockerfile_bin(ndf)
72
+ @selImg = build_image_from_dockerfile(dfPath, dfName)
73
+ end
74
+
75
+ else
76
+ #logger.debug "Dockerfile not being run before"
77
+ #@df, @selImg = build_image_from_dockerfile_bin(ndf) # =>
78
+ @selImg = build_image_from_dockerfile(dfPath, dfName)
79
+ end
80
+
81
+ logger.debug "selected image : #{@selImg}"
82
+
83
+ di = DockerImage.new(@selImg)
84
+ if di.has_containers?
85
+ if di.containers.length > 1
86
+ @selCont = @pmt.select(" Please select one of the container to run : ") do |m|
87
+
88
+ di.containers.each do |c|
89
+ m.choice c.name_for_display, c
90
+ end
91
+
92
+ m.choice "New container", :new
93
+
94
+ end
95
+
96
+ else
97
+ @selCont = di.containers.first
98
+ end
99
+
100
+ end # has_containers?
101
+
102
+
103
+ case @selCont
104
+ when :new, nil
105
+ @selCont = @pmt.ask(" Please provide a new container name : ", required: true, default: "#{File.basename(Dir.getwd)}_#{SecureRandom.hex(4)}")
106
+
107
+ cp = ContainerProfile.new
108
+ if devGems.length > 0
109
+ devGems.each do |name, path|
110
+ cp.add_mount_point(path, File.join(@mount_root, name))
111
+ end
112
+ end
113
+
114
+ # add current dir as mount point
115
+ cp.add_mount_point(Dir.getwd, File.join(@mount_root, File.basename(Dir.getwd)))
116
+
117
+ while true
118
+ STDOUT.puts "\n\n Mount points : \n"
119
+ ctn = 1
120
+ cp.mount_points.each do |local, docker|
121
+ STDOUT.puts " #{ctn}. #{local} ==> #{docker}"
122
+ end
123
+ apath = @pmt.ask("\n Please provide full path to mount in the docker (just enter if done) : ")
124
+ break if is_empty?(apath)
125
+
126
+ if File.exist?(apath)
127
+ mpath = @pmt.ask(" Please provide mount point inside the docker : ", default: File.dirname(apath))
128
+ cp.add_mount_point(mpath, File.join(@mount_root, File.basename(mpath)))
129
+ else
130
+ STDERR.puts "Given path '#{apath}' doesn't exist. Please try again."
131
+ end
132
+ end
133
+
134
+ cmd = @pmt.ask(" What command should be inside the docker? : ", required: true, default: "/bin/bash" )
135
+ cp.run_command = cmd
136
+ cp.image_name = @selImg
137
+
138
+ dc = DockerContainer.new(@selCont)
139
+ dc.create(cp)
140
+ DockerRunLog.instance.log(@selImg, @selCont)
141
+
142
+ else
143
+
144
+ #cmd = @pmt.ask(" What command should be inside the docker? : ", required: true, default: "/bin/bash" )
145
+ dc = DockerContainer.new(@selCont.name)
146
+ dc.start
147
+ dc.attach
148
+ #dc.run(cmd)
149
+
150
+ end
151
+
152
+
153
+ end
154
+
155
+ def build_image_from_dockerfile(df, dfName)
156
+
157
+ iName = File.basename(Dir.getwd)
158
+ name = @pmt.ask(" Please provide an image name for Dockerfile '#{dfName}' : ", required: true, default: "#{iName}_image")
159
+ ctx = @pmt.ask(" Context to run to the dockerfile? ", required: true, default: ".")
160
+
161
+ DockerImage.build(name, dfName ,ctx)
162
+ DockerRunLog.instance.log_dockerfile_image(df, name)
163
+
164
+ name
165
+
166
+ end
167
+
168
+ #def build_image_from_dockerfile_bin(df)
169
+ # #raise NoDockerfileFound, "Given Dockerfile to build image '#{df}' does not exist" if not File.exist?(df)
170
+
171
+ # dfName = @pmt.ask(" Please provide the new name for the generated Dockerfile : ", required: true, default: "Dockerfile.docli")
172
+ # path = File.join(Dir.getwd, dfName)
173
+ # dfName = File.basename(path)
174
+ # if not_empty?(df)
175
+ # File.open(path,"w") do |f|
176
+ # f.write df
177
+ # end
178
+ # end
179
+ #
180
+ # iName = File.basename(Dir.getwd)
181
+ # name = @pmt.ask(" Please provide an image name for Dockerfile '#{dfName}' : ", required: true, default: "#{iName}_image")
182
+ # ctx = @pmt.ask(" Context to run to the dockerfile? ", required: true, default: ".")
183
+
184
+ # DockerImage.build(name, dfName ,ctx)
185
+ # DockerRunLog.instance.log_dockerfile_image(df, name)
186
+
187
+ # [dfName, name]
188
+ #end
189
+
190
+
191
+ private
192
+ def logger
193
+ if @_logger.nil?
194
+ @_logger = Cli.logger(:run_ops)
195
+ end
196
+ @_logger
197
+ end
198
+
199
+ end
200
+
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,67 @@
1
+
2
+ module Docker
3
+ module Cli
4
+ module Operations
5
+ class RunDel
6
+ include TR::ArgUtils
7
+
8
+ arg_spec do
9
+
10
+ callback :pre_processing do |a|
11
+ capture_image(a)
12
+ end
13
+
14
+ opt "-c", "Command to be executed inside the Docker" do |a|
15
+ capture_command(a)
16
+ end
17
+
18
+ opt "-u", "Run as current user for Docker" do
19
+ set_use_same_user(true)
20
+ end
21
+
22
+ callback :post_processing do |a|
23
+ run
24
+ end
25
+
26
+ end
27
+
28
+ def initialize
29
+ @match_user = false
30
+ # leave this blank as the image may have already
31
+ # set an entry program
32
+ @cmd = ""
33
+ end
34
+
35
+ def capture_image(a)
36
+ @dimage = a.first
37
+ [true, a[1..-1]]
38
+ end
39
+
40
+ def capture_command(a)
41
+ @cmd = a
42
+ end
43
+
44
+ def set_use_same_user(bol)
45
+ @match_user = bol
46
+ end
47
+
48
+ # Just run with image name on command line
49
+ def run
50
+
51
+ mountLocal = Dir.getwd
52
+ mountDocker = "/opt/#{File.basename(Dir.getwd)}"
53
+ if TR::RTUtils.on_linux? and @match_user
54
+ # This approach has user match with local user but no name on the docker
55
+ # workable not nice only
56
+ Docker::Cli::DockerContainer.create_container(@dimage, interactive: true, tty: true, command: @cmd, mount: { mountLocal => mountDocker }, match_user: @match_user, del: true)
57
+ else
58
+ # Apparently on Mac and Windows, the user issue is not an issue
59
+ Docker::Cli::DockerContainer.create_container(@dimage, interactive: true, tty: true, command: @cmd, mount: { mountLocal => mountDocker }, del: true)
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,118 @@
1
+
2
+ require 'tty/prompt'
3
+ require_relative '../docker_run_log'
4
+
5
+ module Docker
6
+ module Cli
7
+ module Operations
8
+ class RunKeep
9
+ include TR::ArgUtils
10
+
11
+ arg_spec do
12
+
13
+ callback :pre_processing do |a|
14
+ capture_image(a)
15
+ end
16
+
17
+ opt "-c", "Command to be executed inside the Docker" do |a|
18
+ capture_command(a)
19
+ end
20
+
21
+ opt "-u", "Run as current user for Docker" do
22
+ set_use_same_user(true)
23
+ end
24
+
25
+ opt "-n", "Name of the container" do |a|
26
+ capture_container_name(a)
27
+ end
28
+
29
+ callback :post_processing do |a|
30
+ run
31
+ end
32
+
33
+ end
34
+
35
+ def initialize
36
+ @match_user = false #TR::RTUtils.on_linux?
37
+ # leave this blank as the image may have already
38
+ # set an entry program
39
+ @cmd = ""
40
+ end
41
+
42
+ def capture_image(a)
43
+ @fullArgv = a
44
+ @dimage = a.first
45
+ [true, a[1..-1]]
46
+ end
47
+
48
+ def capture_command(a)
49
+ logger.debug "Capturing command : #{a}"
50
+ @cmd = a
51
+ end
52
+
53
+ def capture_container_name(a)
54
+ @contName = a
55
+ end
56
+
57
+ def set_use_same_user(bol)
58
+ @match_user = bol
59
+ end
60
+
61
+ # Just run with image name on command line
62
+ def run
63
+
64
+ if Docker::Cli::DockerRunLog.instance.has_existing_container?(@dimage)
65
+ pmt = TTY::Prompt.new
66
+ begin
67
+ eCont = pmt.select(" System found there were some container already exist on this image.\n Do you want to reuse the existing container? ") do |m|
68
+ DockerContainer.containers_of_image_from_history(@dimage).each do |c, name|
69
+ m.choice name, c
70
+ end
71
+ m.choice "Run new container", :new_cont
72
+ m.choice "Quit", :quit
73
+ end
74
+
75
+ case eCont
76
+ when :new_cont
77
+ run_new
78
+ when :quit
79
+ STDOUT.puts " Have a nice day "
80
+ else
81
+ cont = DockerContainer.new(eCont)
82
+ cont.start if not cont.is_running?
83
+ cont.attach
84
+ end
85
+ rescue TTY::Reader::InputInterrupt
86
+ end
87
+ else
88
+ run_new
89
+ end
90
+
91
+ end
92
+
93
+ private
94
+ def run_new
95
+ mountLocal = Dir.getwd
96
+ mountDocker = "/opt/#{File.basename(Dir.getwd)}"
97
+ contName = @contName || SecureRandom.hex(18)
98
+ if TR::RTUtils.on_linux? and @match_user
99
+ # This approach has user match with local user but no name on the docker
100
+ # workable not nice only
101
+ Docker::Cli::DockerContainer.create_container(@dimage, interactive: true, tty: true, command: @cmd, mount: { mountLocal => mountDocker }, match_user: @match_user, container_name: contName)
102
+ else
103
+ # Apparently on Mac and Windows, the user issue is not an issue
104
+ Docker::Cli::DockerContainer.create_container(@dimage, interactive: true, tty: true, command: @cmd, mount: { mountLocal => mountDocker }, container_name: contName)
105
+ end
106
+
107
+ Docker::Cli::DockerRunLog.instance.log(@dimage, contName, argv: @fullArgv)
108
+
109
+ end
110
+
111
+ def logger
112
+ Cli.logger(:rk)
113
+ end
114
+
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,39 @@
1
+
2
+ require 'etc'
3
+
4
+ module Docker
5
+ module Cli
6
+
7
+ module UserInfo
8
+ include TR::CondUtils
9
+
10
+ def self.user_info(login = nil)
11
+ login = Etc.getlogin if is_empty?(login)
12
+ res = { login: login }
13
+ begin
14
+ res[:uid] = Etc.getpwnam(login).uid
15
+ rescue Exception => ex
16
+ res[:uid] = nil
17
+ end
18
+ res
19
+ end
20
+
21
+ def self.group_info(login = nil)
22
+ login = Etc.getlogin if is_empty?(login)
23
+ res = { }
24
+ begin
25
+ gnm = Etc.getgrnam(login)
26
+ res[:group_name] = gnm.name
27
+ res[:gid] = gnm.gid
28
+ rescue Exception => ex
29
+ p ex
30
+ res[:group_name] = ""
31
+ res[:gid] = nil
32
+ end
33
+ res
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Docker
4
4
  module Cli
5
- VERSION = "0.3.1"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
data/lib/docker/cli.rb CHANGED
@@ -9,9 +9,21 @@ require_relative "cli/version"
9
9
  require_relative 'cli/command'
10
10
  require_relative 'cli/command_factory'
11
11
 
12
+ require_relative 'cli/docker_image'
13
+ require_relative 'cli/docker_container'
14
+ require_relative 'cli/docker_composer'
15
+
16
+ require_relative 'cli/dockerfile_template'
17
+
12
18
  module Docker
13
19
  module Cli
20
+ include TR::CondUtils
21
+
14
22
  class Error < StandardError; end
23
+ class RuntimeException < StandardError; end
24
+ class CommandFailed < StandardError; end
25
+ class IndefiniteOption < StandardError; end
26
+ class NoDockerfileFound < StandardError; end
15
27
  # Your code goes here...
16
28
 
17
29
  def Cli.docker_exe
@@ -25,5 +37,57 @@ module Docker
25
37
 
26
38
  end
27
39
 
40
+ def self.find_dev_gems
41
+ if @_devGems.nil?
42
+ @_devGems = {}
43
+ Bundler.load.dependencies.each do |d|
44
+ if not d.source.nil?
45
+ src = d.source
46
+ if src.path.to_s != "."
47
+ @_devGems[d.name] = src.path.expand_path.to_s
48
+ end
49
+ end
50
+ end
51
+ end
52
+ @_devGems
53
+ end
54
+
55
+ def self.digest_bin(bin)
56
+ OpenSSL::Digest.new("SHA3-256").hexdigest(bin)
57
+ end
58
+
59
+ def self.command_output(out)
60
+ if out.is_a?(Array)
61
+ out.each do |e|
62
+ STDOUT.puts " ## #{e}"
63
+ end
64
+ else
65
+ STDOUT.puts " ## #{out}"
66
+ end
67
+ end
68
+
69
+ def self.logger(tag = nil, &block)
70
+ if @_logger.nil?
71
+ @_logger = TeLogger::Tlogger.new(STDOUT)
72
+ end
73
+
74
+ if block
75
+ if not_empty?(tag)
76
+ @_logger.with_tag(tag, &block)
77
+ else
78
+ @_logger.with_tag(@_logger.tag, &block)
79
+ end
80
+ else
81
+ if is_empty?(tag)
82
+ @_logger.tag = :docker_cli
83
+ @_logger
84
+ else
85
+ # no block but tag is given? hmm
86
+ @_logger.tag = tag
87
+ @_logger
88
+ end
89
+ end
90
+ end
91
+
28
92
  end
29
93
  end
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+
3
+ # This is mostly a test. May not work across different variant of linux
4
+
5
+ groupadd -f -g <%= user_group_id %> <%= user_group_name %> && useradd -u <%= user_id %> -g <%= user_group_id %> -m <%= user_login %> && usermod -aG sudo <%= user_login %> && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
6
+
7
+ tail -f /dev/null
8
+ #while true; do sleep 1000; done
9
+ #exec /bin/bash
10
+
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-04 00:00:00.000000000 Z
11
+ date: 2023-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: toolrack
14
+ name: teLogger
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: teLogger
28
+ name: ptools
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: ptools
42
+ name: tty-command
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: tty-command
56
+ name: colorize
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: devops_assist
84
+ name: release-gem
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -94,15 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: toolrack
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.24.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 0.24.1
97
111
  description: ''
98
112
  email:
99
113
  - cameronian0@protonmail.com
100
- executables: []
114
+ executables:
115
+ - _gemdocker
116
+ - dc-update
117
+ - gemdocker
118
+ - gemdocker_test
101
119
  extensions: []
102
120
  extra_rdoc_files: []
103
121
  files:
104
122
  - ".release_history.yml"
105
123
  - ".rspec"
124
+ - ".rubocop.yml"
106
125
  - Dockerfile.cli.test
107
126
  - Gemfile
108
127
  - Gemfile.lock
@@ -111,16 +130,36 @@ files:
111
130
  - bin/console
112
131
  - bin/setup
113
132
  - docker-cli.gemspec
133
+ - exe/_gemdocker
134
+ - exe/dc-update
135
+ - exe/gemdocker
136
+ - exe/gemdocker_test
114
137
  - lib/docker/cli.rb
115
138
  - lib/docker/cli/command.rb
116
139
  - lib/docker/cli/command_factory.rb
117
140
  - lib/docker/cli/command_result.rb
141
+ - lib/docker/cli/docker_composer.rb
142
+ - lib/docker/cli/docker_container.rb
143
+ - lib/docker/cli/docker_image.rb
144
+ - lib/docker/cli/docker_run_log.rb
145
+ - lib/docker/cli/dockerfile.rb
146
+ - lib/docker/cli/dockerfile_template.rb
147
+ - lib/docker/cli/dockerfile_template/dup_gem_bundler_env.rb
148
+ - lib/docker/cli/dockerfile_template/match_user.rb
149
+ - lib/docker/cli/gem/bundler_helper.rb
150
+ - lib/docker/cli/image_helper.rb
151
+ - lib/docker/cli/operations/args_parser.rb
152
+ - lib/docker/cli/operations/run.rb
153
+ - lib/docker/cli/operations/run_del.rb
154
+ - lib/docker/cli/operations/run_keep.rb
155
+ - lib/docker/cli/user_info.rb
118
156
  - lib/docker/cli/version.rb
119
157
  - ruby-iterm2.sh
158
+ - scripts/create_user.sh.erb
120
159
  homepage: ''
121
160
  licenses: []
122
161
  metadata: {}
123
- post_install_message:
162
+ post_install_message:
124
163
  rdoc_options: []
125
164
  require_paths:
126
165
  - lib
@@ -135,8 +174,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
174
  - !ruby/object:Gem::Version
136
175
  version: '0'
137
176
  requirements: []
138
- rubygems_version: 3.4.10
139
- signing_key:
177
+ rubygems_version: 3.5.1
178
+ signing_key:
140
179
  specification_version: 4
141
180
  summary: ''
142
181
  test_files: []