dockerun 0.3.6 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -11
  3. data/Rakefile +0 -2
  4. data/Rakefile.bak +8 -0
  5. data/dockerspec.sample +107 -0
  6. data/{dockerun.gemspec → dockerun.gemspec.bak} +20 -22
  7. data/exe/dockerun +15 -115
  8. data/lib/dockerun/cli/command.rb +140 -0
  9. data/lib/dockerun/cli/command_factory.rb +316 -0
  10. data/lib/dockerun/cli/command_result.rb +67 -0
  11. data/lib/dockerun/cli/delete_container.rb +59 -0
  12. data/lib/dockerun/cli/delete_image.rb +103 -0
  13. data/lib/dockerun/cli/run.rb +40 -0
  14. data/lib/dockerun/cli/user_info.rb +39 -0
  15. data/lib/dockerun/cli_engine.rb +122 -0
  16. data/lib/dockerun/config.rb +50 -85
  17. data/lib/dockerun/context/rubygems.rb +142 -0
  18. data/lib/dockerun/dfile.rb +204 -0
  19. data/lib/dockerun/docker_cli.rb +124 -0
  20. data/lib/dockerun/dsl.rb +342 -0
  21. data/lib/dockerun/version.rb +1 -1
  22. data/lib/dockerun.rb +32 -24
  23. data/sig/dockerun.rbs +4 -0
  24. metadata +62 -73
  25. data/.release_history.yml +0 -56
  26. data/Dockerfile.dockerun +0 -38
  27. data/Gemfile +0 -15
  28. data/Gemfile.lock +0 -94
  29. data/bin/console +0 -15
  30. data/bin/setup +0 -8
  31. data/lib/dockerun/bundler_helper.rb +0 -25
  32. data/lib/dockerun/cli_prompt.rb +0 -18
  33. data/lib/dockerun/command/dockerun.rb +0 -30
  34. data/lib/dockerun/command/init.rb +0 -79
  35. data/lib/dockerun/command/remove_container.rb +0 -99
  36. data/lib/dockerun/command/reset_image.rb +0 -107
  37. data/lib/dockerun/command/run.rb +0 -226
  38. data/lib/dockerun/command/run_new_container.rb +0 -94
  39. data/lib/dockerun/command/run_new_image.rb +0 -89
  40. data/lib/dockerun/command/stop_container.rb +0 -90
  41. data/lib/dockerun/docker_command_factory_helper.rb +0 -19
  42. data/lib/dockerun/docker_container_helper.rb +0 -213
  43. data/lib/dockerun/docker_image_helper.rb +0 -381
  44. data/lib/dockerun/template/general_template_writer.rb +0 -14
  45. data/lib/dockerun/template/jruby_template_writer.rb +0 -24
  46. data/lib/dockerun/template/template_engine.rb +0 -27
  47. data/lib/dockerun/template/template_writer.rb +0 -102
  48. data/lib/dockerun/user_info.rb +0 -37
  49. data/template/Dockerfile_general.erb +0 -41
  50. data/template/setup_ruby_devenv.rb.erb +0 -22
