Merge remote-tracking branch 'origin/release/8.3' into dev

pull/7269/head
Oliver Günther 6 years ago
commit e850b2fc60
No known key found for this signature in database
GPG Key ID: A3A8BDAD7C0C552C
  1. 10
      Dockerfile
  2. 22
      db/migrate/20180105130053_rebuild_dag.rb
  3. 5
      db/migrate/20180510184732_rename_planning_elemnt_type_colors_to_colors.rb
  4. 4
      docker/entrypoint.sh
  5. 22
      docker/mysql-to-postgres/Dockerfile
  6. 21
      docker/mysql-to-postgres/bin/build
  7. 180
      docker/mysql-to-postgres/bin/migrate-mysql-to-postgres

@ -18,6 +18,8 @@ ENV OPENPROJECT_INSTALLATION__TYPE docker
ENV NEW_RELIC_AGENT_ENABLED false
ENV ATTACHMENTS_STORAGE_PATH $APP_DATA_PATH/files
ENV PGLOADER_DEPENDENCIES "libsqlite3-dev make curl gawk freetds-dev libzip-dev"
# Set a default key base, ensure to provide a secure value in production environments!
ENV SECRET_KEY_BASE OVERWRITE_ME
@ -35,10 +37,18 @@ RUN apt-get update -qq && \
memcached \
postfix \
postgresql \
$PGLOADER_DEPENDENCIES \
apache2 \
supervisor && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# pgloader
ENV CCL_DEFAULT_DIRECTORY /opt/ccl
COPY docker/mysql-to-postgres/bin/build /tmp/build-pgloader
RUN /tmp/build-pgloader && rm /tmp/build-pgloader
# Add MySQL-to-Postgres migration script to path (used in entrypoint.sh)
COPY docker/mysql-to-postgres/bin/migrate-mysql-to-postgres /usr/local/bin/
# Set up pg defaults
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.6/main/pg_hba.conf
RUN echo "listen_addresses='*'" >> /etc/postgresql/9.6/main/postgresql.conf

@ -58,16 +58,18 @@ class RebuildDag < ActiveRecord::Migration[5.0]
def down
remove_column :relations, :count
remove_index :relations,
name: 'index_relations_hierarchy_follows_scheduling'
remove_index :relations,
name: 'index_relations_only_hierarchy'
remove_index :relations,
name: 'index_relations_to_from_only_follows'
remove_index :relations,
name: 'index_relations_direct_non_hierarchy'
remove_index :relations,
name: 'index_relations_on_type_columns'
if index_exists? :relations, 'index_relations_hierarchy_follows_scheduling'
remove_index :relations,
name: 'index_relations_hierarchy_follows_scheduling'
remove_index :relations,
name: 'index_relations_only_hierarchy'
remove_index :relations,
name: 'index_relations_to_from_only_follows'
remove_index :relations,
name: 'index_relations_direct_non_hierarchy'
remove_index :relations,
name: 'index_relations_on_type_columns'
end
truncate_closure_entries
end

@ -6,6 +6,11 @@ class RenamePlanningElemntTypeColorsToColors < ActiveRecord::Migration[5.1]
rename_index :planning_element_type_colors, :timelines_colors_pkey, :planning_element_type_colors_pkey
end
if ActiveRecord::Base.connection.execute("SELECT 1 as value FROM pg_class c WHERE c.relkind = 'S' and c.relname = 'planning_element_type_colors_id_seq'").to_a.present?
puts "Renaming id_seq to pkey which seems to be required by rename_table"
rename_index :planning_element_type_colors, :planning_element_type_colors_id_seq, :planning_element_type_colors_pkey
end
rename_table :planning_element_type_colors, :colors
remove_column :colors, :position
end

@ -5,6 +5,10 @@ set -o pipefail
APACHE_PIDFILE=/run/apache2/apache2.pid
if [ -n "$DATABASE_URL" ]; then
/usr/local/bin/migrate-mysql-to-postgres || exit 1
fi
# handle legacy configs
if [ -d "$PGDATA_LEGACY" ]; then
echo "WARN: You are using a legacy volume path for your postgres data. You should mount your postgres volumes at $PGDATA instead of $PGDATA_LEGACY."

