baha 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +156 -0
  7. data/Rakefile +21 -0
  8. data/baha.gemspec +31 -0
  9. data/bin/baha +5 -0
  10. data/example/.gitignore +1 -0
  11. data/example/base/init.sh.erb +11 -0
  12. data/example/base/test-template.erb +22 -0
  13. data/example/example.yml +54 -0
  14. data/example/rvm/image.yml +33 -0
  15. data/example/rvm/init.sh.erb +12 -0
  16. data/lib/baha/builder.rb +130 -0
  17. data/lib/baha/cli.rb +69 -0
  18. data/lib/baha/config.rb +142 -0
  19. data/lib/baha/container_options/cmd.rb +33 -0
  20. data/lib/baha/container_options/entrypoint.rb +10 -0
  21. data/lib/baha/container_options/env.rb +21 -0
  22. data/lib/baha/container_options/exposed_ports.rb +35 -0
  23. data/lib/baha/container_options/invalid_option_error.rb +15 -0
  24. data/lib/baha/container_options/option.rb +59 -0
  25. data/lib/baha/container_options/volumes.rb +24 -0
  26. data/lib/baha/container_options.rb +38 -0
  27. data/lib/baha/image.rb +154 -0
  28. data/lib/baha/log.rb +80 -0
  29. data/lib/baha/pre_build/command.rb +51 -0
  30. data/lib/baha/pre_build/download.rb +28 -0
  31. data/lib/baha/pre_build/template.rb +48 -0
  32. data/lib/baha/pre_build.rb +47 -0
  33. data/lib/baha/version.rb +3 -0
  34. data/lib/baha/workspace.rb +13 -0
  35. data/lib/baha.rb +5 -0
  36. data/spec/builder_spec.rb +103 -0
  37. data/spec/config_spec.rb +93 -0
  38. data/spec/container_options/cmd_spec.rb +46 -0
  39. data/spec/container_options/entrypoint_spec.rb +32 -0
  40. data/spec/container_options/env_spec.rb +26 -0
  41. data/spec/container_options/exposed_ports_spec.rb +32 -0
  42. data/spec/container_options/option_spec.rb +43 -0
  43. data/spec/container_options/volumes_spec.rb +25 -0
  44. data/spec/fixtures/base_image.yml +5 -0
  45. data/spec/fixtures/config_build.yml +12 -0
  46. data/spec/fixtures/config_build_image.yml +10 -0
  47. data/spec/fixtures/config_eachimage.yml +12 -0
  48. data/spec/fixtures/config_embedded.yml +11 -0
  49. data/spec/fixtures/config_include.yml +7 -0
  50. data/spec/fixtures/config_ssl.yml +13 -0
  51. data/spec/fixtures/config_sslpath.yml +11 -0
  52. data/spec/helpers/docker_helpers.rb +31 -0
  53. data/spec/image_spec.rb +167 -0
  54. data/spec/log_spec.rb +89 -0
  55. data/spec/options_spec.rb +52 -0
  56. data/spec/pre_build/command_spec.rb +69 -0
  57. data/spec/pre_build/download_spec.rb +43 -0
  58. data/spec/pre_build/template_spec.rb +55 -0
  59. data/spec/pre_build_spec.rb +29 -0
  60. data/spec/spec_helper.rb +39 -0
  61. metadata +255 -0