@@ -0,0 +1,122 @@
1
+
2
+ require 'tty/prompt'
3
+ require_relative 'cli/run'
4
+ require_relative 'cli/delete_container'
5
+ require_relative 'cli/delete_image'
6
+
7
+ module Dockerun
8
+ class CliEngine
9
+ include TR::ArgUtils
10
+
11
+ arg_spec do
12
+ opt "i", "Initialize sample dockerspec at given directory as next argument" do |v|
13
+ init(v)
14
+ end
15
+ opt_alias "i", "init"
16
+
17
+ opt "r", "Run the dockerspec at given directory as next argument" do |v|
18
+ run(v)
19
+ end
20
+ opt_alias "r","run"
21
+
22
+ opt "dc", "Delete container at given directory as next argument" do |v|
23
+ delete_container(v)
24
+ end
25
+
26
+ opt "di", "Delete image and its associated container(s) at given directory as next argument" do |v|
27
+ delete_image(v)
28
+ end
29
+
30
+ opt 'clean', "Clean generated Dockerfile and temporary files at given directory as next argument" do |v|
31
+ clean_env(v)
32
+ end
33
+
34
+ opt 'help', "Command help" do
35
+ print_help
36
+ end
37
+
38
+ end
39
+
40
+ def print_help
41
+ pmt = self.class.pmt
42
+ pmt.puts ""
43
+ pmt.puts " Dockerun version #{Dockerun::VERSION}".magenta
44
+ pmt.puts ""
45
+ pmt.puts " Supported options : "
46
+ self.class.arg_options.each do |key, val|
47
+ pmt.puts " #{key}\t\t#{val[:desc]}"
48
+ end
49
+ pmt.puts ""
50
+ end
51
+
52
+ def self.select_spec(root)
53
+ raise InsufficientParameter, "Given path cannot be empty or nil" if is_empty?(root)
54
+
55
+ #sel = Dir.entries(Dir.getwd).sort
56
+ sel = Dir.entries(root).sort
57
+ default = sel.select { |e| (e =~ /^dockerspec/) != nil }
58
+ selSpec = pmt.select(" Please select the dockerspec to proceed : ", filter: true, default: default.first) do |m|
59
+ sel.each do |s|
60
+ next if sel == "." or sel == ".." or File.directory?(s)
61
+ m.choice s, File.expand_path(s)
62
+ end
63
+ end
64
+
65
+ selSpec
66
+ end
67
+
68
+
69
+ def init(root)
70
+ raise InsufficientParameter, "Given path cannot be empty or nil" if is_empty?(root)
71
+
72
+ root = File.expand_path(root)
73
+ template = File.join(File.dirname(__FILE__),"..","..","dockerspec.sample")
74
+ if File.exist?(template)
75
+ #FileUtils.cp template, File.join(Dir.getwd, "dockerspec.sample")
76
+ FileUtils.cp template, File.join(root, "dockerspec.sample")
77
+ end
78
+ end
79
+
80
+ def run(root)
81
+ raise InsufficientParameter, "Given path cannot be empty or nil" if is_empty?(root)
82
+
83
+ root = File.expand_path(root)
84
+ r = Dockerun::Cli::Run.new
85
+ r.start(root)
86
+ end
87
+
88
+ def delete_container(root)
89
+ raise InsufficientParameter, "Given path cannot be empty or nil" if is_empty?(root)
90
+ root = File.expand_path(root)
91
+ d = Dockerun::Cli::DeleteContainer.new
92
+ d.start(root)
93
+ end
94
+
95
+ def delete_image(root)
96
+ raise InsufficientParameter, "Given path cannot be empty or nil" if is_empty?(root)
97
+ root = File.expand_path(root)
98
+ d = Dockerun::Cli::DeleteImage.new
99
+ d.start(root)
100
+ end
101
+
102
+ def clean_env(root)
103
+ raise InsufficientParameter, "Given path cannot be empty or nil" if is_empty?(root)
104
+ root = File.expand_path(root)
105
+
106
+ Dir.glob(File.join(root,"Dockerfile-*")).each do |f|
107
+ FileUtils.rm(f)
108
+ end
109
+ pa = File.join(root,"script_for_gem.sh")
110
+ FileUtils.rm(pa) if File.exist?(pa)
111
+ self.class.pmt.puts " Generated Dockerfile-* and script_for_gem.sh is deleted at '#{root}'".green
112
+ end
113
+
114
+ def self.pmt
115
+ if @_pmt.nil?
116
+ @_pmt = TTY::Prompt.new
117
+ end
118
+ @_pmt
119
+ end
120
+
121
+ end
122
+ end
@@ -1,115 +1,80 @@
1
1
 
2
- require 'yaml'
2
+ require_relative 'context/rubygems'
3
3
 
4
4
  module Dockerun
5
5
  class Config
6
6
  include TR::CondUtils
7
7
 
