Class: Lux::App

Inherits:
Thor
  • Object
show all
Defined in:
lib/lux.rb

Overview

The Thor subclass containing useful tasks shared between the Lux standalone executable and Rake tasks.

Constant Summary collapse

EXCLUDE_VARS =
%w{
  _ HOME PWD TMPDIR SSH_AUTH_SOCK SHLVL DISPLAY Apple_PubSub_Socket_Render SECURITYSESSIONID
  XPC_SERVICE_NAME XPC_FLAGS __CF_USER_TEXT_ENCODING TERM_PROGRAM TERM_PROGRAM_VERSION TERM_SESSION_ID
}

Instance Method Summary collapse

Instance Method Details

#checkObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/lux.rb', line 19

def check
  repobranch = `git symbolic-ref -q HEAD`.chomp.gsub(%r{^.*/},'')
  puts "Repository is on branch #{repobranch}"
  `git fetch --recurse-submodules=on-demand`
  nModuleErr = 0
  nModuleWarn = 0
  # Inspect the submodules currently checked out in turtle
  submodules = Hash[`git submodule status --recursive`.split(/\n/).map do |s|
    die "Bad submodule status #{s}" unless /^(?<flag>[-+U\s])(?<sha>[0-9a-f]{40})\s(?<path>\S+)(\s*\((?<ref>\S+)\))?$/ =~ s
    case flag
    when '-'
      Highline.say "Submodule at #{path} is <%= color('not initialized', RED) %>!"
      nModuleWarn += 1
    when '+'
      Highline.say "Submodule at #{path} is <%= color('not at correct commit', RED) %>!"
      nModuleErr += 1
    when 'U'
      Highline.say "Submodule at #{path} is <%= color('conflicted', RED) %>!"
      nModuleErr += 1
    else
      Highline.say "Submodule at #{path} is <%= color('OK', GREEN) %>"
    end
    [path, [flag, sha, ref]]
  end ]
  die "There were #{nModuleErr} submodule errors and #{nModuleWarn} warnings" if nModuleErr > 0
  # If the submodule status (above) was good, then we can ignore any submodule issues here
  changes = `git status --porcelain`.split(/\n/).reject do |ch|
    die "Bad status #{ch}" unless /^(?<x>.)(?<y>.)\s(?<path1>\S+)( -> (?<path2>\S+))?$/ =~ ch
    submodules.include? path1
  end
  if changes.size > 0
    die "Repository is not clean (#{changes.size} issues), use 'git status'"
  else
    HighLine.say "<%= color('Repository is clean', GREEN) %>"
  end
end

#cleanObject



94
95
96
97
98
99
100
101
# File 'lib/lux.rb', line 94

def clean
  exited = `docker ps -q -f status=exited`.gsub! /\n/,' '
  if exited and not exited.empty?
    system "docker rm #{exited}"
  else
    puts "No exited containers"
  end
end

#clobberObject



164
165
166
167
168
169
170
171
172
# File 'lib/lux.rb', line 164

def clobber
  clean
  running = `docker ps -q -f status=running`.gsub! /\n/,' '
  if running and not running.empty?
    system "docker rm -f #{running}"
  else
    puts "No running containers"
  end
end

#dockeripObject



175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/lux.rb', line 175

def dockerip
  docker_url = URI(ENV['DOCKER_HOST'])
  name = docker_url.host
  if z = Socket.gethostbyname(name) rescue nil
      z.shift 3
      z.each do |a|
          name = a.unpack('CCCC').join('.') if a.size == 4
      end
  end
  puts "DOCKER_HOST=#{docker_url.to_s}"
  docker_url.host = name
  puts "export DOCKER_HOST=#{docker_url.to_s}"
end

#exec(image, *command) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/lux.rb', line 81