@@ -0,0 +1,142 @@
1
+ require 'yaml'
2
+ require 'pathname'
3
+ require 'baha/log'
4
+
5
+ class Baha::Config
6
+ DEFAULTS = {
7
+ :parent => 'ubuntu:14.04.1',
8
+ :bind => '/.baha',
9
+ :command => ['/bin/bash','./init.sh'],
10
+ :repository => nil,
11
+ :maintainer => nil,
12
+ :timeout => 1200
13
+ }
14
+ LOG = Baha::Log.for_name("Config")
15
+ class << self
16
+ def load(file)
17
+ LOG.debug { "Loading file #{file}"}
18
+ filepath = Pathname.new(file)
19
+ raise ArgumentError.new("Cannot read config file #{file}") unless filepath.readable?
20
+ config = YAML.load_file(filepath)
21
+ config['configdir'] ||= filepath.dirname
22
+ Baha::Config.new(config)
23
+ end
24
+ end
25
+
26
+ attr_reader :configdir, :workspace, :secure, :options
27
+ attr_reader :defaults
28
+
29
+ def initialize(config)
30
+ @config = config
31
+
32
+ # Defaults
33
+ defaults = config['defaults'] || {}
34
+ raise ArgumentError.new("Expected Hash for defaults") unless defaults.is_a?(Hash)
35
+ @defaults = {}
36
+ DEFAULTS.keys.each do |k|
37
+ @defaults[k] = defaults[k] || defaults[k.to_s] || DEFAULTS[k]
38
+ end
39
+
40
+ @configdir = Pathname.new(config['configdir'] || Pathname.pwd)
41
+ @workspace = Pathname.new(config['workspace'] || @configdir + 'workspace')
42
+ @secure = false
43
+ @options = {}
44
+ init_security if ENV.has_key?('DOCKER_CERT_PATH') || config.has_key?('ssl')
45
+ end
46
+
47
+ def init_security
48
+ @secure = true
49
+ cert_path = ''
50
+ ssl_options = { }
51
+ if ENV['DOCKER_CERT_PATH']
52
+ cert_path = Pathname.new(ENV['DOCKER_CERT_PATH'])
53
+ ssl_options[:ssl_verify_peer] = (ENV['DOCKER_TLS_VERIFY'] == '1')
54
+ ssl_options[:client_cert] = (cert_path + 'cert.pem').expand_path.to_s
55
+ ssl_options[:client_key] = (cert_path + 'key.pem').expand_path.to_s
56
+ ssl_options[:ssl_ca_file] = (cert_path + 'ca.pem').expand_path.to_s
57
+ elsif @config.has_key?('ssl')
58
+ ssl = @config['ssl']
59
+ ssl_options[:ssl_verify_peer] = ssl['verify'] || false
60
+ if ssl.has_key?('cert_path')
61
+ cert_path = Pathname.new(ssl['cert_path'])
62
+ ssl_options[:client_cert] = (cert_path + 'cert.pem').expand_path.to_s
63
+ ssl_options[:client_key] = (cert_path + 'key.pem').expand_path.to_s
64
+ ssl_options[:ssl_ca_file] = (cert_path + 'ca.pem').expand_path.to_s
65
+ else
66
+ ssl_options[:client_cert] = ssl['cert']
67
+ ssl_options[:client_key] = ssl['key']
68
+ ssl_options[:ssl_ca_file] = ssl['ca']
69
+ end
70
+ end
71
+ @options.merge!(ssl_options)
72
+ end
73
+
74
+ def each_image
75
+ return unless @config.has_key?('images')
76
+ @config['images'].each do |image|
77
+ if image.has_key?('include')
78
+ path = Pathname.new(image['include'])
79
+ file = resolve_file(path)
80
+ if file
81
+ yml = YAML.load_file(file)
82
+ yield Baha::Image.new(self,yml)
83
+ else
84
+ LOG.error { "Unable to find image include: #{path}"}
85
+ next
86
+ end
87
+ else
88
+ yield Baha::Image.new(self,image)
89
+ end
90
+ end
91
+ end
92
+
93
+ def resolve_file(file)
94
+ filepath = Pathname.new(file)
95
+ LOG.debug { "resolve_file(#{file})" }
96
+ paths = [
97
+ filepath, # 0. Absolute path
98
+ @workspace + file, # 1. Workspace
99
+ @configdir + file, # 2. Config
100
+ Pathname.pwd + file # 3. Current directory
101
+ ]
102
+ paths.reduce(nil) do |result,path|
103
+ if result.nil?
104
+ if path.exist?
105
+ result = path
106
+ LOG.debug("found file at: #{path}")
107
+ else
108
+ LOG.debug("did not find file at: #{path}")
109
+ end
110
+ end
111
+ result
112
+ end
113
+ end
114
+
115
+ # Initialize Docker Client
116
+ def init_docker!
117
+ Docker.options = @options
118
+ if @config.has_key?('docker_url')
119
+ url = @config['docker_url']
120
+ Docker.url = url
121
+ end
122
+ if @secure
123
+ Docker.url = Docker.url.gsub(/^tcp:/,'https:')
124
+ end
125
+ LOG.debug { "Docker URL: #{Docker.url}"}
126
+ LOG.debug { "Docker Options: #{Docker.options.inspect}"}
127
+ Docker.validate_version!
128
+ end
129
+
130
+ def inspect
131
+ <<-eos.gsub(/\n?\s{2,}/,'')
132
+ #{self.class.name}<
133
+ @config=#{@config.inspect},
134
+ @configdir=#{@configdir},
135
+ @workspace=#{@workspace},
136
+ @defaults=#{@defaults.inspect},
137
+ @secure=#{@secure},
138
+ @options=#{@options.inspect}
139
+ >
140
+ eos
141
+ end
142
+ end
@@ -0,0 +1,33 @@
1
+ require 'baha/container_options/invalid_option_error'
2
+ require 'baha/container_options/option'
3
+ module Baha
4
+ module ContainerOptions
5
+ class Cmd < Option
6
+
7
+ def self.split_command(cmd)
8
+ require 'csv'
9
+ CSV.parse_line(cmd,{:col_sep => ' ', :skip_blanks => true, :quote_char => '"'})
10
+ end
11
+
12
+ def initialize(*args)
13
+ if args.length < 2 then
14
+ @conf = 'Cmd'
15
+ super('Cmd',*args)
16
+ else
17
+ @conf = args[0]
18
+ super(*args)
19
+ end
20
+ end
21
+ def apply(config)
22
+ if @value.kind_of?(Array)
23
+ config[@conf] = @value
24
+ else
25
+ config[@conf] = Cmd::split_command(@value)
26
+ end
27
+ end
28
+ def validate!
29
+ raise ERROR("should be an array or string") unless @value.kind_of?(Array) or @value.kind_of?(String)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ require 'baha/container_options/cmd'
2
+ module Baha
3
+ module ContainerOptions
4
+ class Entrypoint < Cmd
5
+ def initialize(*args)
6
+ super('Entrypoint',*args)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ require 'baha/container_options/option'
2
+ module Baha
3
+ module ContainerOptions
4
+ class Env < Option
5
+ def initialize(*args)
6
+ super(:env,*args)
7
+ end
8
+ def apply(config)
9
+ unless config.has_key?('Env')
10
+ config['Env'] = []
11
+ end
12
+ @value.each_pair do |k,v|
13
+ config['Env'] << "#{k}=#{v}"
14
+ end
15
+ end
16
+ def validate!
17
+ raise ERROR("should be a hash") unless @value.kind_of?(Hash)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ require 'baha/container_options/invalid_option_error'
2
+ require 'baha/container_options/option'
3
+ module Baha
4
+ module ContainerOptions
5
+ class ExposedPorts < Option
6
+ def initialize(*args)
7
+ super(:exposedports,*args)
8
+ end
9
+ def apply(config)
10
+ unless config.has_key?('ExposedPorts')
11
+ config['ExposedPorts'] = {}
12
+ end
13
+ @value.each do |port|
14
+ case port
15
+ when Fixnum
16
+ config['ExposedPorts']["#{port}/tcp"] = {}
17
+ when String
18
+ config['ExposedPorts'][port] = {}
19
+ end
20
+ end
21
+ end
22
+
23
+ def validate!
24
+ raise ERROR("should be an array") unless @value.kind_of?(Array)
25
+ @value.each_with_index do |item,index|
26
+ if item.kind_of?(String)
27
+ unless /(\d+)\/(tcp|udp)/ =~ item
28
+ raise ERROR("#{index}: '#{item}' should be in the form 8080/tcp")
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ module Baha
2
+ module ContainerOptions
3
+ class InvalidOptionError < RuntimeError
4
+ attr_reader :key
5
+ attr_reader :value
6
+ attr_reader :reason
7
+ def initialize(key,value,reason)
8
+ super("Unable to validate option: #{key}. '#{value}' #{reason}")
9
+ @key = key
10
+ @value = value
11
+ @reason = reason
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ require 'baha/container_options/invalid_option_error'
2
+ module Baha
3
+ module ContainerOptions
4
+ class Option
5
+ KEYS = {
6
+ :cmd => 'Cmd',
7
+ :cpushares => 'CpuShares',
8
+ :cpuset => 'Cpuset',
9
+ :domainname => 'Domainname',
10
+ :entrypoint => 'Entrypoint',
11
+ :env => 'Env',
12
+ :exposedports => 'ExposedPorts',
13
+ :hostname => 'Hostname',
14
+ :image => 'Image',
15
+ :memory => 'Memory',
16
+ :memoryswap => 'MemorySwap',
17
+ :networkdisabled => 'NetworkDisabled',
18
+ :user => 'User',
19
+ :volumes => 'Volumes',
20
+ :workingdir => 'WorkingDir',
21
+ }
22
+
23
+ attr_reader :key
24
+ attr_reader :config_key
25
+ attr_reader :value
26
+
27
+ def initialize(*args)
28
+ k,@value = args
29
+ raise ArgumentError, "Cannot understand option key '#{k}'" unless k.respond_to?(:to_sym)
30
+ @key = k.to_sym.downcase
31
+ raise ERROR("Option with key '#{@key}' is not found. Expecting #{KEYS.keys.inspect}") unless KEYS.has_key?(@key)
32
+ @config_key = KEYS[@key]
33
+ end
34
+
35
+ def eql?(other)
36
+ @key == other.key and @value == other.value
37
+ end
38
+
39
+ # Apply this option to the container's config hash
40
+ def apply(config)
41
+ config[@config_key] = @value
42
+ end
43
+
44
+ # Validate the option's value
45
+ def validate!
46
+ KEYS.has_key?(@key)
47
+ end
48
+
49
+ def inspect
50
+ "#{self.class.name}<@key=#{@key.inspect},@value=#{@value.inspect}>"
51
+ end
52
+
53
+ private
54
+ def ERROR(reason)
55
+ InvalidOptionError.new(@key,@value,reason)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,24 @@
1
+ require 'baha/container_options/option'
2
+ module Baha
3
+ module ContainerOptions
4
+ class Volumes < Option
5
+ def initialize(*args)
6
+ super(:volumes,*args)
7
+ end
8
+ def apply(config)
9
+ unless config.has_key?('Volumes')
10
+ config['Volumes'] = {}
11
+ end
12
+ @value.each do |mount|
13
+ config['Volumes'][mount] = {}
14
+ end
15
+ end
16
+ def validate!
17
+ raise ERROR("should be an array") unless @value.kind_of?(Array)
18
+ @value.each_with_index do |item,index|
19
+ raise ERROR("#{index}: '#{item}' should be a string") unless item.kind_of?(String)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ require 'baha/container_options/cmd'
2
+ require 'baha/container_options/entrypoint'
3
+ require 'baha/container_options/env'
4
+ require 'baha/container_options/exposed_ports'
5
+ require 'baha/container_options/invalid_option_error'
6
+ require 'baha/container_options/option'
7
+ require 'baha/container_options/volumes'
8
+ module Baha
9
+ module ContainerOptions
10
+ def self.parse_options(options)
11
+ if options
12
+ Hash[options.map { |k,v| opt = self.parse_option(k,v)
13
+ [opt.key,opt] }]
14
+ else
15
+ {}
16
+ end
17
+ end
18
+ def self.parse_option(key,value)
19
+ k = key.to_sym.downcase
20
+ option = case k
21
+ when :volumes
22
+ Volumes.new(value)
23
+ when :env
24
+ Env.new(value)
25
+ when :cmd
26
+ Cmd.new(value)
27
+ when :entrypoint
28
+ Entrypoint.new(value)
29
+ when :exposedports
30
+ ExposedPorts.new(value)
31
+ else
32
+ Option.new(key,value)
33
+ end
34
+ option.validate!
35
+ option
36
+ end
37
+ end
38
+ end
data/lib/baha/image.rb ADDED
@@ -0,0 +1,154 @@
1
+ require 'docker'
2
+ require 'baha/container_options'
3
+ require 'baha/log'
4
+ require 'set'
5
+
6
+ module Baha
7
+ class ImageNotFoundError < RuntimeError
8
+ attr_reader :image
9
+ def initialize(image)
10
+ super("Unable to locate image : #{image[:name]}:#{image[:tag]}")
11
+ @image = image
12
+ end
13
+ end
14
+ class Image
15
+ LOG = Baha::Log.for_name("Image")
16
+ class << self
17
+ # Parses an image name
18
+ def parse_name(image)
19
+ m = /(?:([a-z0-9\-._\/]+))(?::([a-zA-Z0-9\-._]+))?/.match(image)
20
+ unless m
21
+ raise ArgumentError.new("Unable to parse image name #{image}")
22
+ end
23
+ tag = m.captures[1]
24
+ tag ||= 'latest'
25
+ imagename = m.captures[0]
26
+ m2 = /(?:(.+)\/)?(.+)/.match(imagename)
27
+ ns = m2.captures[0]
28
+ name = m2.captures[1]
29
+ {
30
+ :ns => ns,
31
+ :name => name,
32
+ :tag => tag
33
+ }
34
+ end
35
+
36
+ def parse_with_default(image,repository)
37
+ i = parse_name(image)
38
+ unless i[:ns]
39
+ i[:ns] = repository
40
+ end
41
+ i
42
+ end
43
+
44
+ def get_image!(image)
45
+ LOG.debug { "get_image!(#{image.inspect})" }
46
+ tag = image[:tag] || 'latest'
47
+ repo = "#{image[:ns]}/#{image[:name]}"
48
+ img = [
49
+ lambda { Docker::Image.get("#{image[:name]}:#{image[:tag]}") },
50
+ lambda { Docker::Image.create('fromImage'=> image[:name], 'tag' => tag) },
51
+ lambda { Docker::Image.create('fromImage' => repo, 'tag' => tag) }
52
+ ].reduce(nil) do |result,block|
53
+ unless result
54
+ begin
55
+ result = block.call
56
+ result = Docker::Image.get(result.id)
57
+ rescue
58
+ result = nil
59
+ end
60
+ end
61
+ result
62
+ end
63
+ raise Baha::ImageNotFoundError.new(image) unless img
64
+ img
65
+ end
66
+
67
+ end
68
+ attr_reader :parent, :image, :maintainer, :options, :pre_build, :bind, :command, :timeout, :workspace, :name, :tags
69
+
70
+ def initialize(config,image)
71
+ @parent = Baha::Image.parse_with_default(image['parent'] || config.defaults[:parent], config.defaults[:repository])
72
+ @image = Baha::Image.parse_with_default(image['name'], config.defaults[:repository])
73
+ @image[:tag] = image['tag'] if image.has_key?('tag')
74
+ @maintainer = image['maintainer'] || config.defaults[:maintainer]
75
+ @options = Baha::ContainerOptions::parse_options(image['config'])
76
+ @pre_build = image['pre_build']
77
+ @bind = image['bind'] || config.defaults[:bind]
78
+ @command = image['command'] || config.defaults[:command]
79
+ @timeout = image['timeout'] || config.defaults[:timeout]
80
+ @workspace = config.workspace + (image['workspace'] || @image[:name])
81
+ @name = @image[:name]
82
+ @tags = Set.new [
83
+ "#{@image[:name]}:#{@image[:tag]}",
84
+ "#{@image[:name]}:latest"
85
+ ]
86
+ if @image[:ns]
87
+ @tags << "#{@image[:ns]}/#{@image[:name]}:#{@image[:tag]}"
88
+ @tags << "#{@image[:ns]}/#{@image[:name]}:latest"
89
+ end
90
+ end
91
+
92
+ def env
93
+ {
94
+ :parent => @parent,
95
+ :maintainer => @maintainer,
96
+ :bind => @bind,
97
+ :name => @image[:name],
98
+ :tag => @image[:tag],
99
+ :workspace => @workspace.expand_path.to_s
100
+ }
101
+ end
102
+
103
+ def parent_id
104
+ parent = Baha::Image.get_image!(@parent)
105
+ parent.id
106
+ end
107
+
108
+ def commit_config
109
+ @options.values.reduce({}) do |memo,option|
110
+ option.apply(memo)
111
+ memo
112
+ end
113
+ end
114
+
115
+ # Checks if the image needs updating
116
+ # 1. If it's parent image has changed
117
+ # 2. If the desired tag is not found
118
+ # Will raise Baha::ImageNotFoundError if the parent image can not be found
119
+ def needs_update?
120
+ LOG.debug { "needs_update?(#{@image.inspect})" }
121
+ parent = Baha::Image.get_image!(@parent)
122
+ LOG.debug { "got parent: #{parent.inspect}" }
123
+ begin
124
+ image = Baha::Image.get_image!(@image)
125
+ LOG.debug { "got image: #{image.inspect}" }
126
+ parent_id = image.info['Parent']
127
+ this_tags = image.history[0]["Tags"]
128
+ local_tag = "#{@image[:name]}:#{@image[:tag]}"
129
+ remote_tag = "#{@image[:ns]}/#{local_tag}"
130
+ LOG.debug { "current parent id = #{parent_id}" }
131
+ LOG.debug { "current image tags = #{parent_id}" }
132
+ LOG.debug { "current parent id = #{parent_id}" }
133
+ parent_id != parent.id or not ( this_tags.include?(local_tag) or this_tags.include?(remote_tag) )
134
+ rescue
135
+ true
136
+ end
137
+ end
138
+
139
+ def inspect
140
+ <<-eos.gsub(/\n?\s{2,}/,'')
141
+ #{self.class.name}<
142
+ @parent=#{@parent.inspect},
143
+ @image=#{@image.inspect},
144
+ @maintainer=#{@maintainer},
145
+ @options=#{@options.inspect},
146
+ @pre_build=#{@pre_build.inspect},
147
+ @bind=#{@bind},
148
+ @command=#{@command.inspect},
149
+ @timeout=#{@timeout}
150
+ >
151
+ eos
152
+ end
153
+ end
154
+ end
data/lib/baha/log.rb ADDED
@@ -0,0 +1,80 @@
1
+ class Baha::Log
2
+ require 'logger'
3
+ LEVELS = {
4
+ :debug => Logger::DEBUG,
5
+ :info => Logger::INFO,
6
+ :warn => Logger::WARN,
7
+ :error => Logger::ERROR,
8
+ :fatal => Logger::FATAL
9
+ }
10
+ class Formatter
11
+ Format = "%s [%5s] %s -- %s\n"
12
+
13
+ def call(severity, time, progname, msg)
14
+ Format % [time.strftime('%Y-%m-%d %H:%M:%S.%L'), severity, progname, msg2str(msg)]
15
+ end
16
+
17
+ private
18
+
19
+ def msg2str(msg)
20
+ case msg
21
+ when ::String
22
+ msg
23
+ when ::Exception
24
+ "#{ msg.message } (#{ msg.class })\n\t" <<
25
+ (msg.backtrace || []).join("\n\t")
26
+ else
27
+ msg.inspect
28
+ end
29
+ end
30
+ end
31
+ class << self
32
+ attr_reader :level, :logfile, :io
33
+ def logfile=(io)
34
+ @io = io
35
+ @logfile = Logger.new(io)
36
+ @logfile.formatter = Baha::Log::Formatter.new()
37
+ self.level = :error
38
+ end
39
+ def level=(level)
40
+ key = case level
41
+ when String
42
+ @level = level.downcase.to_sym
43
+ when Symbol
44
+ @level = level.downcase
45
+ else
46
+ raise ArgumentError.new("level must be a string or symbol")
47
+ end
48
+ raise ArgumentError.new("level must be in #{LEVELS.keys}") unless LEVELS.has_key?(key)
49
+ @level = key
50
+ self.logfile.sev_threshold = LEVELS[@level]
51
+ end
52
+ def close!
53
+ if @logfile
54
+ @logfile.close
55
+ @logfile = nil
56
+ end
57
+ end
58
+ def for_name(progname)
59
+ Baha::Log.new(progname)
60
+ end
61
+ end
62
+
63
+ attr_reader :progname
64
+
65
+ def initialize(progname)
66
+ @progname = progname
67
+ end
68
+
69
+ LEVELS.keys.each do |level|
70
+ define_method(level) do |*message, &block|
71
+ if Baha::Log.logfile
72
+ if block
73
+ Baha::Log.logfile.send(level, @progname, &block)
74
+ else
75
+ Baha::Log.logfile.send(level, @progname) { message[0] }
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,51 @@
1
+ require 'baha/pre_build'
2
+ require 'open3'
3
+
4
+ class Baha::PreBuild::Module::Command
5
+ LOG = Baha::Log.for_name("Module::Command")
6
+
7
+ def self.execute(mod)
8
+ LOG.debug("execute(#{mod.args.inspect})")
9
+ command = mod.args['command']
10
+ creates = mod.args['creates']
11
+ onlyif = mod.args['only_if']
12
+
13
+ cwd = mod.image.workspace.expand_path
14
+
15
+ if creates
16
+ filepath = cwd + creates
17
+ LOG.debug { "Checking if file exists #{filepath}"}
18
+ if filepath.exist?
19
+ LOG.info("#{creates} exists - skipping command")
20
+ return
21
+ end
22
+ end
23
+
24
+ if onlyif
25
+ exit_status = 0
26
+ LOG.info { "Running test [onlyif] #{onlyif.inspect}" }
27
+ Open3.popen2e(onlyif,:chdir=>cwd.to_s) do |stdin, oe, wait_thr|
28
+ oe.each do |line|
29
+ LOG.debug { "++ " + line }
30
+ end
31
+ exit_status = wait_thr.value # Process::Status object returned.
32
+ end
33
+ unless exit_status.success?
34
+ LOG.debug { "onlyif did not exist successfully - skipping command" }
35
+ return
36
+ end
37
+ end
38
+
39
+ LOG.info { "Running command #{command.inspect}" }
40
+ Open3.popen2e(command,:chdir=>cwd.to_s) do |stdin, oe, wait_thr|
41
+ oe.each do |line|
42
+ LOG.debug { "++ " + line.chomp }
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ Baha::PreBuild::Module.register(:command) do |mod|
50
+ Baha::PreBuild::Module::Command.execute(mod)
51
+ end
@@ -0,0 +1,28 @@
1
+ require 'baha/pre_build'
2
+ require 'open-uri'
3
+
4
+ class Baha::PreBuild::Module::Download
5
+ LOG = Baha::Log.for_name("Module::Download")
6
+
7
+ def self.execute(mod)
8
+ LOG.debug("execute(#{mod.args.inspect})")
9
+
10
+ filename = mod.image.workspace + mod.args['file']
11
+ url = mod.args['download']
12
+ overwrite = mod.args['overwrite'] || false
13
+ if Pathname.new(filename).exist? and not overwrite
14
+ LOG.info("#{filename} already exists")
15
+ else
16
+ LOG.info("Download #{url} -> #{filename}")
17
+ File.open(filename, "w") do |saved_file|
18
+ open(url, "rb") do |read_file|
19
+ saved_file.write(read_file.read)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ Baha::PreBuild::Module.register(:download) do |mod|
27
+ Baha::PreBuild::Module::Download.execute(mod)
28
+ end