lux 1.0.3 → 1.0.4
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 +4 -4
- data/CHANGELOG +9 -2
- data/README.md +14 -0
- data/bin/lux +1 -0
- data/lib/lux.rb +25 -192
- data/lib/lux/app.rb +189 -0
- data/lib/lux/docker_tasks.rb +1 -0
- data/lib/lux/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 470b01fc27a167ded67ac3e78b182c1a6de73ea8
|
4
|
+
data.tar.gz: db905561412bbd7af5d5b5e07a75d2b55b30f49e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a531c424ab7e8791ab40f1d5fc754e30dbbd37adea65c1c0be5f7676e8629709183f04ad50bcd93970566091cc3237bf854f352f276b80a32264efbb7d063d85
|
7
|
+
data.tar.gz: 51d5965a0e686aa7ed79b3cb1906196b3c526a3ec13efd791260868977d8bb37e032677be0c0dd565666f1bc9c62766f9bcb3424a0687224f3868bffc3d57eef
|
data/CHANGELOG
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
+
lux (1.0.4)
|
2
|
+
|
3
|
+
* Refactor Lux into a Module
|
4
|
+
* Add the Module function Lux.dockerip to return IP address of DOCKER_HOST
|
5
|
+
|
6
|
+
-- Nick Townsend <nick.townsend@mac.com> Thu, 13 Aug 2015 16:07:08 -0700
|
7
|
+
|
1
8
|
lux (1.0.3)
|
2
9
|
|
3
|
-
|
4
|
-
|
10
|
+
* Disabled IPv6 in the Docker API host lookup as it causes 5 second delay
|
11
|
+
when using .local names.
|
5
12
|
|
6
13
|
-- Nick Townsend <nick.townsend@mac.com> Mon, 10 Aug 2015 14:43:12 -0700
|
7
14
|
|
data/README.md
CHANGED
@@ -43,6 +43,20 @@ cleaning, tidying and clobbering containers and their images.
|
|
43
43
|
|
44
44
|
Type: `lux help` to get started
|
45
45
|
|
46
|
+
### Handy Functions
|
47
|
+
|
48
|
+
To assist in creating Rakefiles where the location of container targets is on the Docker
|
49
|
+
host use the module function `Lux.dockerip` as follows:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
require 'lux'
|
53
|
+
|
54
|
+
DOCKER_IP = Lux.dockerip[0]
|
55
|
+
```
|
56
|
+
|
57
|
+
The function returns a second element which is a Ruby URI object representing the
|
58
|
+
environment variable `DOCKER_HOST` or `DOCKER_URL`.
|
59
|
+
|
46
60
|
### Rake Tasks
|
47
61
|
|
48
62
|
When trying to write Rakefiles that start Docker containers it is useful to have a Rake
|
data/bin/lux
CHANGED
data/lib/lux.rb
CHANGED
@@ -1,199 +1,32 @@
|
|
1
|
-
require 'lux/version'
|
2
|
-
|
3
1
|
require 'highline/import'
|
4
|
-
require 'pathname'
|
5
|
-
require 'shellwords'
|
6
|
-
require 'thor'
|
7
2
|
require 'uri'
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
when '-'
|
31
|
-
Highline.say "Submodule at #{path} is <%= color('not initialized', RED) %>!"
|
32
|
-
nModuleWarn += 1
|
33
|
-
when '+'
|
34
|
-
Highline.say "Submodule at #{path} is <%= color('not at correct commit', RED) %>!"
|
35
|
-
nModuleErr += 1
|
36
|
-
when 'U'
|
37
|
-
Highline.say "Submodule at #{path} is <%= color('conflicted', RED) %>!"
|
38
|
-
nModuleErr += 1
|
39
|
-
else
|
40
|
-
Highline.say "Submodule at #{path} is <%= color('OK', GREEN) %>"
|
41
|
-
end
|
42
|
-
[path, [flag, sha, ref]]
|
43
|
-
end ]
|
44
|
-
die "There were #{nModuleErr} submodule errors and #{nModuleWarn} warnings" if nModuleErr > 0
|
45
|
-
# If the submodule status (above) was good, then we can ignore any submodule issues here
|
46
|
-
changes = `git status --porcelain`.split(/\n/).reject do |ch|
|
47
|
-
die "Bad status #{ch}" unless /^(?<x>.)(?<y>.)\s(?<path1>\S+)( -> (?<path2>\S+))?$/ =~ ch
|
48
|
-
submodules.include? path1
|
49
|
-
end
|
50
|
-
if changes.size > 0
|
51
|
-
die "Repository is not clean (#{changes.size} issues), use 'git status'"
|
52
|
-
else
|
53
|
-
HighLine.say "<%= color('Repository is clean', GREEN) %>"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
desc "start IMAGE", "Run a Docker image with user/home mapping"
|
58
|
-
method_option :env, type: :string, aliases: '-e', desc: 'Path to environment file'
|
59
|
-
method_option :name, type: :string, aliases: '-n', default: '<autogenerated>', desc: 'Docker container name'
|
60
|
-
method_option :port, type: :string, aliases: '-p', default: nil, desc: 'Expose ports (default all)'
|
61
|
-
def start(image)
|
62
|
-
image = findimage image
|
63
|
-
raise "no image" if image.empty?
|
64
|
-
puts "Starting #{image} container..."
|
65
|
-
me, setup_cmd = user_setup_cmd()
|
66
|
-
args = ["-v #{ENV['HOME']}:#{ENV['HOME']}"]
|
67
|
-
args << "--env-file=#{options.env}" if options.env
|
68
|
-
args << "--name=#{options.name}" unless options.name == '<autogenerated>'
|
69
|
-
args << (options.port ? "-p #{options.port}" : "-P")
|
70
|
-
cid = `docker run -dit #{args.join(' ')} #{image} /bin/bash`.strip
|
71
|
-
die "Container failed to start" unless cid =~ /^[a-z0-9]+$/
|
72
|
-
system "docker exec #{cid} bash -c #{setup_cmd.shellescape}"
|
73
|
-
puts "Type 'su [-] #{me}' then hit enter to attach to the container as yourself:"
|
74
|
-
Kernel.exec "docker attach #{cid}"
|
75
|
-
end
|
76
|
-
|
77
|
-
EXCLUDE_VARS = %w{
|
78
|
-
_ HOME PWD TMPDIR SSH_AUTH_SOCK SHLVL DISPLAY Apple_PubSub_Socket_Render SECURITYSESSIONID
|
79
|
-
XPC_SERVICE_NAME XPC_FLAGS __CF_USER_TEXT_ENCODING TERM_PROGRAM TERM_PROGRAM_VERSION TERM_SESSION_ID
|
80
|
-
}
|
81
|
-
|
82
|
-
desc "exec IMAGE COMMAND", "Run a command inside a Docker container"
|
83
|
-
method_option :env, type: :string, aliases: '-e', desc: 'Path to environment file'
|
84
|
-
def exec(image, *command)
|
85
|
-
image = findimage image
|
86
|
-
me, setup_cmd = user_setup_cmd
|
87
|
-
die "You must be within your home directory!" unless relwd = Pathname.pwd.to_s.gsub!(/^#{ENV['HOME']}/,'~')
|
88
|
-
command.map!{|m| m.start_with?('/') ? Pathname.new(m).relative_path_from(Pathname.pwd) : m }
|
89
|
-
env = ENV.reject{|k,v| EXCLUDE_VARS.include? k or v =~/\s+/}.map{|k,v| "#{k}=#{v.shellescape}"}
|
90
|
-
env += IO.readlines(options.env).grep(/^(?!#)/).map(&:rstrip) if options.env
|
91
|
-
cmd = setup_cmd + "su - #{me} -c 'cd #{relwd}; env -i #{env.join(' ')} #{command.join(' ')}'"
|
92
|
-
args = ["-v #{ENV['HOME']}:#{ENV['HOME']}"]
|
93
|
-
system "docker run --rm #{args.join(' ')} #{image} /bin/bash -c #{cmd.shellescape}"
|
94
|
-
end
|
95
|
-
|
96
|
-
desc "clean", "Destroy all exited containers"
|
97
|
-
def clean
|
98
|
-
exited = `docker ps -q -f status=exited`.gsub! /\n/,' '
|
99
|
-
if exited and not exited.empty?
|
100
|
-
system "docker rm #{exited}"
|
101
|
-
else
|
102
|
-
puts "No exited containers"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
desc "tidy", "Remove dangling Docker images"
|
107
|
-
def tidy
|
108
|
-
images = `docker images -f "dangling=true" -q`
|
109
|
-
if images.size > 0
|
110
|
-
system 'docker rmi $(docker images -f "dangling=true" -q)'
|
111
|
-
else
|
112
|
-
puts "No dangling images"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
desc "lsimages [PATTERN]", "List Docker images (with optional pattern)"
|
117
|
-
method_option :regex, type: :boolean, aliases: '-r', default: false, desc: 'Pattern is a regular expression'
|
118
|
-
def lsimages(pattern=nil)
|
119
|
-
if options.regex
|
120
|
-
pattern = '.*' unless pattern
|
121
|
-
rx = Regexp.new(pattern)
|
122
|
-
matcher = lambda {|s| rx.match(s)}
|
123
|
-
else
|
124
|
-
pattern = '*' unless pattern
|
125
|
-
matcher = lambda {|s| File.fnmatch?(pattern, s)}
|
126
|
-
end
|
127
|
-
imagelines = `docker images`.split("\n")[1..-1].sort
|
128
|
-
imagelines.each do |imageline|
|
129
|
-
imageinfo = imageline.split(/\s+/)
|
130
|
-
next if imageinfo[0] == '<none>'
|
131
|
-
imagename = imageinfo[0]+':'+imageinfo[1]
|
132
|
-
imagesize = imageinfo[-2]+' '+imageinfo[-1]
|
133
|
-
imageage = imageinfo[3..-3].join(' ')
|
134
|
-
next unless matcher.call(imagename)
|
135
|
-
printf "%-54s%-16s%10s\n", imagename, imageage, imagesize
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
desc "rmimages [PATTERN]", "Remove Docker images (with optional pattern)"
|
140
|
-
method_option :regex, type: :boolean, aliases: '-r', default: false, desc: 'Pattern is a regular expression'
|
141
|
-
method_option :force, type: :boolean, aliases: '-f', default: false, desc: 'Do not prompt for confirmation'
|
142
|
-
def rmimages(pattern=nil)
|
143
|
-
if options.regex
|
144
|
-
pattern = '.*' unless pattern
|
145
|
-
rx = Regexp.new(pattern)
|
146
|
-
matcher = lambda {|s| rx.match(s)}
|
147
|
-
else
|
148
|
-
pattern = '*' unless pattern
|
149
|
-
matcher = lambda {|s| File.fnmatch?(pattern, s)}
|
150
|
-
end
|
151
|
-
imagelines = `docker images`.split("\n")[1..-1]
|
152
|
-
imagelines.each do |imageline|
|
153
|
-
imageinfo = imageline.split(/\s+/)
|
154
|
-
next if imageinfo[0] == '<none>'
|
155
|
-
imagename = imageinfo[0]+':'+imageinfo[1]
|
156
|
-
imagesize = imageinfo[-2]+' '+imageinfo[-1]
|
157
|
-
imageage = imageinfo[3..-3].join(' ')
|
158
|
-
next unless matcher.call(imagename)
|
159
|
-
if options.force or (agree("Delete #{imagename} (#{imageage}, #{imagesize})? "){|q|q.echo=true})
|
160
|
-
`docker rmi #{options.force ? '-f':''} #{imageinfo[2]}`
|
161
|
-
HighLine.say "Image <%= color('#{imagename}', RED)%> deleted"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
desc "clobber", "Destroy all containers (even if running!)"
|
167
|
-
def clobber
|
168
|
-
clean
|
169
|
-
running = `docker ps -q -f status=running`.gsub! /\n/,' '
|
170
|
-
if running and not running.empty?
|
171
|
-
system "docker rm -f #{running}"
|
172
|
-
else
|
173
|
-
puts "No running containers"
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
desc "dockerip", "Show DOCKER_HOST IP address"
|
178
|
-
def dockerip
|
179
|
-
docker_url = URI(ENV['DOCKER_HOST'])
|
180
|
-
name = docker_url.host
|
181
|
-
if z = Socket.gethostbyname(name) rescue nil
|
182
|
-
z.shift 3
|
183
|
-
z.each do |a|
|
184
|
-
name = a.unpack('CCCC').join('.') if a.size == 4
|
185
|
-
end
|
186
|
-
end
|
187
|
-
puts "DOCKER_HOST=#{docker_url.to_s}"
|
188
|
-
docker_url.host = name
|
189
|
-
puts "export DOCKER_HOST=#{docker_url.to_s}"
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module Lux
|
6
|
+
|
7
|
+
# Determine the IPv4 address of the current Docker host
|
8
|
+
# Used to avoid long reverse DNS lookups on .local names
|
9
|
+
# Returns either nil if the lookup failed, or a triplet:
|
10
|
+
# - the IPv4 address as a string
|
11
|
+
# - a URI object
|
12
|
+
# - a string saying which variable was used, 'URL' or 'HOST'
|
13
|
+
# Note that DOCKER_URL is used by the docker-api client, but
|
14
|
+
# as Docker uses the misleading DOCKER_HOST we fallback to that.
|
15
|
+
#
|
16
|
+
def self.dockerip
|
17
|
+
vars = ['DOCKER_URL', 'DOCKER_HOST']
|
18
|
+
var, url = vars.map{|v| [v, ENV[v]]}.find{|d| d[1]}
|
19
|
+
return nil unless var
|
20
|
+
uri = URI.parse(url)
|
21
|
+
name = uri.host
|
22
|
+
addrs = Socket.getaddrinfo(name, nil, :INET, :STREAM, 0, 0, false) rescue []
|
23
|
+
name = addrs.first[3] if addrs.size > 0
|
24
|
+
return name, var, uri
|
190
25
|
end
|
191
26
|
|
192
|
-
private
|
193
|
-
|
194
27
|
# Get the current list of images and make a guess at which one it is...
|
195
28
|
#
|
196
|
-
def findimage image
|
29
|
+
def self.findimage image
|
197
30
|
local_images = `docker images`.strip.split("\n")[1..-1].map{|l| l.gsub!(/^(\S+)\s+(\S+).*/,'\1:\2')}.sort
|
198
31
|
matching_images = local_images.select{|l| l.include? image }
|
199
32
|
if matching_images.size > 0
|
@@ -218,7 +51,7 @@ class Lux::App < Thor
|
|
218
51
|
# - user name (defaults to current user), and
|
219
52
|
# - a bash script setup command
|
220
53
|
#
|
221
|
-
def user_setup_cmd user = `id -nu`.strip
|
54
|
+
def self.user_setup_cmd user = `id -nu`.strip
|
222
55
|
[user, <<-COMMAND.gsub(/^\s*/,'').gsub(/\n/,' ; ')]
|
223
56
|
uid=$(echo $(stat -c %u:%g #{ENV['HOME']}) | cut -d: -f2)
|
224
57
|
useradd -M -d #{ENV['HOME']} -u $uid -s #{ENV['SHELL']} #{user}
|
@@ -226,7 +59,7 @@ class Lux::App < Thor
|
|
226
59
|
COMMAND
|
227
60
|
end
|
228
61
|
|
229
|
-
def die msg, rc = 1
|
62
|
+
def self.die msg, rc = 1
|
230
63
|
HighLine.say HighLine.color(msg, HighLine::RED)
|
231
64
|
exit(rc)
|
232
65
|
end
|
data/lib/lux/app.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'lux/version'
|
2
|
+
|
3
|
+
require 'highline/import'
|
4
|
+
require 'pathname'
|
5
|
+
require 'shellwords'
|
6
|
+
require 'thor'
|
7
|
+
|
8
|
+
# The Thor subclass containing useful tasks shared between the Lux
|
9
|
+
# standalone executable and Rake tasks.
|
10
|
+
#
|
11
|
+
class Lux::App < Thor
|
12
|
+
|
13
|
+
desc "version", "Show the version"
|
14
|
+
def version
|
15
|
+
puts "Version #{Lux::VERSION}"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "check", "Check the integrity of the Git repositories"
|
19
|
+
def check
|
20
|
+
repobranch = `git symbolic-ref -q HEAD`.chomp.gsub(%r{^.*/},'')
|
21
|
+
puts "Repository is on branch #{repobranch}"
|
22
|
+
`git fetch --recurse-submodules=on-demand`
|
23
|
+
nModuleErr = 0
|
24
|
+
nModuleWarn = 0
|
25
|
+
# Inspect the submodules currently checked out in turtle
|
26
|
+
submodules = Hash[`git submodule status --recursive`.split(/\n/).map do |s|
|
27
|
+
Lux.die "Bad submodule status #{s}" unless /^(?<flag>[-+U\s])(?<sha>[0-9a-f]{40})\s(?<path>\S+)(\s*\((?<ref>\S+)\))?$/ =~ s
|
28
|
+
case flag
|
29
|
+
when '-'
|
30
|
+
Highline.say "Submodule at #{path} is <%= color('not initialized', RED) %>!"
|
31
|
+
nModuleWarn += 1
|
32
|
+
when '+'
|
33
|
+
Highline.say "Submodule at #{path} is <%= color('not at correct commit', RED) %>!"
|
34
|
+
nModuleErr += 1
|
35
|
+
when 'U'
|
36
|
+
Highline.say "Submodule at #{path} is <%= color('conflicted', RED) %>!"
|
37
|
+
nModuleErr += 1
|
38
|
+
else
|
39
|
+
Highline.say "Submodule at #{path} is <%= color('OK', GREEN) %>"
|
40
|
+
end
|
41
|
+
[path, [flag, sha, ref]]
|
42
|
+
end ]
|
43
|
+
Lux.die "There were #{nModuleErr} submodule errors and #{nModuleWarn} warnings" if nModuleErr > 0
|
44
|
+
# If the submodule status (above) was good, then we can ignore any submodule issues here
|
45
|
+
changes = `git status --porcelain`.split(/\n/).reject do |ch|
|
46
|
+
Lux.die "Bad status #{ch}" unless /^(?<x>.)(?<y>.)\s(?<path1>\S+)( -> (?<path2>\S+))?$/ =~ ch
|
47
|
+
submodules.include? path1
|
48
|
+
end
|
49
|
+
if changes.size > 0
|
50
|
+
Lux.die "Repository is not clean (#{changes.size} issues), use 'git status'"
|
51
|
+
else
|
52
|
+
HighLine.say "<%= color('Repository is clean', GREEN) %>"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "start IMAGE", "Run a Docker image with user/home mapping"
|
57
|
+
method_option :env, type: :string, aliases: '-e', desc: 'Path to environment file'
|
58
|
+
method_option :name, type: :string, aliases: '-n', default: '<autogenerated>', desc: 'Docker container name'
|
59
|
+
method_option :port, type: :string, aliases: '-p', default: nil, desc: 'Expose ports (default all)'
|
60
|
+
def start(image)
|
61
|
+
image = Lux.findimage image
|
62
|
+
raise "no image" if image.empty?
|
63
|
+
puts "Starting #{image} container..."
|
64
|
+
me, setup_cmd = user_setup_cmd()
|
65
|
+
args = ["-v #{ENV['HOME']}:#{ENV['HOME']}"]
|
66
|
+
args << "--env-file=#{options.env}" if options.env
|
67
|
+
args << "--name=#{options.name}" unless options.name == '<autogenerated>'
|
68
|
+
args << (options.port ? "-p #{options.port}" : "-P")
|
69
|
+
cid = `docker run -dit #{args.join(' ')} #{image} /bin/bash`.strip
|
70
|
+
Lux.die "Container failed to start" unless cid =~ /^[a-z0-9]+$/
|
71
|
+
system "docker exec #{cid} bash -c #{setup_cmd.shellescape}"
|
72
|
+
puts "Type 'su [-] #{me}' then hit enter to attach to the container as yourself:"
|
73
|
+
Kernel.exec "docker attach #{cid}"
|
74
|
+
end
|
75
|
+
|
76
|
+
EXCLUDE_VARS = %w{
|
77
|
+
_ HOME PWD TMPDIR SSH_AUTH_SOCK SHLVL DISPLAY Apple_PubSub_Socket_Render SECURITYSESSIONID
|
78
|
+
XPC_SERVICE_NAME XPC_FLAGS __CF_USER_TEXT_ENCODING TERM_PROGRAM TERM_PROGRAM_VERSION TERM_SESSION_ID
|
79
|
+
}
|
80
|
+
|
81
|
+
desc "exec IMAGE COMMAND", "Run a command inside a Docker container"
|
82
|
+
method_option :env, type: :string, aliases: '-e', desc: 'Path to environment file'
|
83
|
+
def exec(image, *command)
|
84
|
+
image = Lux.findimage image
|
85
|
+
me, setup_cmd = user_setup_cmd
|
86
|
+
Lux.die "You must be within your home directory!" unless relwd = Pathname.pwd.to_s.gsub!(/^#{ENV['HOME']}/,'~')
|
87
|
+
command.map!{|m| m.start_with?('/') ? Pathname.new(m).relative_path_from(Pathname.pwd) : m }
|
88
|
+
env = ENV.reject{|k,v| EXCLUDE_VARS.include? k or v =~/\s+/}.map{|k,v| "#{k}=#{v.shellescape}"}
|
89
|
+
env += IO.readlines(options.env).grep(/^(?!#)/).map(&:rstrip) if options.env
|
90
|
+
cmd = setup_cmd + "su - #{me} -c 'cd #{relwd}; env -i #{env.join(' ')} #{command.join(' ')}'"
|
91
|
+
args = ["-v #{ENV['HOME']}:#{ENV['HOME']}"]
|
92
|
+
system "docker run --rm #{args.join(' ')} #{image} /bin/bash -c #{cmd.shellescape}"
|
93
|
+
end
|
94
|
+
|
95
|
+
desc "clean", "Destroy all exited containers"
|
96
|
+
def clean
|
97
|
+
exited = `docker ps -q -f status=exited`.gsub! /\n/,' '
|
98
|
+
if exited and not exited.empty?
|
99
|
+
system "docker rm #{exited}"
|
100
|
+
else
|
101
|
+
puts "No exited containers"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
desc "tidy", "Remove dangling Docker images"
|
106
|
+
def tidy
|
107
|
+
images = `docker images -f "dangling=true" -q`
|
108
|
+
if images.size > 0
|
109
|
+
system 'docker rmi $(docker images -f "dangling=true" -q)'
|
110
|
+
else
|
111
|
+
puts "No dangling images"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "lsimages [PATTERN]", "List Docker images (with optional pattern)"
|
116
|
+
method_option :regex, type: :boolean, aliases: '-r', default: false, desc: 'Pattern is a regular expression'
|
117
|
+
def lsimages(pattern=nil)
|
118
|
+
if options.regex
|
119
|
+
pattern = '.*' unless pattern
|
120
|
+
rx = Regexp.new(pattern)
|
121
|
+
matcher = lambda {|s| rx.match(s)}
|
122
|
+
else
|
123
|
+
pattern = '*' unless pattern
|
124
|
+
matcher = lambda {|s| File.fnmatch?(pattern, s)}
|
125
|
+
end
|
126
|
+
imagelines = `docker images`.split("\n")[1..-1].sort
|
127
|
+
imagelines.each do |imageline|
|
128
|
+
imageinfo = imageline.split(/\s+/)
|
129
|
+
next if imageinfo[0] == '<none>'
|
130
|
+
imagename = imageinfo[0]+':'+imageinfo[1]
|
131
|
+
imagesize = imageinfo[-2]+' '+imageinfo[-1]
|
132
|
+
imageage = imageinfo[3..-3].join(' ')
|
133
|
+
next unless matcher.call(imagename)
|
134
|
+
printf "%-54s%-16s%10s\n", imagename, imageage, imagesize
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
desc "rmimages [PATTERN]", "Remove Docker images (with optional pattern)"
|
139
|
+
method_option :regex, type: :boolean, aliases: '-r', default: false, desc: 'Pattern is a regular expression'
|
140
|
+
method_option :force, type: :boolean, aliases: '-f', default: false, desc: 'Do not prompt for confirmation'
|
141
|
+
def rmimages(pattern=nil)
|
142
|
+
if options.regex
|
143
|
+
pattern = '.*' unless pattern
|
144
|
+
rx = Regexp.new(pattern)
|
145
|
+
matcher = lambda {|s| rx.match(s)}
|
146
|
+
else
|
147
|
+
pattern = '*' unless pattern
|
148
|
+
matcher = lambda {|s| File.fnmatch?(pattern, s)}
|
149
|
+
end
|
150
|
+
imagelines = `docker images`.split("\n")[1..-1]
|
151
|
+
imagelines.each do |imageline|
|
152
|
+
imageinfo = imageline.split(/\s+/)
|
153
|
+
next if imageinfo[0] == '<none>'
|
154
|
+
imagename = imageinfo[0]+':'+imageinfo[1]
|
155
|
+
imagesize = imageinfo[-2]+' '+imageinfo[-1]
|
156
|
+
imageage = imageinfo[3..-3].join(' ')
|
157
|
+
next unless matcher.call(imagename)
|
158
|
+
if options.force or (agree("Delete #{imagename} (#{imageage}, #{imagesize})? "){|q|q.echo=true})
|
159
|
+
`docker rmi #{options.force ? '-f':''} #{imageinfo[2]}`
|
160
|
+
HighLine.say "Image <%= color('#{imagename}', RED)%> deleted"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
desc "clobber", "Destroy all containers (even if running!)"
|
166
|
+
def clobber
|
167
|
+
clean
|
168
|
+
running = `docker ps -q -f status=running`.gsub! /\n/,' '
|
169
|
+
if running and not running.empty?
|
170
|
+
system "docker rm -f #{running}"
|
171
|
+
else
|
172
|
+
puts "No running containers"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
desc "dockerip", "Show DOCKER_HOST IP address"
|
177
|
+
def dockerip
|
178
|
+
name, var, uri = Lux.dockerip
|
179
|
+
Lux.die "Docker URL or HOST not found" unless name
|
180
|
+
puts "Found #{var}=#{uri.to_s}"
|
181
|
+
if uri.host != name
|
182
|
+
uri.host = name
|
183
|
+
puts "export #{var}=#{uri.to_s}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
# vim: ft=ruby sts=2 sw=2 ts=8
|
data/lib/lux/docker_tasks.rb
CHANGED
data/lib/lux/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Townsend
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -99,6 +99,7 @@ files:
|
|
99
99
|
- Rakefile.test
|
100
100
|
- bin/lux
|
101
101
|
- lib/lux.rb
|
102
|
+
- lib/lux/app.rb
|
102
103
|
- lib/lux/docker_tasks.rb
|
103
104
|
- lib/lux/version.rb
|
104
105
|
- lux.gemspec
|