@ -0,0 +1,22 @@
FROM ruby:2.6-stretch
MAINTAINER operations@openproject.com
ENV PGLOADER_DEPENDENCIES "libsqlite3-dev make curl gawk freetds-dev libzip-dev"
# Install
#
# 1) mysql and postgres clients
# 2) pgloader dependencies minus SBCL since we use CCL
RUN apt-get update -qq && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
mysql-client postgresql-client \
$PGLOADER_DEPENDENCIES && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# pgloader
ENV CCL_DEFAULT_DIRECTORY /opt/ccl
COPY docker/mysql-to-postgres/bin/build /tmp/build-pgloader
RUN /tmp/build-pgloader && rm /tmp/build-pgloader
COPY docker/mysql-to-postgres/bin/migrate-mysql-to-postgres /usr/local/bin/
CMD ["migrate-mysql-to-postgres"]

@ -0,0 +1,21 @@
#!/bin/bash
set -e
cd /opt
# install Clozure CL to avoid memory issues with the standard SBCL
wget -q https://github.com/Clozure/ccl/releases/download/v1.11.5/ccl-1.11.5-linuxx86.tar.gz
tar -xzf ccl-1.11.5-linuxx86.tar.gz
rm ccl-1.11.5-linuxx86.tar.gz
ln -s /opt/ccl/scripts/ccl64 /usr/local/bin/ccl
export CCL_DEFAULT_DIRECTORY=/opt/ccl
# build pgloader from source using CCL as the lisp runtime
git clone https://github.com/dimitri/pgloader.git
cd pgloader
git checkout v3.6.1
make CL=ccl pgloader >& /tmp/pgloader-compile.log || (cat /tmp/pgloader-compile.log && exit 1)
mv /opt/pgloader/build/bin/pgloader /usr/local/bin/pgloader-ccl
rm -rf /opt/pgloader

