123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- #!/usr/bin/env ruby
- # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
- require 'yaml'
- require 'resolv'
- require 'fileutils'
- #
- # Configures the CI system
- # - either (randomly) mysql or postgresql, if it is available
- # - (randomly) Redis or File as web socket session back end, if Redis is available
- #
- # Database config happens directly in config/database.yml, other settings are written to
- # .gitlab/environment.env which must be sourced in the CI configuration.
- #
- class ConfigureEnvironment
- @env_file_content = <<~ENV_FILE_CONTENT
- #!/bin/bash
- FRESHENVFILE=fresh.env && test -f $FRESHENVFILE && source $FRESHENVFILE
- true
- ENV_FILE_CONTENT
- def self.configure_database # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
- if File.exist? File.join(__dir__, '../config/database.yml')
- puts "'config/database.yml' already exists and will not be changed."
- return
- end
- cnf = YAML.load_file(File.join(__dir__, '../config/database/database.yml'))
- cnf.delete('default')
- database = ENV['ENFORCE_DB_SERVICE']
- # Lookup in /etc/hosts first: gitlab uses that if FF_NETWORK_PER_BUILD is not set.
- if !database
- hostsfile = '/etc/hosts'
- database = %w[postgresql mysql].shuffle.find do |possible_database|
- File.foreach(hostsfile).any? { |l| l[possible_database] }
- end
- end
- # Lookup via DNS if needed: gitlab uses that if FF_NETWORK_PER_BUILD is enabled.
- if !database
- dns = Resolv::DNS.new
- dns.timeouts = 3
- database = %w[postgresql mysql].shuffle.find do |possible_database|
- # Perform a lookup of the database host to check if it is configured as a service.
- if dns.getaddress possible_database
- next possible_database
- end
- rescue Resolv::ResolvError
- # Ignore DNS lookup errors
- end
- end
- raise "Can't find any supported database." if database.nil?
- puts "Using #{database} as database service."
- db_settings_map = {
- 'postgresql' => {
- 'adapter' => 'postgresql',
- 'username' => 'zammad',
- 'password' => 'zammad',
- 'host' => 'postgresql', # db alias from gitlab-ci.yml
- },
- 'mysql' => {
- 'adapter' => 'mysql2',
- 'username' => 'root',
- 'password' => 'zammad',
- 'host' => 'mysql', # db alias from gitlab-ci.yml
- }
- }
- # fetch DB settings from settings map and fallback to postgresql
- db_settings = db_settings_map.fetch(database) { db_settings_map['postgresql'] }
- %w[development test production].each do |environment|
- cnf[environment].merge!(db_settings)
- end
- File.write(File.join(__dir__, '../config/database.yml'), Psych.dump(cnf))
- end
- def self.configure_redis
- if ENV['REDIS_URL'].nil? || ENV['REDIS_URL'].empty? # rubocop:disable Rails/Blank
- if database_type == 'mysql'
- raise 'Redis was not found, but is required for ActionCable on MySQL based systems.'
- end
- puts 'Redis is not available, using File as web socket session store.'
- puts 'Redis is not available, using the PostgreSQL adapter for ActionCable.'
- return
- end
- if database_type == 'mysql' || [true, false].sample
- puts 'Using Redis as web socket session store.'
- puts 'Using the Redis adapter for ActionCable.'
- return
- end
- puts 'Using File as web socket session store.'
- puts 'Using the PostgreSQL adapter for ActionCable.'
- @env_file_content += "unset REDIS_URL\n"
- end
- def self.configure_memcached
- if ENV['MEMCACHE_SERVERS'].nil? || ENV['MEMCACHE_SERVERS'].empty? # rubocop:disable Rails/Blank
- puts 'Memcached is not available, using File as Rails cache store.'
- return
- end
- if [true, false].sample
- puts 'Using memcached as Rails cache store.'
- return
- end
- puts "Using Zammad's file store as Rails cache store."
- @env_file_content += "unset MEMCACHE_SERVERS\n"
- end
- # Since configure_database skips if database.yml already exists, check the
- # content of that file to reliably determine the database type in all cases.
- def self.database_type
- database = File.read(File.join(__dir__, '../config/database.yml')).match(%r{^\s*adapter:\s*(mysql|postgresql)})[1]
- if !database
- raise 'Could not determine database type, cannot setup cable.yml'
- end
- database
- end
- def self.write_env_file
- File.write(File.join(__dir__, 'environment.env'), @env_file_content)
- end
- def self.run
- configure_database
- configure_redis
- configure_memcached
- write_env_file
- end
- end
- ConfigureEnvironment.run
|