vx-lib-container 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 52d219b00f697bccf0ae07cdfe83c6e84f94dd36
4
+ data.tar.gz: d8430e648a7a68d15a2c179873780dccbc4eef21
5
+ SHA512:
6
+ metadata.gz: e6c1297d7736988de5b7bd18a9afe3417b8ff4844444114979acb3f2c3f5d1e48f44d465945c1169209ded9c3e1a6ca8f199b30f4eee09cf1e3d5563327e832a
7
+ data.tar.gz: 12f41995d3d5299b78b5de63ab131aefd6b9907d867e313893387a3131cfd67c9fa1d56786653b4c75db834e43df44bc82aafba307d020f3241c83ae6bee5cb9
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/ruby
19
+ .vagrant
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ -f d
3
+ --order=rand
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - 2.1.0
4
+
5
+ script: "rake travis"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vx-container_connector.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,276 @@
1
+ Copyright (c) 2013 Dmitry Galinsky
2
+
3
+ The GNU General Public License, Version 2, June 1991 (GPLv2)
4
+ ============================================================
5
+
6
+ > Copyright (C) 1989, 1991 Free Software Foundation, Inc.
7
+ > 59 Temple Place, Suite 330
8
+ > Boston, MA 02111-1307 USA
9
+
10
+ Everyone is permitted to copy and distribute verbatim copies of this license
11
+ document, but changing it is not allowed.
12
+
13
+
14
+ Preamble
15
+ --------
16
+
17
+ The licenses for most software are designed to take away your freedom to share
18
+ and change it. By contrast, the GNU General Public License is intended to
19
+ guarantee your freedom to share and change free software--to make sure the
20
+ software is free for all its users. This General Public License applies to most
21
+ of the Free Software Foundation's software and to any other program whose
22
+ authors commit to using it. (Some other Free Software Foundation software is
23
+ covered by the GNU Library General Public License instead.) You can apply it to
24
+ your programs, too.
25
+
26
+ When we speak of free software, we are referring to freedom, not price. Our
27
+ General Public Licenses are designed to make sure that you have the freedom to
28
+ distribute copies of free software (and charge for this service if you wish),
29
+ that you receive source code or can get it if you want it, that you can change
30
+ the software or use pieces of it in new free programs; and that you know you can
31
+ do these things.
32
+
33
+ To protect your rights, we need to make restrictions that forbid anyone to deny
34
+ you these rights or to ask you to surrender the rights. These restrictions
35
+ translate to certain responsibilities for you if you distribute copies of the
36
+ software, or if you modify it.
37
+
38
+ For example, if you distribute copies of such a program, whether gratis or for a
39
+ fee, you must give the recipients all the rights that you have. You must make
40
+ sure that they, too, receive or can get the source code. And you must show them
41
+ these terms so they know their rights.
42
+
43
+ We protect your rights with two steps: (1) copyright the software, and (2) offer
44
+ you this license which gives you legal permission to copy, distribute and/or
45
+ modify the software.
46
+
47
+ Also, for each author's protection and ours, we want to make certain that
48
+ everyone understands that there is no warranty for this free software. If the
49
+ software is modified by someone else and passed on, we want its recipients to
50
+ know that what they have is not the original, so that any problems introduced by
51
+ others will not reflect on the original authors' reputations.
52
+
53
+ Finally, any free program is threatened constantly by software patents. We wish
54
+ to avoid the danger that redistributors of a free program will individually
55
+ obtain patent licenses, in effect making the program proprietary. To prevent
56
+ this, we have made it clear that any patent must be licensed for everyone's free
57
+ use or not licensed at all.
58
+
59
+ The precise terms and conditions for copying, distribution and modification
60
+ follow.
61
+
62
+
63
+ Terms And Conditions For Copying, Distribution And Modification
64
+ ---------------------------------------------------------------
65
+ 0. This License applies to any program or other work which contains a notice
66
+ placed by the copyright holder saying it may be distributed under the terms
67
+ of this General Public License. The "Program", below, refers to any such
68
+ program or work, and a "work based on the Program" means either the Program
69
+ or any derivative work under copyright law: that is to say, a work
70
+ containing the Program or a portion of it, either verbatim or with
71
+ modifications and/or translated into another language. (Hereinafter,
72
+ translation is included without limitation in the term "modification".)
73
+ Each licensee is addressed as "you".
74
+
75
+ Activities other than copying, distribution and modification are not
76
+ covered by this License; they are outside its scope. The act of running the
77
+ Program is not restricted, and the output from the Program is covered only
78
+ if its contents constitute a work based on the Program (independent of
79
+ having been made by running the Program). Whether that is true depends on
80
+ what the Program does.
81
+
82
+ 1. You may copy and distribute verbatim copies of the Program's source code as
83
+ you receive it, in any medium, provided that you conspicuously and
84
+ appropriately publish on each copy an appropriate copyright notice and
85
+ disclaimer of warranty; keep intact all the notices that refer to this
86
+ License and to the absence of any warranty; and give any other recipients
87
+ of the Program a copy of this License along with the Program.
88
+
89
+ You may charge a fee for the physical act of transferring a copy, and you
90
+ may at your option offer warranty protection in exchange for a fee.
91
+
92
+ 2. You may modify your copy or copies of the Program or any portion of it,
93
+ thus forming a work based on the Program, and copy and distribute such
94
+ modifications or work under the terms of Section 1 above, provided that you
95
+ also meet all of these conditions:
96
+
97
+ a) You must cause the modified files to carry prominent notices stating
98
+ that you changed the files and the date of any change.
99
+
100
+ b) You must cause any work that you distribute or publish, that in whole
101
+ or in part contains or is derived from the Program or any part thereof,
102
+ to be licensed as a whole at no charge to all third parties under the
103
+ terms of this License.
104
+
105
+ c) If the modified program normally reads commands interactively when run,
106
+ you must cause it, when started running for such interactive use in the
107
+ most ordinary way, to print or display an announcement including an
108
+ appropriate copyright notice and a notice that there is no warranty (or
109
+ else, saying that you provide a warranty) and that users may
110
+ redistribute the program under these conditions, and telling the user
111
+ how to view a copy of this License. (Exception: if the Program itself
112
+ is interactive but does not normally print such an announcement, your
113
+ work based on the Program is not required to print an announcement.)
114
+
115
+ These requirements apply to the modified work as a whole. If identifiable
116
+ sections of that work are not derived from the Program, and can be
117
+ reasonably considered independent and separate works in themselves, then
118
+ this License, and its terms, do not apply to those sections when you
119
+ distribute them as separate works. But when you distribute the same
120
+ sections as part of a whole which is a work based on the Program, the
121
+ distribution of the whole must be on the terms of this License, whose
122
+ permissions for other licensees extend to the entire whole, and thus to
123
+ each and every part regardless of who wrote it.
124
+
125
+ Thus, it is not the intent of this section to claim rights or contest your
126
+ rights to work written entirely by you; rather, the intent is to exercise
127
+ the right to control the distribution of derivative or collective works
128
+ based on the Program.
129
+
130
+ In addition, mere aggregation of another work not based on the Program with
131
+ the Program (or with a work based on the Program) on a volume of a storage
132
+ or distribution medium does not bring the other work under the scope of
133
+ this License.
134
+
135
+ 3. You may copy and distribute the Program (or a work based on it, under
136
+ Section 2) in object code or executable form under the terms of Sections 1
137
+ and 2 above provided that you also do one of the following:
138
+
139
+ a) Accompany it with the complete corresponding machine-readable source
140
+ code, which must be distributed under the terms of Sections 1 and 2
141
+ above on a medium customarily used for software interchange; or,
142
+
143
+ b) Accompany it with a written offer, valid for at least three years, to
144
+ give any third party, for a charge no more than your cost of physically
145
+ performing source distribution, a complete machine-readable copy of the
146
+ corresponding source code, to be distributed under the terms of
147
+ Sections 1 and 2 above on a medium customarily used for software
148
+ interchange; or,
149
+
150
+ c) Accompany it with the information you received as to the offer to
151
+ distribute corresponding source code. (This alternative is allowed only
152
+ for noncommercial distribution and only if you received the program in
153
+ object code or executable form with such an offer, in accord with
154
+ Subsection b above.)
155
+
156
+ The source code for a work means the preferred form of the work for making
157
+ modifications to it. For an executable work, complete source code means all
158
+ the source code for all modules it contains, plus any associated interface
159
+ definition files, plus the scripts used to control compilation and
160
+ installation of the executable. However, as a special exception, the source
161
+ code distributed need not include anything that is normally distributed (in
162
+ either source or binary form) with the major components (compiler, kernel,
163
+ and so on) of the operating system on which the executable runs, unless
164
+ that component itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering access to
167
+ copy from a designated place, then offering equivalent access to copy the
168
+ source code from the same place counts as distribution of the source code,
169
+ even though third parties are not compelled to copy the source along with
170
+ the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program except as
173
+ expressly provided under this License. Any attempt otherwise to copy,
174
+ modify, sublicense or distribute the Program is void, and will
175
+ automatically terminate your rights under this License. However, parties
176
+ who have received copies, or rights, from you under this License will not
177
+ have their licenses terminated so long as such parties remain in full
178
+ compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not signed it.
181
+ However, nothing else grants you permission to modify or distribute the
182
+ Program or its derivative works. These actions are prohibited by law if you
183
+ do not accept this License. Therefore, by modifying or distributing the
184
+ Program (or any work based on the Program), you indicate your acceptance of
185
+ this License to do so, and all its terms and conditions for copying,
186
+ distributing or modifying the Program or works based on it.
187
+
188
+ 6. Each time you redistribute the Program (or any work based on the Program),
189
+ the recipient automatically receives a license from the original licensor
190
+ to copy, distribute or modify the Program subject to these terms and
191
+ conditions. You may not impose any further restrictions on the recipients'
192
+ exercise of the rights granted herein. You are not responsible for
193
+ enforcing compliance by third parties to this License.
194
+
195
+ 7. If, as a consequence of a court judgment or allegation of patent
196
+ infringement or for any other reason (not limited to patent issues),
197
+ conditions are imposed on you (whether by court order, agreement or
198
+ otherwise) that contradict the conditions of this License, they do not
199
+ excuse you from the conditions of this License. If you cannot distribute so
200
+ as to satisfy simultaneously your obligations under this License and any
201
+ other pertinent obligations, then as a consequence you may not distribute
202
+ the Program at all. For example, if a patent license would not permit
203
+ royalty-free redistribution of the Program by all those who receive copies
204
+ directly or indirectly through you, then the only way you could satisfy
205
+ both it and this License would be to refrain entirely from distribution of
206
+ the Program.
207
+
208
+ If any portion of this section is held invalid or unenforceable under any
209
+ particular circumstance, the balance of the section is intended to apply
210
+ and the section as a whole is intended to apply in other circumstances.
211
+
212
+ It is not the purpose of this section to induce you to infringe any patents
213
+ or other property right claims or to contest validity of any such claims;
214
+ this section has the sole purpose of protecting the integrity of the free
215
+ software distribution system, which is implemented by public license
216
+ practices. Many people have made generous contributions to the wide range
217
+ of software distributed through that system in reliance on consistent
218
+ application of that system; it is up to the author/donor to decide if he or
219
+ she is willing to distribute software through any other system and a
220
+ licensee cannot impose that choice.
221
+
222
+ This section is intended to make thoroughly clear what is believed to be a
223
+ consequence of the rest of this License.
224
+
225
+ 8. If the distribution and/or use of the Program is restricted in certain
226
+ countries either by patents or by copyrighted interfaces, the original
227
+ copyright holder who places the Program under this License may add an
228
+ explicit geographical distribution limitation excluding those countries, so
229
+ that distribution is permitted only in or among countries not thus excluded.
230
+ In such case, this License incorporates the limitation as if written in
231
+ the body of this License.
232
+
233
+ 9. The Free Software Foundation may publish revised and/or new versions of the
234
+ General Public License from time to time. Such new versions will be similar
235
+ in spirit to the present version, but may differ in detail to address new
236
+ problems or concerns.
237
+
238
+ Each version is given a distinguishing version number. If the Program
239
+ specifies a version number of this License which applies to it and "any
240
+ later version", you have the option of following the terms and conditions
241
+ either of that version or of any later version published by the Free
242
+ Software Foundation. If the Program does not specify a version number of
243
+ this License, you may choose any version ever published by the Free
244
+ Software Foundation.
245
+
246
+ 10. If you wish to incorporate parts of the Program into other free programs
247
+ whose distribution conditions are different, write to the author to ask for
248
+ permission. For software which is copyrighted by the Free Software
249
+ Foundation, write to the Free Software Foundation; we sometimes make
250
+ exceptions for this. Our decision will be guided by the two goals of
251
+ preserving the free status of all derivatives of our free software and of
252
+ promoting the sharing and reuse of software generally.
253
+
254
+
255
+ No Warranty
256
+ -----------
257
+
258
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
259
+ THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
260
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
261
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
262
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
263
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO
264
+ THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
265
+ PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
266
+ CORRECTION.
267
+
268
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
269
+ ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
270
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
271
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
272
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
273
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
274
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
275
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
276
+ SUCH DAMAGES.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require
4
+ require "bundler/gem_tasks"
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => :spec
10
+
11
+ desc "run travis build"
12
+ task :travis do
13
+ exec "bundle exec rake SPEC_OPTS='--format documentation -t ~docker --order=rand'"
14
+ end
15
+
16
+ namespace :remote do
17
+ desc "run box"
18
+ task :up do
19
+ exec "vagrant up --provider=rackspace"
20
+ end
21
+
22
+ desc "destroy box"
23
+ task :down do
24
+ exec "vagrant destroy -f"
25
+ end
26
+
27
+ desc "run spec on rackspace box"
28
+ task :spec do
29
+ 1
30
+ end
31
+ end
32
+
data/Vagrantfile ADDED
@@ -0,0 +1,28 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5
+ VAGRANTFILE_API_VERSION = "2"
6
+
7
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8
+ config.vm.box = "dummy"
9
+
10
+ config.ssh.private_key_path = "~/.ssh/id_rsa"
11
+ config.ssh.pty = true
12
+
13
+ config.vm.provider :rackspace do |rs|
14
+ rs.username = ENV['SDK_USERNAME']
15
+ rs.api_key = ENV['SDK_TOKEN']
16
+ rs.flavor = /4 GB/
17
+ rs.image = /Ubuntu 14.04/
18
+ rs.rackspace_region = ENV['SDK_REGION']
19
+ rs.key_name = ENV['SDK_KEYNAME']
20
+ rs.server_name = 'vx.lib.container.build'
21
+ end
22
+
23
+ script = <<SCRIPT
24
+ /vagrant/scripts/box_up.sh
25
+ SCRIPT
26
+
27
+ config.vm.provision "shell", inline: script
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'vx/lib/shell'
2
+
3
+ module Vx ; module Lib ; module Container ;
4
+
5
+ class Docker
6
+
7
+ Spawner = Struct.new(:container, :ssh) do
8
+
9
+ include Lib::Shell
10
+ include Lib::Container::Upload
11
+
12
+ def exec(script, &logger)
13
+ sh(:ssh, ssh).exec upload(script, "~/build.sh", mode: '0755', &logger)
14
+ sh(:ssh, ssh).exec("~/build.sh", &logger)
15
+ end
16
+
17
+ def id
18
+ container.id
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ end ; end ; end
@@ -0,0 +1,102 @@
1
+ require 'docker'
2
+ require 'excon'
3
+ require 'timeout'
4
+ require 'net/ssh'
5
+ require 'vx/lib/shell'
6
+
7
+ module Vx
8
+ module Lib
9
+ module Container
10
+
11
+ class Docker
12
+
13
+ autoload :Spawner, File.expand_path("../docker/spawner", __FILE__)
14
+
15
+ include Lib::Shell
16
+ include Lib::Container::Retriable
17
+ include Lib::Container::Instrument
18
+
19
+ attr_reader :user, :password, :init, :image, :remote_dir, :memory, :memory_swap
20
+
21
+ def initialize(options = {})
22
+ @user = options[:user] || "vexor"
23
+ @password = options[:password] || "vexor"
24
+ @init = options[:init] || %w{ /sbin/my_init }
25
+ @image = options[:image] || "vexor/trusty:2.0.1"
26
+ @memory = options[:memory].to_i
27
+ @memory_swap = options[:memory_swap].to_i
28
+ end
29
+
30
+ def start(&block)
31
+ start_container do |container|
32
+ open_ssh_session(container, &block)
33
+ end
34
+ end
35
+
36
+ def create_container_options
37
+ @create_container_options ||= {
38
+ 'Cmd' => init,
39
+ 'Image' => image,
40
+ 'Memory' => memory,
41
+ 'MemorySwap' => memory_swap
42
+ }
43
+ end
44
+
45
+ private
46
+
47
+ def open_ssh_session(container)
48
+ host = container.json['NetworkSettings']['IPAddress']
49
+
50
+ ssh_options = {
51
+ password: password,
52
+ port: 22,
53
+ paranoid: false,
54
+ forward_agent: false,
55
+ timeout: 3,
56
+ }
57
+
58
+ instrumentation = {
59
+ container_type: "docker",
60
+ container: container.json,
61
+ ssh_options: ssh_options.merge(host: host, user: user)
62
+ }
63
+
64
+ ssh = with_retries ::Net::SSH::AuthenticationFailed, ::Errno::ECONNREFUSED, ::Errno::ETIMEDOUT, ::Timeout::Error, limit: 5, sleep: 3 do
65
+ instrument("start_ssh_session", instrumentation) do
66
+ ::Net::SSH.start host, user, ssh_options
67
+ end
68
+ end
69
+
70
+ re = yield Spawner.new(container, ssh)
71
+ ssh.shutdown!
72
+ re
73
+ end
74
+
75
+ def start_container(&block)
76
+ container = instrument("create", container_type: "docker", container_options: create_container_options) do
77
+ ::Docker::Container.create create_container_options
78
+ end
79
+
80
+ instrumentation = {
81
+ container_type: "docker",
82
+ container: container.json
83
+ }
84
+
85
+ instrument("start", instrumentation) do
86
+ container.start
87
+ end
88
+
89
+ begin
90
+ yield container
91
+ ensure
92
+ instrument("kill", instrumentation) do
93
+ container.kill
94
+ container.remove
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,7 @@
1
+ module Vx
2
+ module Lib
3
+ module Container
4
+ class NotFoundConnector < ::StandardError ; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ require 'vx/lib/shell'
2
+ require 'stringio'
3
+
4
+ module Vx
5
+ module Lib
6
+ module Container
7
+
8
+ class Local
9
+ Spawner = Struct.new(:work_dir) do
10
+ include Lib::Shell
11
+ include Lib::Container::Upload
12
+
13
+ def exec(script, &logger)
14
+ Dir.chdir work_dir do
15
+ sh.exec upload(script, "~/build.sh", mode: '0755')
16
+ sh.exec("~/build.sh", &logger)
17
+ end
18
+ end
19
+
20
+ def id
21
+ work_dir
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ require 'tempfile'
2
+ require 'fileutils'
3
+
4
+ module Vx ; module Lib ; module Container ;
5
+
6
+ class Local
7
+
8
+ include Lib::Container::Instrument
9
+
10
+ autoload :Spawner, File.expand_path("../local/spawner", __FILE__)
11
+
12
+ attr_reader :work_dir
13
+
14
+ def initialize(options = {})
15
+ @work_dir = options[:work_dir] || default_work_dir
16
+ @work_dir = File.expand_path(@work_dir)
17
+ end
18
+
19
+ def start(&block)
20
+ instrument( "create", container_type: 'local', container: { work_dir: work_dir }) do
21
+ FileUtils.rm_rf(work_dir)
22
+ FileUtils.mkdir_p(work_dir)
23
+ end
24
+
25
+ begin
26
+ spawner = Spawner.new(work_dir)
27
+ yield spawner
28
+ ensure
29
+ instrument( "kill", container_type: 'local', container: { work_dir: work_dir }) do
30
+ FileUtils.mkdir_p(work_dir)
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def default_work_dir
38
+ "#{::Dir.tmpdir}/vx_lib_container_#{::Process.pid}"
39
+ end
40
+
41
+ end
42
+
43
+ end ; end ; end
@@ -0,0 +1,23 @@
1
+ module Vx
2
+ module Lib
3
+ module Container
4
+ module Instrument
5
+
6
+ def instrument(name, payload, &block)
7
+ name = "#{name}.container.lib.vx"
8
+
9
+ if ENV['DEBUG']
10
+ $stdout.puts " --> #{name}: #{payload}"
11
+ end
12
+
13
+ if inst = Container.instrumenter
14
+ inst.instrument(name, payload, &block)
15
+ else
16
+ yield if block_given?
17
+ end
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ module Vx
2
+ module Lib
3
+ module Container
4
+ module Retriable
5
+ # This will catch any exception and retry twice (three tries total):
6
+ # with_retries { ... }
7
+ #
8
+ # This will catch any exception and retry four times (five tries total):
9
+ # with_retries(:limit => 5) { ... }
10
+ #
11
+ # This will catch a specific exception and retry once (two tries total):
12
+ # with_retries(Some::Error, :limit => 2) { ... }
13
+ #
14
+ # You can also sleep inbetween tries. This is helpful if you're hoping
15
+ # that some external service recovers from its issues.
16
+ # with_retries(Service::Error, :sleep => 1) { ... }
17
+ #
18
+ def with_retries(*args, &block)
19
+ options = args.last.is_a?(Hash) ? args.pop : {}
20
+ exceptions = args
21
+
22
+ options[:limit] ||= 3
23
+ options[:sleep] ||= 0
24
+ exceptions = [Exception] if exceptions.empty?
25
+
26
+ retried = 0
27
+ begin
28
+ yield
29
+ rescue *exceptions => e
30
+ if retried + 1 < options[:limit]
31
+ retried += 1
32
+ sleep options[:sleep]
33
+ retry
34
+ else
35
+ raise e
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ require 'base64'
2
+
3
+ module Vx ; module Lib ; module Container
4
+
5
+ module Upload
6
+ def upload(content, path, options = {})
7
+ mode = options[:mode] || '0600'
8
+ encoded = ::Base64.encode64(content).gsub("\n", '')
9
+ "( echo #{encoded} | base64 --decode ) > #{path} ; chmod #{mode} #{path}"
10
+ end
11
+ end
12
+
13
+ end ; end ; end
@@ -0,0 +1,7 @@
1
+ module Vx
2
+ module Lib
3
+ module Container
4
+ VERSION = "0.5.7"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path("../container/version", __FILE__)
2
+ require File.expand_path("../container/errors", __FILE__)
3
+
4
+ module Vx
5
+ module Lib
6
+ module Container
7
+
8
+ autoload :Local, File.expand_path("../container/local", __FILE__)
9
+ autoload :Docker, File.expand_path("../container/docker", __FILE__)
10
+ autoload :Retriable, File.expand_path("../container/mixin/retriable", __FILE__)
11
+ autoload :Instrument, File.expand_path("../container/mixin/instrument", __FILE__)
12
+ autoload :Upload, File.expand_path("../container/mixin/upload", __FILE__)
13
+
14
+ extend self
15
+
16
+ attr_accessor :instrumenter
17
+
18
+ def lookup(name, options = {})
19
+ case name.to_sym
20
+ when :docker
21
+ Container::Docker.new options
22
+ when :local
23
+ Container::Local.new options
24
+ else
25
+ raise NotFoundConnector.new("No available connector for #{name.inspect} found")
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
data/scripts/box_up.sh ADDED
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+ set -x
5
+
6
+ cd /root
7
+
8
+ apt-get update -y
9
+ apt-get install software-properties-common -y
10
+ add-apt-repository ppa:brightbox/ruby-ng-experimental -y
11
+ apt-get update -y
12
+ apt-get install ruby2.1 -y
13
+ gem install bundler --no-ri --no-rdoc
14
+
15
+ curl -sSL https://get.docker.com/ | sh
16
+
17
+ curl -o insecure_key -fSL https://github.com/phusion/baseimage-docker/raw/master/image/insecure_key
18
+ chmod 600 insecure_key
19
+
20
+ docker pull phusion/baseimage:0.9.15
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vx::Lib::Container do
4
+ it { should be }
5
+
6
+ context "lookup" do
7
+ it "should return local connector" do
8
+ expect(described_class.lookup(:local)).to be_an_instance_of(Vx::Lib::Container::Local)
9
+ end
10
+
11
+ it "should return docker connector" do
12
+ expect(described_class.lookup(:docker)).to be_an_instance_of(Vx::Lib::Container::Docker)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vx::Lib::Container::Docker do
4
+ let(:conn) { described_class.new }
5
+
6
+ it { should be }
7
+
8
+ context "user" do
9
+ subject { conn.user }
10
+
11
+ it "by default should eq 'vexor'" do
12
+ expect(subject).to eq 'vexor'
13
+ end
14
+
15
+ it "when passed via options should be" do
16
+ expect(described_class.new(user: "user").user).to eq 'user'
17
+ end
18
+ end
19
+
20
+ context "password" do
21
+ subject { conn.password }
22
+
23
+ it "by default should eq 'vexor'" do
24
+ expect(subject).to eq 'vexor'
25
+ end
26
+
27
+ it "when passed via options should be" do
28
+ expect(described_class.new(password: "pass").password).to eq 'pass'
29
+ end
30
+ end
31
+
32
+ context "image" do
33
+ subject { conn.image }
34
+
35
+ it "when passed via options should be" do
36
+ expect(described_class.new(image: "image").image).to eq 'image'
37
+ end
38
+ end
39
+
40
+ context "init" do
41
+ subject { conn.init }
42
+
43
+ it "by default should be" do
44
+ expect(subject).to eq ["/sbin/my_init"]
45
+ end
46
+
47
+ it "when passed via options should be" do
48
+ expect(described_class.new(init: "init").init).to eq 'init'
49
+ end
50
+ end
51
+
52
+ context "start container", docker: true do
53
+
54
+ let(:conn) { described_class.new }
55
+
56
+ it 'should be successfuly' do
57
+ rs = nil
58
+ conn.start do |sh|
59
+ rs = sh.id
60
+ end
61
+ expect(rs).to_not be_empty
62
+ end
63
+
64
+ it 'should be successfuly with memory limit' do
65
+ gb = 1024 * 1024 * 1024
66
+ conn = described_class.new memory: gb, memory_swap: 2 * gb
67
+ rs = nil
68
+ conn.start do |sh|
69
+ rs = sh.id
70
+ end
71
+
72
+ expect(rs).to_not be_empty
73
+ end
74
+
75
+ context "and spawn script" do
76
+ it "successfuly" do
77
+ rs = ""
78
+ code = nil
79
+
80
+ conn.start do |sh|
81
+ code = sh.exec("pwd") do |out|
82
+ rs << out
83
+ end
84
+ end
85
+
86
+ expect(rs).to eq "/home/vexor\r\n"
87
+ expect(code).to eq 0
88
+ end
89
+
90
+ it "failed" do
91
+ code = nil
92
+ rs = ""
93
+ conn.start do |sh|
94
+ code = sh.exec('ls /notexists ; exit') do |out|
95
+ rs << out
96
+ end
97
+ end
98
+
99
+ expect([1,2]).to be_include(code)
100
+ expect(rs).to match(/No such file or directory/)
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vx::Lib::Container::Local do
4
+ let(:conn) { described_class.new }
5
+ subject { conn }
6
+
7
+ it { should be }
8
+
9
+ context "work_dir" do
10
+ it "by default should be inside Dir.tmpdir" do
11
+ expect(conn.work_dir).to eq("#{Dir.tmpdir}/vx_lib_container_#{Process.pid}")
12
+ end
13
+
14
+ it "when passed via options, should be" do
15
+ expect(described_class.new(work_dir: "/tmp").work_dir).to eq '/tmp'
16
+ end
17
+ end
18
+
19
+ context "start container" do
20
+
21
+ it "spawner id should eq local" do
22
+ rs = nil
23
+ conn.start do |sh|
24
+ rs = sh.id
25
+ end
26
+ expect(rs).to be
27
+ end
28
+
29
+ context "and spawn script" do
30
+ it "successfuly" do
31
+ rs = ""
32
+ code = nil
33
+
34
+ conn.start do |sh|
35
+ code = sh.exec("pwd") do |out|
36
+ rs << out
37
+ end
38
+ end
39
+
40
+ dir = "#{Dir.tmpdir}/vx_lib_container_#{Process.pid}\n"
41
+ if RUBY_PLATFORM =~ /darwin/
42
+ dir.gsub!(/^\/var/, '/private/var')
43
+ end
44
+
45
+ expect(rs).to eq dir
46
+ expect(code).to eq 0
47
+ end
48
+
49
+ it "failed" do
50
+ code = nil
51
+ rs = ""
52
+ conn.start do |sh|
53
+ code = sh.exec('ls /notexists') do |out|
54
+ rs << out
55
+ end
56
+ end
57
+
58
+ expect(rs).to match(/No such file or directory/)
59
+ expect([1,2]).to be_include(code)
60
+ end
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ class TestRetriable
4
+ include Vx::Lib::Container::Retriable
5
+
6
+ class Error < Exception ; end
7
+ end
8
+
9
+ describe Vx::Lib::Container::Retriable do
10
+ let(:proxy) { TestRetriable.new }
11
+
12
+ it "should rescue 2 times" do
13
+ expect(test_retriable(2)).to eq :pass
14
+ end
15
+
16
+ it "should fail on 3 attempt" do
17
+ expect {
18
+ test_retriable(3)
19
+ }.to raise_error(TestRetriable::Error, "0")
20
+ end
21
+
22
+ def test_retriable(n)
23
+ proxy.with_retries(TestRetriable::Error, limit: 3, sleep: 0.1) do
24
+ if n != 0
25
+ n -= 1
26
+ raise TestRetriable::Error.new(n.to_s)
27
+ end
28
+ :pass
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,12 @@
1
+ Bundler.require(:test)
2
+
3
+ #ENV['VX_ENV'] = 'test'
4
+ #ENV['DOCKER_URL'] = "tcp://localhost:2375"
5
+
6
+ require File.expand_path '../../lib/vx/lib/container', __FILE__
7
+ require 'rspec/autorun'
8
+
9
+ Dir[File.expand_path("../..", __FILE__) + "/spec/support/**/*.rb"].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vx/lib/container/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vx-lib-container"
8
+ spec.version = Vx::Lib::Container::VERSION
9
+ spec.authors = ["Dmitry Galinsky"]
10
+ spec.email = ["dima.exe@gmail.com"]
11
+ spec.description = %q{ description }
12
+ spec.summary = %q{ summary }
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency 'docker-api', '= 1.16.1'
22
+ spec.add_runtime_dependency 'vx-lib-shell', '= 0.1.3'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vx-lib-container
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.7
5
+ platform: ruby
6
+ authors:
7
+ - Dmitry Galinsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docker-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.16.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.16.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: vx-lib-shell
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.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.1.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
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: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: " description "
84
+ email:
85
+ - dima.exe@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - Rakefile
96
+ - Vagrantfile
97
+ - lib/vx/lib/container.rb
98
+ - lib/vx/lib/container/docker.rb
99
+ - lib/vx/lib/container/docker/spawner.rb
100
+ - lib/vx/lib/container/errors.rb
101
+ - lib/vx/lib/container/local.rb
102
+ - lib/vx/lib/container/local/spawner.rb
103
+ - lib/vx/lib/container/mixin/instrument.rb
104
+ - lib/vx/lib/container/mixin/retriable.rb
105
+ - lib/vx/lib/container/mixin/upload.rb
106
+ - lib/vx/lib/container/version.rb
107
+ - scripts/box_up.sh
108
+ - spec/lib/container_spec.rb
109
+ - spec/lib/docker_spec.rb
110
+ - spec/lib/local_spec.rb
111
+ - spec/lib/mixin/retriable_spec.rb
112
+ - spec/spec_helper.rb
113
+ - vx-lib-container.gemspec
114
+ homepage: ''
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.2.2
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: summary
138
+ test_files:
139
+ - spec/lib/container_spec.rb
140
+ - spec/lib/docker_spec.rb
141
+ - spec/lib/local_spec.rb
142
+ - spec/lib/mixin/retriable_spec.rb
143
+ - spec/spec_helper.rb