@ -0,0 +1,180 @@
#!/usr/bin/env ruby
require 'uri'
db_url = URI(ENV.fetch("DATABASE_URL"))
mysql_url = URI(ENV.fetch("MYSQL_DATABASE_URL")) if ENV.has_key?("MYSQL_DATABASE_URL")
if db_url.scheme.start_with?("mysql")
puts "WARNING: You are running MySQL. OpenProject will drop support for MySQL in 10.0."
puts " We can convert it to Postgres for you. Please setup postgres and "
puts " rerun this with MYSQL_DATABASE_URL pointing to your original database "
puts " and DATABASE_URL pointing to a new Postgres database."
puts ""
puts "EXAMPLE: docker run \\"
puts " -e MYSQL_DATABASE_URL=mysql://openproject:<PASSWORD>@localhost:3306/openproject \\"
puts " -e DATABASE_URL=postgresql://openproject:<PASSWORD>@localhost:5432/openproject \\"
puts " -it openproject/community:latest"
exit 0 # MySQL still supported until 9.x - with 10.0 we must make this an error (exit 1)
end
if db_url.scheme.start_with?("postgresql") && mysql_url.nil?
# nothing to do
exit 0
end
filtered_mysql_url = mysql_url.dup.tap{|url| url.password = "REDACTED"}
filtered_db_url = db_url.dup.tap{|url| url.password = "REDACTED"}
puts "Migrating database from MySQL to PostgreSQL."
puts
puts "Import"
puts " MySQL database"
puts " #{filtered_mysql_url.to_s}"
puts " into Postgres database "
puts " #{filtered_db_url.to_s}"
puts " ?"
puts "WARNING: This resets the given Postgres database."
puts
print "Y/n "
answer = ENV.fetch("FORCE_YES") { gets.chomp }
if answer.downcase == "n"
exit 0
end
db_user, db_password, db_host, db_port, db_name = db_url.user, db_url.password, db_url.host, db_url.port, db_url.path.sub("/", "")
db_port ||= 5432
if [db_host, db_name, db_port].any?{|value| [nil, ""].include?(value)}
puts "ERROR: Could not parse database URL (#{filtered_db_url})"
exit 1
end
require 'pty'
# Memcached is not yet running at this point so we use the file cache store.
# This will and is supposed to affect the spawned ruby processes.
ENV["RAILS_CACHE_STORE"] = "file_store"
def run(cmd, silent: false, record_output: true)
output = []
PTY.spawn(cmd) do |stdout, stdin, pid|
begin
stdout.each do |line|
output << line if record_output
puts line unless silent
end
rescue Errno::EIO
# raised when stdout is closed after process finished
ensure
stdout.close
stdin.close
end
Process.wait pid
end
[output.join("\n").strip, $?.to_i]
end
puts "Resetting target database..."
drop_cmd = "PGPASSWORD=#{db_password} psql -U #{db_user} -h #{db_host} -p #{db_port} -d postgres -c 'DROP DATABASE #{db_name}'"
drop_output, _ = run drop_cmd, silent: true
if drop_output.include?("database \"#{db_name}\" does not exist") || drop_output == "DROP DATABASE"
# that's ok then we don't have to drop it or dropped database successfully
puts "Database dropped"
else
puts drop_output
exit 1 # something went wrong
end
puts "Creating database..."
create_cmd = "PGPASSWORD=#{db_password} psql -U #{db_user} -h #{db_host} -p #{db_port} -d postgres -c 'CREATE DATABASE #{db_name}'"
create_output, _ = run create_cmd, silent: true
if create_output == "CREATE DATABASE"
# created database successfully
else
puts create_output
exit 1 # something went wrong
end
puts "Importing database ..."
mysql_url.query = nil
mysql_url.scheme = "mysql"
_, pgloader_status = run "pgloader-ccl --verbose #{mysql_url} #{db_url}", record_output: false
if pgloader_status != 0
puts "\nFailed to import MySQL database into Postgres. See above."
exit 1
end
check_fulltext_cmd = "PGPASSWORD=#{db_password} psql -o /dev/stdout -U #{db_user} -h #{db_host} -p #{db_port} -d #{db_name} -c \"select 'true' from schema_migrations where version = '20180122135443'\""
check_output, check_status = run check_fulltext_cmd, silent: true
if check_status != 0
puts check_output
puts "Failed to check full-text status of database. See above."
exit 1
end
# if the version was present on MySQL already we need to redo it to
# add the postgres specific columns.
needs_fulltext_migration = check_output.include?("true")
puts "Migrating database ..."
_, migrate_status = run "bundle exec rake db:migrate", record_output: false
if migrate_status != 0
puts "\nMigration failed. See above."
end
if needs_fulltext_migration
drop_version_cmd = "PGPASSWORD=#{db_password} psql -U #{db_user} -h #{db_host} -p #{db_port} -d #{db_name} -c \"delete from schema_migrations where version = '20180122135443'\""
drop_version_output, drop_version_status = run drop_version_cmd, silent: true
if drop_version_status != 0
puts drop_version_output
puts "Failed to drop schema_migrations entry. See above."
exit 1
end
puts "Running full-text search migration"
_, redo_status = run "bundle exec rake db:migrate:up VERSION=20180122135443", record_output: false
if redo_status != 0
puts "\nFull-text search migration failed. See above."
exit 1
end
_, extract_status = run "bundle exec rake attachments:extract_fulltext_where_missing", record_output: false
if extract_status != 0
puts "\nFull-text extraction failed. See above."
exit 1
end
end
puts "\nRe-building DAG to create Postgres-specific indices"
_, dag_status = run "bundle exec rake db:migrate:redo VERSION=20180105130053", record_output: false
if dag_status != 0
puts "\nRebuild DAG migration failed. See above."
exit 1
end
puts "Migration from MySQL to Postgres completed successfully!"
Loading…
Cancel
Save