|
| 1 | +require 'mysql2' |
| 2 | +require 'ruby-progressbar' |
| 3 | + |
| 4 | +DB = Mysql2::Client.new( |
| 5 | + host: ENV['LEGACY_DB_HOST'] || 'localhost', |
| 6 | + username: ENV['LEGACY_DB_USERNAME'] || 'root', |
| 7 | + database: ENV['LEGACY_DB_DATABASE'] || 'opscode_community_site_production' |
| 8 | +) |
| 9 | + |
| 10 | +namespace :chef_legacy do |
| 11 | + desc 'Import legacy community site data from CSV files.' |
| 12 | + task :import => :environment do |
| 13 | + progress_bar = ProgressBar.create(total: cookbooks.count) |
| 14 | + |
| 15 | + import_cookbooks_with_versions_and_platforms(progress_bar) |
| 16 | + end |
| 17 | +end |
| 18 | + |
| 19 | +# |
| 20 | +# Parses cookbooks.csv, cookbook_versions.csv and |
| 21 | +# platform_versions.csv Then the cookbooks and their dependencies |
| 22 | +# (Category and CookbookVersion) are associated/created. The cookbook |
| 23 | +# Category is found by using a column in each cookbook row named category_name |
| 24 | +# derived from joining the categories and cookbooks table from the original |
| 25 | +# legacy database. For each cookbook row the corresponding cookbook version |
| 26 | +# rows are found by selecting rows from cookbook_versions.csv |
| 27 | +# where the column cookbook_id matches the current cookbook row id. |
| 28 | +# Each instance of CookbookVersion is created with a hard coded |
| 29 | +# tarball_content_type of application/x-gzip because of inconsistencies |
| 30 | +# in the legacy database application/x-gzip is the desired content type |
| 31 | +# as all of the legacy tarballs are tgz files. For each CookbookVersion |
| 32 | +# the supported platforms are created and associated by finding the corresponding |
| 33 | +# platform version rows by matching the current cookbook version row id with the |
| 34 | +# platform version row id. |
| 35 | +# |
| 36 | +def import_cookbooks_with_versions_and_platforms(progress_bar) |
| 37 | + cookbooks.each do |row| |
| 38 | + progress_bar.increment |
| 39 | + |
| 40 | + next if Cookbook.with_name(row['name']).first |
| 41 | + |
| 42 | + category_name = categories.find do |category| |
| 43 | + category['id'] == row['category_id'] |
| 44 | + end.fetch('name') |
| 45 | + |
| 46 | + category = Category.with_name(category_name).first_or_initialize |
| 47 | + |
| 48 | + if row['external_url'].to_s.strip.size > 0 |
| 49 | + external_url = URI(row['external_url']) |
| 50 | + |
| 51 | + unless external_url.is_a?(URI::HTTP) || external_url.is_a?(URI::HTTPS) |
| 52 | + external_url = URI('http://' + row['external_url']) |
| 53 | + end |
| 54 | + else |
| 55 | + external_url = nil |
| 56 | + end |
| 57 | + |
| 58 | + cookbook = Cookbook.new( |
| 59 | + name: row['name'], |
| 60 | + maintainer: 'john@example.com', |
| 61 | + description: row['description'], |
| 62 | + category: category, |
| 63 | + source_url: external_url.to_s, |
| 64 | + download_count: row['download_count'], |
| 65 | + deprecated: row['deprecated'], |
| 66 | + ) |
| 67 | + |
| 68 | + build_cookbook_versions(row['id']).each do |cookbook_version| |
| 69 | + cookbook_version.cookbook = cookbook |
| 70 | + cookbook.cookbook_versions << cookbook_version |
| 71 | + end |
| 72 | + |
| 73 | + cookbook.save! |
| 74 | + end |
| 75 | +end |
| 76 | + |
| 77 | +def build_cookbook_versions(cookbook_id) |
| 78 | + cookbook_versions. |
| 79 | + select { |v| v['cookbook_id'] == cookbook_id }. |
| 80 | + map do |version| |
| 81 | + |
| 82 | + CookbookVersion.new( |
| 83 | + version: version['version'], |
| 84 | + license: version['license'], |
| 85 | + tarball_file_name: version['tarball_file_name'], |
| 86 | + tarball_content_type: 'application/x-gzip', |
| 87 | + tarball_file_size: version['tarball_file_size'], |
| 88 | + tarball_updated_at: version['tarball_updated_at'], |
| 89 | + download_count: version['download_count'], |
| 90 | + ).tap do |cookbook_version| |
| 91 | + build_supported_platforms(version['id']).each do |supported_platform| |
| 92 | + supported_platform.cookbook_version = cookbook_version |
| 93 | + cookbook_version.supported_platforms << supported_platform |
| 94 | + end |
| 95 | + end |
| 96 | + end |
| 97 | +end |
| 98 | + |
| 99 | +def build_supported_platforms(cookbook_version_id) |
| 100 | + platform_versions. |
| 101 | + select { |p| p['cookbook_version_id'] == cookbook_version_id }. |
| 102 | + map do |platform| |
| 103 | + |
| 104 | + version_constraint = platform['version'] || '>= 0.0.0' |
| 105 | + |
| 106 | + if version_constraint != '>=0.0.0' |
| 107 | + numeric_part = version_constraint.split(' ').last |
| 108 | + |
| 109 | + if numeric_part.size == 1 |
| 110 | + version_constraint << '.0' # Corrects, e.g., '~> 5' to '~> 5.0' |
| 111 | + end |
| 112 | + else |
| 113 | + version_constraint = '>= 0.0.0' |
| 114 | + end |
| 115 | + |
| 116 | + SupportedPlatform.new( |
| 117 | + name: platform['platform'], |
| 118 | + version_constraint: version_constraint |
| 119 | + ) |
| 120 | + end |
| 121 | +end |
| 122 | + |
| 123 | +def categories |
| 124 | + @categories ||= DB.query('select * from categories').to_a |
| 125 | +end |
| 126 | + |
| 127 | +def cookbooks |
| 128 | + @cookbooks ||= DB.query('select * from cookbooks').to_a |
| 129 | +end |
| 130 | + |
| 131 | +def cookbook_versions |
| 132 | + @cookbook_versions ||= DB.query('select * from cookbook_versions').to_a |
| 133 | +end |
| 134 | + |
| 135 | +def platform_versions |
| 136 | + @platform_versions ||= DB.query('select * from platform_versions').to_a |
| 137 | +end |
| 138 | + |
| 139 | +# |
| 140 | +# Parses a given CSV file found in the data directory. |
| 141 | +# |
| 142 | +def parse_csv(filename) |
| 143 | + CSV.parse(File.read(File.join(File.dirname(__FILE__), "data/#{filename}")), headers: true) |
| 144 | +end |
0 commit comments