8
- FILENAME = ".dockerun".freeze
9
-
10
- def self.from_storage
11
- path = File.join(Dir.getwd, FILENAME)
12
- if File.exist?(path)
13
- #cont = nil
14
- #File.open(path,"r") do |f|
15
- # cont = f.read
16
- #end
17
-
18
- #Config.new(YAML.load(cont), true)
19
- Config.new(YAML.unsafe_load_file(path), true)
20
- else
21
- Config.new({}, false)
22
- end
8
+ def set_workdir(path)
9
+ @workdir = path
23
10
  end
24
-
25
- def self.remove
26
- path = File.join(Dir.getwd, FILENAME)
27
- FileUtils.rm(path) if File.exist?(path)
28
- end
29
-
30
- def initialize(configHash = { }, configFileAvail = false)
31
- @config = configHash
32
- @images = @config[:images] || { }
33
- @confFileAvail = configFileAvail
34
- #@images = { } if @images.nil?
11
+ def workdir
12
+ if @workdir.nil?
13
+ @workdir = File.join("/opt",File.basename(Dir.getwd))
14
+ end
15
+ @workdir
35
16
  end
36
-
37
- def isConfigFileAvail?
38
- @confFileAvail
17
+ def is_workdir_given?
18
+ not_empty?(@workdir)
39
19
  end
40
20
 
41
- def image_names
42
- @images.keys
43
- end
44
21
 
45
- def add_image(name)
46
- @images[name] = { } if not_empty?(name) and not @images.keys.include?(name)
22
+ def set_platform(val)
23
+ @platform = val
47
24
  end
48
-
49
- def remove_image(name)
50
- @images.delete(name)
25
+ def platform
26
+ if is_empty?(@platform)
27
+ # wild guess
28
+ @platform = :debian
29
+ end
30
+ @platform
51
31
  end
52
32
 
53
- def container_names(imageName)
54
- @images[imageName].keys
55
- end
56
33
 
57
- def container_configs(imageName, name)
58
- @images[imageName].nil? ? {} : @images[imageName][name].nil? ? {} : @images[imageName][name]
34
+ def set_current_user(bool = true)
35
+ @set_current_user = bool
59
36
  end
60
-
61
- def add_container(imageName, name)
62
- @images[imageName] = { } if @images[imageName].nil?
63
- @images[imageName][name] = {} if @images[imageName][name].nil?
37
+ def set_current_user?
38
+ @set_current_user.nil? ? true : @set_current_user
64
39
  end
65
40
 
66
- def remove_container(imageName, name)
67
- if not @images[imageName].nil?
68
- @images[imageName].delete(name)
69
- end
70
- end
71
41
 
72
- def add_mount_to_container(imageName, container, mount)
73
- add_container(imageName, container)
74
- @images[imageName][container][:mount] = [] if @images[imageName][container][:mount].nil?
75
- case mount.class
76
- when Array
77
- @images[imageName][container][:mount]concat(mount)
42
+ def activate_context(ctx, &block)
43
+ case ctx
44
+ when :rubygems
45
+ @active_context = Context::Rubygems.new(self)
78
46
  else
79
- @images[imageName][container][:mount] << mount
47
+ raise Error, "Unknown context '#{ctx}'"
80
48
  end
49
+ @active_context.instance_eval(&block)
81
50
  end
82
-
83
- def container_mount_points(imageName, container)
84
- res = @images[imageName][container]
85
- if is_empty?(res) or is_empty?(res[:mount])
86
- []
87
- else
88
- res[:mount]
89
- end
51
+ def active_context
52
+ @active_context
90
53
  end
91
54
 
92
- def add_port_mapping_to_container(imageName, container, port_mapping)
93
- add_container(imageName, container)
94
- @images[imageName][container][:port_mapping] = [] if @images[imageName][container][:port_mapping].nil?
95
- case mount.class
96
- when Array
97
- @images[imageName][container][:port_mapping]concat(port_mapping)
98
- else
99
- @images[imageName][container][:port_mapping] << port_mapping
100
- end
55
+
56
+ def gen_docker_runscript(bool = true, overwrite = false)
57
+ @_gen_docker_runscript = bool
58
+ @_overwrite_docker_runscript = overwrite
101
59
  end
