class RightImageTools::S3HtmlIndexer
Public Class Methods
new(bucket, id=nil, key=nil)
click to toggle source
# File lib/s3_html_indexer.rb, line 10 def initialize(bucket, id=nil, key=nil) @s3 = RightAws::S3.new(id, key) @dev_bucket = bucket.downcase.include?("dev") # If the bucket holds base images. @base_bucket = bucket.downcase.include?("rightimage-base") # If the bucket holds reports for the public clouds, ec2, Google, or Azure. @public_bucket = bucket.downcase =~ /ec2|google|azure/ @cloudstack_bucket = bucket.downcase.include?("cloudstack") @bucket = @s3.bucket(bucket) @keys = @bucket.keys @auto_hash = Hash.new{ |h,k| h[k] = Hash.new &h.default_proc } end
Public Instance Methods
to_html(filename)
click to toggle source
# File lib/s3_html_indexer.rb, line 26 def to_html(filename) # Create hash hierarchy from bucket list #@keys.sort! {|x,y| ver(x.full_name) <=> ver(y.full_name) } #TODO: sort by rightlink version @keys.each do |path| next unless is_public?(path) path_key = path.full_name # Ignore index.html and report_viewer.html . next if path_key =~ /index.html/ next if path_key =~ /report_viewer.html/ path_key.gsub!('xen/','xenserver/') path_key.gsub!(/(vmware|esxi)\/(vmware|esxi)\//,'esxi/') path_key.gsub!('vmware/','esxi/') #if path_key.split("/").size != 5 # puts "WARNING: Skipping malformed path: #{path}" # next #end # Skip files if they are too small to be an image. # Except for mega cloud buckets that collect reports. if path.size.to_i < 1024*1024*100 and not @public_bucket puts "WARNING: Skipping #{path}: it appears to be too small (<100 MB) to be an image" next end sub = @auto_hash path_key.split( "/" ).each do |dir| sub = sub[dir] end # Retrieve image and report links duple. links = fix_public_endpoint(path.public_link) sub[:link] = links[0] sub[:report] = links[1] sub[:size] = path.size sub[:date] = path.last_modified.strftime("%m/%d/%Y") sub[:md5sum] = path.e_tag.gsub(/\"/, "") end # make a non-auto hash copy dirs = Hash.new dirs = dirs.merge(@auto_hash) # visualize hierarchy dirs.each do |k,v| @file = File.open(filename, "w") output("<html>") add_style display_dirs(k,v) output("</html>") puts "Output written to #{@file.path}" @file.close end end
upload_index(filename)
click to toggle source
# File lib/s3_html_indexer.rb, line 85 def upload_index(filename) # if File.exists?("index.html") @bucket.put("index.html", File.open(filename), {}, 'public-read') File.delete("index.html") # Upload amalgamated report_viewer.html with index.html. Dir.chdir(File.join(File.dirname(File.expand_path(__FILE__)), "..", "ui", "build")) @bucket.put("report_viewer.html", File.open("report_viewer.html"), {}, 'public-read') else # Upload index.html for empty buckets. Dir.chdir(File.join(File.dirname(File.expand_path(__FILE__)), "..", "ui", "build")) @bucket.put("index.html", File.open("empty_bucket_index.html"), {}, 'public-read') puts "Uploaded empty bucket index.html." end end
Private Instance Methods
add_header(str, level)
click to toggle source
# File lib/s3_html_indexer.rb, line 179 def add_header(str, level) case level when 0 # bucket name output("<div id='header'><img alt='Embedded Image' width='140' height='19' src='#{encoded_logo}' /></div>") output("<div class='bucket common'>#{str.gsub(/rightscale-/,"").upcase}") output("<br/><br/>") output("<div class='disclaimer code common'>#{disclaimer}</div>") output("<br/>") output("</div>") when 1 # Hypervisor output("<div class='hypervisor common'>") # Include "Hypervisor" in subheader if not base image bucket. if @base_bucket output("<h#{level-1}>#{str.upcase}</h#{level-1}>\n") else output("<h#{level-1}>#{str.upcase} Hypervisor</h#{level-1}>\n") end output("</div>") output("<div class='platform common'>") output("<table style='padding:none; size:90%'>") output("<tr style='border: solid 1px black;'>") output("<th style='text-align:left'>Image</th>") # Leave 'Notes' header empty. output("<th></th>") if not @public_bucket output("<th>Size</th>") output("<th>Date</th>") output("<th>MD5</th>") else output("<th>Date</th>") end output("</tr>") when 2 return # OS when 3 return # OS Version else return # image # output("<div class='platform'>") end end
add_style()
click to toggle source
# File lib/s3_html_indexer.rb, line 291 def add_style output "<style>" output( "body {min-width: 600px; margin:0; padding:0; font-size:70.5%; /* font-family:'Lucida Sans', Verdana, Arial, sans-serif; */ font-family:'Lucida Grande','Lucida Sans Unicode','Lucida Sans',Verdana,lucida,sans-serif; background:#FFF; height:100%} html {height:100%} a img {border:none} a {color:#1e4a7e} table { width:90% } th { text-align:center } #header { background:#235186; padding:2px 20px; position:relative; height:25px; } #header #logo { margin-top:3px; } .common { font-size: 16px; margin-left:auto; margin-right:auto; font-weight: bold; padding:2px 20px; position:relative; } .bucket { font-size: 24px; color: #F5F2A9; background:#235186; padding:10px 30px 20px; } .version { color: #F5F2A9; background:#235186; } .hypervisor { color: #235186; background:#F5F2A9; } .platform { background: #FFFFFF; width:90%; margin-left: auto ; margin-right: auto ; position: relative; } .disclaimer { background: #FFFFFF; width:90%; margin-left: auto ; margin-right: auto ; position: relative; border: 2px solid black; font-weight: normal; } .code { font-family:'Courier New', monospace; color: #000000; position:relative; left:10px; } ") output "</style>" end
disclaimer()
click to toggle source
Refer to “Base Images” or “RightImages” based on bucket.
# File lib/s3_html_indexer.rb, line 164 def disclaimer if @dev_bucket prod_bucket = @bucket.name.sub("-dev","") disclaimer = "The following " disclaimer << (@base_bucket ? "Base Images" : "RightImages") disclaimer << " are currently in RightScale development and testing. They are not supported by RightScale. For " disclaimer << (@base_bucket ? "Base Images" : "RightImages") disclaimer << " that RightScale supports, please see our <a href='http://#{prod_bucket}.s3.amazonaws.com/index.html'>production images</a>." else disclaimer = "The following " disclaimer << (@base_bucket ? "Base Images" : "RightImages") disclaimer << " are tested and supported by RightScale for general use. For further information regarding use of these images with RightScale, please contact your RightScale account manager or sign up for an account at <a href='http://www.rightscale.com'>www.rightscale.com</a>." end end
display_dirs(k,v,level=0)
click to toggle source
# File lib/s3_html_indexer.rb, line 125 def display_dirs(k,v,level=0) return unless v unless v.keys.include?(:link) add_header(k, level) v.sort_by {|k2, v2| k2}.each do |k2, v2| display_dirs(k2, v2, level+1) end add_footer(k, level) else output("<tr class='code'>") # Link to images stored on S3 bucket. if not @public_bucket output("<td><a href='#{v[:link]}'>#{k}</a></td>") # Otherwise, the bucket only collects reports. else # Remove '.js.' extension in public cloud buckets. kp = k.gsub(/\.js$/,"") output("<td>#{kp}</td>") end # If bucket does not have report key, do not add "notes" link. if not v[:report].empty? output("<td><a href='#{v[:report]}'>notes</a></td>") else # Empty 'notes' cell. output("<td></td>") end # Hide fields for public cloud images. if not @public_bucket output("<td>#{v[:size].to_i/(1024*1024)}MB</td>") output("<td>#{v[:date]}</td>") output("<td>#{v[:md5sum]}</td>") else output("<td>#{v[:date]}</td>") end output("</tr>") end end
encoded_logo()
click to toggle source
# File lib/s3_html_indexer.rb, line 365 def encoded_logo "data:image/png;base64,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%3D%3D" end
fix_public_endpoint(link)
click to toggle source
s3.amazonaws.com/rightscale-cloudstack/foo to rightscale-cloudstack.s3.amazonaws.com
# File lib/s3_html_indexer.rb, line 248 def fix_public_endpoint(link) link = link.dup # http apparently more reliable than https when importing cloudstack images (w-4839) if @cloudstack_bucket link.sub!("https","http") link.sub!(":443","") end link_ary = link.split("/") bucket = link_ary[3] host = link_ary[2] link_ary[2] = "#{bucket}.#{host}" link_ary.delete_at(3) new_link = link_ary.join("/") # Relative link to report. link_ary.slice!(1..2) #!!! Change the (usually double) compressed image extension to ".js". #if not @public_bucket # link_ary[-1].gsub!(/\.[^.]+\.[^.]+$/,'.js') #end # If report doesn't exist, return empty string. # Relative url begins at link_ary[1]. if not RightAws::S3::Key.create(@bucket,link_ary.slice(1..-1).join("/").gsub!(/\.[^.]+\.[^.]+$/,'.js')).exists? return [new_link , ''] end # Replace "https://" with image viewer prefix. link_ary[0] = 'report_viewer.html?image=' report_link = link_ary.join("/") # Return image link and report link. return [new_link , report_link] end
is_public?(key)
click to toggle source
# File lib/s3_html_indexer.rb, line 107 def is_public?(key) key.refresh # puts "Key: #{key.name}" is_public = false key.grantees.each do |g| # puts "grantee:#{g.name} perms:#{g.perms}" if g.name.to_s == "AllUsers" && g.perms.to_s == "READ" is_public = true end end if is_public puts "PUBLIC: #{key.name}" else puts "NOT PUBLIC: #{key.name}" end return is_public end
output(str)
click to toggle source
# File lib/s3_html_indexer.rb, line 287 def output(str) @file.write "#{str}\n" if @file end
ver(key)
click to toggle source
# File lib/s3_html_indexer.rb, line 103 def ver(key) key.match(/v[0-9]+\.[0-9]+\.[0-9]+/).to_s end