def exec(image, *command)
  image = findimage image
  me, setup_cmd = user_setup_cmd
  die "You must be within your home directory!" unless relwd = Pathname.pwd.to_s.gsub!(/^#{ENV['HOME']}/,'~')
  command.map!{|m| m.start_with?('/') ? Pathname.new(m).relative_path_from(Pathname.pwd) : m }
  env = ENV.reject{|k,v| EXCLUDE_VARS.include? k or v =~/\s+/}.map{|k,v| "#{k}=#{v.shellescape}"}
  env += IO.readlines(options.env).grep(/^(?!#)/).map(&:rstrip) if options.env
  cmd = setup_cmd + "su - #{me} -c 'cd #{relwd}; env -i #{env.join(' ')} #{command.join(' ')}'"
  args = ["-v #{ENV['HOME']}:#{ENV['HOME']}"]
  system "docker run --rm #{args.join(' ')} #{image} /bin/bash -c #{cmd.shellescape}"
end

#lsimages(pattern = nil) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/lux.rb', line 115

def lsimages(pattern=nil)
  if options.regex
    pattern = '.*' unless pattern
    rx = Regexp.new(pattern)
    matcher = lambda {|s| rx.match(s)}
  else
    pattern = '*' unless pattern
    matcher = lambda {|s| File.fnmatch?(pattern, s)}
  end
  imagelines = `docker images`.split("\n")[1..-1].sort
  imagelines.each do |imageline|
    imageinfo = imageline.split(/\s+/)
    next if imageinfo[0] == '<none>'
    imagename = imageinfo[0]+':'+imageinfo[1]
    imagesize = imageinfo[-2]+' '+imageinfo[-1]
    imageage  = imageinfo[3..-3].join(' ')
    next unless matcher.call(imagename)
    printf "%-54s%-16s%10s\n", imagename, imageage, imagesize
  end
end

#rmimages(pattern = nil) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/lux.rb', line 139

def rmimages(pattern=nil)
  if options.regex
    pattern = '.*' unless pattern
    rx = Regexp.new(pattern)
    matcher = lambda {|s| rx.match(s)}
  else
    pattern = '*' unless pattern
    matcher = lambda {|s| File.fnmatch?(pattern, s)}
  end
  imagelines = `docker images`.split("\n")[1..-1]
  imagelines.each do |imageline|
    imageinfo = imageline.split(/\s+/)
    next if imageinfo[0] == '<none>'
    imagename = imageinfo[0]+':'+imageinfo[1]
    imagesize = imageinfo[-2]+' '+imageinfo[-1]
    imageage  = imageinfo[3..-3].join(' ')
    next unless matcher.call(imagename)
    if options.force or (agree("Delete #{imagename} (#{imageage}, #{imagesize})? "){|q|q.echo=true})
      `docker rmi #{imageinfo[2]}`
      HighLine.say "Image <%= color('#{imagename}', RED)%> deleted"
    end
  end
end

#start(image) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/lux.rb', line 59

def start(image)
  image = findimage image
  raise "no image" if image.empty?
  puts "Starting #{image} container..."
  me, setup_cmd = user_setup_cmd()
  args = ["-v #{ENV['HOME']}:#{ENV['HOME']}"]
  args << "--env-file=#{options.env}" if options.env
  args << "--name=#{options.name}" unless options.name == '<autogenerated>'
  cid = `docker run -dit #{args.join(' ')} #{image} /bin/bash`.strip
  die "Container failed to start" unless cid =~ /^[a-z0-9]+$/
  system "docker exec #{cid} bash -c #{setup_cmd.shellescape}"
  puts "Type 'su [-] #{me}' then hit enter to attach to the container as yourself:"
  Kernel.exec "docker attach #{cid}"
end

#tidyObject



104
105
106
107
108
109
110
111
# File 'lib/lux.rb', line 104

def tidy
  images = `docker images -f "dangling=true" -q`
  if images.size > 0
    system 'docker rmi $(docker images -f "dangling=true" -q)'
  else
    puts "No dangling images"
  end
end

#versionObject



14
15
16
# File 'lib/lux.rb', line 14

def version
  puts "Version #{Lux::VERSION}"
end