extras/generate-stock-images
#!/usr/local/ruby-current/bin/ruby
# Copyright:: Copyright (c) 2019 eGlobalTech, Inc., all rights reserved
#
# Licensed under the BSD-3 license (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License in the root of the project or at
#
# http://egt-labs.com/mu/LICENSE.html
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require File.realpath(File.expand_path(File.dirname(__FILE__)+"/../bin/mu-load-config.rb"))
# now we have our global config available as the read-only hash $MU_CFG
require 'rubygems'
require 'bundler/setup'
require 'optimist'
require 'mu'
bok_dir = MU.myRoot+"/extras/image-generators"
available_clouds = {}
Dir.foreach(bok_dir) { |d|
next if d == "." or d == ".."
next if !Dir.exist?(MU.myRoot+"/extras/image-generators/"+d)
available_clouds[d] = []
Dir.foreach(bok_dir+"/"+d) { |yamlfile|
next if !yamlfile.match(/(.+?)\.yaml$/)
platform = Regexp.last_match[1]
available_clouds[d] << platform
}
}
$opts = Optimist::options do
banner <<-EOS
Usage:
#{$0} [-c <cloud>] [-p <platform>]
EOS
opt :clouds, "Clouds for which to generate images", :require => false, :type => :strings, :default => available_clouds.keys
opt :platforms, "Platforms for which to generate images", :require => false, :type => :strings, :default => available_clouds.values.flatten.sort.uniq
opt :environment, "Environment with which to tag our generated images.", :require => false, :type => :string, :default => "prod"
opt :age, "Minimum age, in days, at which we will replace existing images. Set to 0 to force a new build regardless of age.", :require => false, :type => :integer, :default => 30
if available_clouds.keys.include?("AWS")
opt :upload_to, "AWS S3 bucket and path to which we should upload our updated image list.", :require => false, :type => :string, :default => "s3://"+MU::Cloud::BASE_IMAGE_BUCKET+MU::Cloud::BASE_IMAGE_PATH
end
available_clouds.keys.each { |cloud|
opt (cloud.downcase+"_creds").to_sym, "Credentials to use when creating images in #{cloud}.", :require => false, :type => :string
}
opt :dryrun, "Don't actually run our deploy.", :require => false, :type => :boolean, :default => false
end
pwd = Dir.pwd
if !available_clouds.keys.include?("AWS") # XXX or if we don't have permissions to write $opt[:upload_to]
MU.log "No AWS credentials available- I have nowhere to upload new imaged lists. Will print to STDOUT instead.", MU::WARN
end
now = DateTime.now
exitcode = 0
succeeded = 0
$opts[:clouds].each { |cloud|
current_images = MU::Cloud.getStockImage(cloud, fail_hard: true)
$opts[:platforms].each { |platform|
if File.exists?(bok_dir+"/"+cloud+"/"+platform+".yaml")
cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud).const_get("Server")
if current_images[platform].is_a?(String)
age = cloudclass.imageTimeStamp(current_images[platform])
if (now - age) >= $opts[:age]
MU.log "#{cloud} image for #{platform} was last built #{age.to_s}, refreshing", MU::NOTICE
else
next
end
else
needed = false
if !current_images[platform]
needed = true
else
current_images[platform].each_pair { |r, img_id|
age = cloudclass.imageTimeStamp(img_id, region: r)
if (now - age) >= $opts[:age]
MU.log "#{cloud} image for #{platform} was last built #{age.to_s}, refreshing", MU::NOTICE
needed = true
break
end
}
end
next if !needed
end
MU.log "Loading "+bok_dir+"/"+cloud+"/"+platform+".yaml"
conf_engine = MU::Config.new(
bok_dir+"/"+cloud+"/"+platform+".yaml",
default_credentials: $opts[(cloud.downcase+"_creds").to_sym]
)
stack_conf = conf_engine.config
if $opts[:dryrun]
puts stack_conf.to_yaml
else
begin
deployer = MU::Deploy.new(
$opts[:environment],
stack_conf: stack_conf
)
deployer.run
MU.log "New images for #{cloud}:#{platform}", MU::NOTICE, details: deployer.mommacat.deployment['images']
current_images[platform] ||= {}
current_images.deep_merge!(deployer.mommacat.deployment['images'])
# Scrub any loose metadata left over from our image deployment. It's
# ok, this won't touch the images we just made.
MU::Cleanup.run(deployer.mommacat.deploy_id, skipsnapshots: true, verbosity: MU::Logger::QUIET)
succeeded += 1
rescue Exception => e
MU.log e.message, MU::ERR
exitcode = 1
end
end
end
}
if !$opts[:dryrun] and succeeded > 0
puts current_images.to_yaml
if available_clouds.keys.include?("AWS")
MU::Cloud::AWS::Bucket.upload($opts[:upload_to]+"/"+cloud+".yaml", data: current_images.to_yaml, credentials: $opts[:aws_creds], acl: "public-read")
end
end
}
exit exitcode