60
+ def is_gen_docker_runscript?
61
+ @_gen_docker_runscript.nil? ? false : @_gen_docker_runscript
62
+ end
63
+ def is_overwrite_docker_runscript?
64
+ @_overwrite_docker_runscript.nil? ? false : @_overwrite_docker_runscript
65
+ end
66
+
102
67
 
103
-
104
- def to_storage
105
- res = { images: @images }
106
-
107
- path = File.join(Dir.getwd, FILENAME)
108
- File.open(path,"w") do |f|
109
- f.write YAML.dump(res)
110
- end
68
+ def dry_run(bool = true, prompt = true)
69
+ @dry_run = bool
70
+ @dry_run_prompt = prompt
71
+ end
72
+ def is_dry_run?
73
+ @dry_run.nil? ? false : @dry_run
74
+ end
75
+ def is_dry_run_prompt?
76
+ @dry_run_prompt.nil? ? false : @dry_run_prompt
111
77
  end
112
- alias_method :save, :to_storage
113
78
 
114
79
  end
115
80
  end
@@ -0,0 +1,142 @@
1
+
2
+ require 'bundler'
3
+
4
+ require_relative '../cli/command_factory'
5
+
6
+ module Dockerun
7
+ module Context
8
+
9
+ class Rubygems
10
+ include TR::CondUtils
11
+
12
+ def self.is_rubygems?(path)
13
+ fs = Dir.entries(path)
14
+ gs = fs.select { |s| s =~ /.gemspec/ }
15
+ fs.include?("Gemfile") and fs.include?("Gemfile.lock") and not_empty?(gs)
16
+ end
17
+
18
+ def initialize(conf)
19
+ @_config = conf
20
+ end
21
+
22
+ def call(ops, *val)
23
+ case ops
24
+ when :dsl_before_go
25
+ check_integrity
26
+
27
+ when :dsl_image_built
28
+ FileUtils.rm(gen_file_name) if not is_keep_gen_file?
29
+
30
+ when :dockerfile_before_workdir
31
+ init_script_in_dockerfile
32
+
33
+ when :docker_cli_construct_command
34
+ para = val.first
35
+ if not_empty?(dev_gems_mounts)
36
+ para[:mounts] = {} if para[:mounts].nil?
37
+ para[:mounts].merge!(dev_gems_mounts)
38
+ end
39
+ para
40
+
41
+ end
42
+ end
43
+
44
+ def check_integrity
45
+ puts `cd #{Dir.getwd} && bundle`
46
+ end
47
+
48
+ def keep_gen_file(bool = true)
49
+ @_keep_gen_file = bool
50
+ end
51
+ def is_keep_gen_file?
52
+ @_keep_gen_file.nil? ? true : @_keep_gen_file
53
+ end
54
+
55
+ def gen_file_name
56
+ "script_for_gem.sh"
57
+ end
58
+
59
+ # shell script to set the env
60
+ def init_script_in_dockerfile
61
+ cmd = ["#!/usr/bin/env ruby"]
62
+ if is_duplicate_dev_env?
63
+ if has_dev_gems?
64
+ find_local_dev_gems.each do |name, path|
65
+ if @_config.is_workdir_given?
66
+ root = File.dirname(@_config.workdir)
67
+ else
68
+ root = "/opt"
69
+ end
70
+
71
+ dockerPath = File.join(root, name)
72
+ cmd << "`bundle config --global local.#{name} #{dockerPath}`"
73
+ dev_gems_mounts[path] = dockerPath
74
+ end
75
+ end
76
+ end
77
+
78
+ cmd << "`echo 'alias be=\"bundle exec\"' >> ~/.bashrc`"
79
+
80
+ initScript = cmd.join("\n")
81
+ File.open(gen_file_name,"w") do |f|
82
+ f.write initScript
83
+ end
84
+ `chmod +x script_for_gem.sh`
85
+
86
+ cont = []
87
+ cont << "COPY script_for_gem.sh /tmp"
88
+ cont << "RUN /tmp/script_for_gem.sh"
89
+ cont.join("\n")
90
+ end
91
+
92
+ def duplicate_dev_env(bool = true)
93
+ @dup_dev_env = bool
94
+ end
95
+ def is_duplicate_dev_env?
96
+ @dup_dev_env.nil? ? true : @dup_dev_env
97
+ end
98
+
99
+
100
+ def dev_gems_mounts
101
+ if @_dev_gems_mounts.nil?
102
+ @_dev_gems_mounts = {}
103
+ end
104
+ @_dev_gems_mounts
105
+ end
106
+
107
+
108
+ def has_dev_gems?
109
+ not find_local_dev_gems.empty?
110
+ end
111
+
112
+ def find_local_dev_gems
113
+
114
+ if @_dev_gems.nil?
115
+
116
+ @_dev_gems = {}
117
+ Bundler.load.dependencies.each do |d|
118
+ if not d.source.nil?
119
+ src = d.source
120
+ if src.path.to_s != "."
121
+ @_dev_gems[d.name] = src.path.expand_path.to_s
122
+ end
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+ @_dev_gems
129
+
130
+ end # find_local_dev_gem
131
+
132
+ def docker_cli
133
+ if @_docker_cli.nil?
134
+ @_docker_cli = Dockerun::Cli::CommandFactory.new
135
+ end
136
+ @_docker_cli
137
+ end
138
+
139
+ end # class RubygemsEngine
140
+
141
+ end
142
+ end
@@ -0,0 +1,204 @@
1
+
2
+ require_relative 'cli/user_info'
3
+
4
+ module Dockerun
5
+
6
+ # Generate Dockerfile
7
+ class Dfile
8
+ include TR::CondUtils
9
+
10
+ def initialize(config)
11
+ @_config = config
12
+ end
13
+
14
+ # DSL
15
+ def set_image_name(val)
16
+ @image_name = val
17
+ end
18
+ def image_name
19
+ @image_name
20
+ end
21
+ def is_image_name_given?
22
+ not_empty?(@image_name)
23
+ end
24
+ def generated_image_name
25
+ if @_genImgName.nil?
26
+ @_genImgName = "#{File.basename(Dir.getwd.gsub(" ","-"))}_docker_image"
27
+ end
28
+ @_genImgName
29
+ end
30
+
31
+ # DSL
32
+ def output=(val)
33
+ @output = val
34
+ end
35
+ def output_filename
36
+ @output
37
+ end
38
+
39
+ def install(*app)
40
+ @installApp = app
41
+ end
42
+ def required_app
43
+ @installApp.nil? ? [] : @installApp
44
+ end
45
+
46
+ def set_command(*val)
47
+ @cmd = val
48
+ end
49
+ def command
50
+ @cmd
51
+ end
52
+ def default_command
53
+ ["/bin/bash"]
54
+ end
55
+ def is_command_given?
56
+ not_empty?(command)
57
+ end
58
+
59
+ def base_image=(img)
60
+ @base_image = img
61
+ end
62
+ def base_image
63
+ @base_image
64
+ end
65
+
66
+ def set_workdir(bool = true)
67
+ @set_workdir = bool
68
+ end
69
+ def is_set_workdir?
70
+ @set_workdir.nil? ? true : @set_workdir
71
+ end
72
+
73
+ def skip_update(bool = false)
74
+ @skip_update = bool
75
+ end
76
+ def skip_update?
77
+ @skip_update.nil? ? false : @skip_update
78
+ end
79
+
80
+ def skip_upgrade(bool = false)
81
+ @skip_upgrade = bool
82
+ end
83
+ def skip_upgrade?
84
+ @skip_upgrade.nil? ? false : @skip_upgrade
85
+ end
86
+
87
+ def keep_dockerfile(bool = true)
88
+ @keep_dockerfile = bool
89
+ end
90
+ def keep_dockerfile?
91
+ @keep_dockerfile.nil? ? true : @keep_dockerfile
92
+ end
93
+
94
+
95
+ # for context to install listener
96
+ def listener(&block)
97
+ @listener = block
98
+ end
99
+
100
+ def generate(opts = {})
101
+
102
+ opts = {} if opts.nil?
103
+
104
+ config = @_config
105
+ raise Error, "Config is required" if config.nil?
106
+
107
+ cont = []
108
+ cont << "FROM #{base_image}"
109
+ cont << ""
110
+
111
+ pkgMgr = pkg_mgr(config)
112
+
113
+ if not skip_update? or not skip_upgrade?
114
+ st = []
115
+ st << "#{pkgMgr} update" if not skip_update?
116
+ st << "#{pkgMgr} -y upgrade" if not skip_upgrade?
117
+ cont << "RUN #{st.join(" && ")}" if not_empty?(st)
118
+ cont << ""
119
+ end
120
+
121
+ cb = trigger_listener(:dockerfile_before_install_app)
122
+ cont << cb if not_empty?(cb)
123
+ cont << "RUN #{pkgMgr} -y install #{required_app.join(" ")}"
124
+ cont << ""
125
+
126
+ cb = trigger_listener(:dockerfile_after_install_app)
127
+ cont << cb if not_empty?(cb)
128
+
129
+ if config.set_current_user?
130
+ #RUN 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
131
+ #USER <%= @user_login %>
132
+
133
+ uInfo = Dockerun::Cli::UserInfo.user_info
134
+ gInfo = Dockerun::Cli::UserInfo.group_info
135
+
136
+ uCmd = []
137
+ uCmd << "groupadd -f -g"
138
+ uCmd << gInfo[:gid]
139
+ uCmd << gInfo[:group_name]
140
+ uCmd << "&& useradd"
141
+ uCmd << "-u"
142
+ uCmd << uInfo[:uid]
143
+ uCmd << "-g"
144
+ uCmd << gInfo[:gid]
145
+ uCmd << "-m"
146
+ uCmd << uInfo[:login]
147
+ uCmd << "&& usermod -aG sudo"
148
+ uCmd << uInfo[:login]
149
+ uCmd << "&& echo '#{uInfo[:login]} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers"
150
+
151
+ cb = trigger_listener(:dockerfile_before_add_user)
152
+ cont << cb if not_empty?(cb)
153
+
154
+ cont << "RUN #{pkgMgr} -y install sudo && #{uCmd.join(" ")}"
155
+ cont << "USER #{uInfo[:login]}"
156
+ cont << ""
157
+
158
+ cb = trigger_listener(:dockerfile_after_add_user)
159
+ cont << cb if not_empty?(cb)
160
+
161
+ end
162
+
163
+ cb = trigger_listener(:dockerfile_before_workdir)
164
+ cont << cb if not_empty?(cb)
165
+
166
+ if config.is_workdir_given? and is_set_workdir?
167
+ cont << "WORKDIR #{config.workdir}"
168
+ cont << ""
169
+ end
170
+
171
+ cb = trigger_listener(:dockerfile_after_workdir)
172
+ cont << cb if not_empty?(cb)
173
+
174
+
175
+ cb = trigger_listener(:dockerfile_before_command)
176
+ cont << cb if not_empty?(cb)
177
+
178
+ cont << "CMD [\"#{command.join(",")}\"]" if is_command_given?
179
+
180
+ cont.join("\n")
181
+
182
+ end
183
+
184
+ private
185
+ def pkg_mgr(config)
186
+ case config.platform
187
+ when :debian
188
+ "apt-get"
189
+ when :fedora
190
+ "dnf"
191
+ else
192
+ raise Error, "Unknown package manager for platform '#{config.platform}'"
193
+ end
194
+ end
195
+
196
+ def trigger_listener(evt, *argv)
197
+ if not @listener.nil?
198
+ argv << { dfile: self }
199
+ @listener.call(evt, *argv)
200
+ end
201
+ end
202
+
203
+ end
204
+ end