【问题标题】:DDEV multisite setup with Acquia pull使用 Acquia pull 的 DDEV 多站点设置
【发布时间】:2021-07-23 15:25:46
【问题描述】:

我刚刚完成了 DDEV 设置,并且通过手动运行 ddev import-db --target-db=[db-name] 进行了多站点工作。它工作得很好,但我想弄清楚如何从 Acquia 获取数据库拉取,以便我可以指定要从中提取的站点。

我有这个脚本可以运行,但是有没有办法使用 DDEV 命令来做到这一点,这样会更干净一点?

首先我将 acquia.yaml 修改为:

environment_variables:
  project_id: mysite.dev
  uri: mysite.com
  db_name: mysite_us

#uri: mysite.ca
#db_name: mysite_canada

#uri: mysite.co.uk
#db_name: mysite_unitedkingdom

# etc etc

db_pull_command:
  command: |
    # set -x   # You can enable bash debugging output by uncommenting
    ls /var/www/html/.ddev >/dev/null # This just refreshes stale NFS if possible
    pushd /var/www/html/.ddev/.downloads >/dev/null
    acli remote:drush -n ${project_id} -- sql-dump --extra-dump=--no-tablespaces --uri=${uri}  >${db_name}.sql

然后我编写了以下脚本,我称之为:

./ddev-refresh-db.sh mysite_us mysite.com
#!/bin/bash

site="$1"
uri="$2"

ddev pull acquia
ddev import-db --target-db=${site} --src=.ddev/.downloads/${site}.sql
ddev drush --uri=${uri} cr

但是,这仍然需要我们在运行此命令之前更改 acquia.yaml 文件中的站点和 URI。

有没有办法将变量传递给 ddev pull acquia ?还有一种方法可以用真实的 DDEV 命令模拟这个脚本正在做什么?

【问题讨论】:

    标签: drupal ddev acquia


    【解决方案1】:

    这里是 Acquia 多站点拉取的更完整答案,拉取 所有 站点。从 DDEV v1.18.0 开始,ddev pull 本身确实不够健壮,无法拉取多个站点,因为它假定一个数据库和一组文件。这适用于@kelly howard 在https://stackoverflow.com/a/68553116/215713 中的回答不足的情况。 (在她的示例中,她只提取了一个多站点,这非常适合这种情况。)

    但是在这里我们将把所有逻辑放在一个 DDEV 自定义命令中,并为任何命名站点提取所有数据库和文件,所以 ddev acquiapull <sitename>

    将此文件作为.ddev/commands/web/acquiapull放在项目中

    #!/bin/bash
    
    # This DDEV custom command is set up to pull database and files from Acquia for several subsites.
    # Usage: `ddev acquiapull [ --skip-db ] [ --skip-files ] <site1> <site2>
    # Example: `ddev acquiapull subsite1`
    
    # This assumes that each subsite has its own database (named for the site)
    # and that each subsite has its own files in sites/<sitename>/files
    
    # To use it set up the needed ACQUIA_API_KEY and ACQUIA_API_SECRET in global 
    # or project config, just as described in 
    # https://ddev.readthedocs.io/en/stable/users/providers/acquia/
    
    acquia_project_id=myprojectid.dev
    tmpdir=/tmp  #inside web container
    
    set -eu -o pipefail
    
    while :; do
      case ${1:-} in
      -h | -\? | --help)
        show_help
        exit
        ;;
      -y|--yes)
        SKIP_CONFIRMATION=true
        ;;
      --skip-files)
        SKIP_FILES=true
        ;;
      --skip-db)
        SKIP_DB=true
        ;;
      --) # End of all options.
        shift
        break
        ;;
      -?*)
        printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
        ;;
      *) # Default case: No more options, so break out of the loop.
        break ;;
      esac
    
      shift
    done
    
    
    # Map sitename to database name
    function target_db_name() {
      site_name=$1
      echo $site_name
    }
    
    # Map sitename to files dir
    function target_files_dir() {
      site_name=$1
      echo "sites/${site_name}/files"
    }
    
    # Get the files from upstream and load them.
    function files_pull() {
      #set -x                           # You can enable bash debugging output by uncommenting
      set -eu -o pipefail
      site_name=$1
      files_dir=$(target_files_dir $1)
      mkdir -p ${DDEV_DOCROOT}/${files_dir}/
      echo "Using drush rsync to update files for ${site_name}..."
      drush rsync --alias-path=~/.drush -q -y -r ${DDEV_DOCROOT} --verbose @${acquia_project_id}:${files_dir}/ ${DDEV_DOCROOT}/${files_dir}/
    }
    
    # Get the db from upstream and load it
    function db_pull() {
      #set -x   # You can enable bash debugging output by uncommenting
      set -eu -o pipefail
      site_name=$1
      target_db=$(target_db_name ${site_name})
      echo "Downloading ${site_name} database..."
      acli remote:drush -n ${acquia_project_id} -- sql-dump --uri=${site_name} --extra-dump=--no-tablespaces >${tmpdir}/${site_name}.sql
      echo "Loading ${site_name} into database '${target_db}'..."
      mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS ${target_db}; GRANT ALL ON ${target_db}.* TO 'db'@'%'"
      mysql -uroot -proot ${target_db} <${tmpdir}/${site_name}.sql
      drush -r root --uri=${site_name} cr
    }
    
    # Handle initial authentication via Acquia secrets and ssh
    function authenticate() {
      if [ -z "${ACQUIA_API_KEY:-}" ] || [ -z "${ACQUIA_API_SECRET:-}" ]; then echo "Please make sure you have set ACQUIA_API_KEY and ACQUIA_API_SECRET in your project or global config" && exit 1; fi
      if ! command -v drush >/dev/null; then echo "Please make sure your project contains drush, ddev composer require drush/drush" && exit 1; fi
      ssh-add -l >/dev/null || (echo "Please 'ddev auth ssh' before running this command." && exit 1)
      acli auth:login -n --key="${ACQUIA_API_KEY}" --secret="${ACQUIA_API_SECRET}"
      acli remote:aliases:download -n >/dev/null
    }
    
    # Main script
    authenticate || (printf "Failed to authenticate" && exit $?)
    
    if [ $# -eq 0 ]; then
      printf "Usage: ddev acquiapull [ --skip-db ] [ --skip-files ] <sitename>"
      exit 1
    fi
    
    if [ ${SKIP_CONFIRMATION:-} != "true" ]; then
      echo "This will overwrite your database and files for sites $*. OK?"
      select yn in "Yes" "No"; do
          case $yn in
              No ) exit;;
          esac
      done
    fi
    
    for subsite in $*; do
      echo "Pulling subsite: $subsite"
      if [ "${SKIP_DB:-}" != "true" ]; then
        db_pull ${subsite} || (printf "Failed to pull db for ${subsite}" && exit $?)
      else
        echo "Skipping db pull for ${subsite}"
      fi
    
      if [ "${SKIP_FILES:-}" != "true" ]; then
        files_pull ${subsite} || (printf "Failed to pull files for ${subsite}" && exit $?)
      else
        echo "Skipping files pull for ${subsite}"
      fi
    done
    

    【讨论】:

      【解决方案2】:

      感谢@rfay 的指导,我在 .ddev/providers 中为每个国家/地区设置了一组文件。每一个的结构如下:

      environment_variables:
        uri: mysite.be
        db_name: belgium
      
      auth_command:
        command: |
         <no changes>
      
      db_pull_command:
        command: |
          # set -x   # You can enable bash debugging output by uncommenting
          ls /var/www/html/.ddev >/dev/null # This just refreshes stale NFS if possible
          pushd /var/www/html/.ddev/.downloads >/dev/null
          acli remote:drush -n ${ACQUIA_PROJECT_ID} -- sql-dump --extra-dump=--no-tablespaces --uri=${uri}  >${db_name}.sql
      

      然后我在 .ddev/commands/host 中创建了一个自定义命令,其中包含我的脚本内容。真实剧本中的案例更多,涵盖所有国家。

      #!/usr/bin/env bash
      
      ## Description: Refresh a database from Acquia and run post-db commands
      ## Usage: refresh-db [dbname]
      ## Example: "ddev refresh-db france"
      
      site="$1"
      
      case $site in
        canada)
          uri="mysite.ca"
          ;;
        australia)
          uri="mysite.com.au"
          ;;
        belgium)
          uri="mysite.be"
          ;;
        brazil)
          uri="mysite.com.br"
          ;;
        *)
          site="db"
          uri="mysite.com"
          ;;
      esac
      
      ddev pull ${site} -y 2>/dev/null # suppress pull failed message since it really didn't
      ddev import-db --target-db=${site} --src=${DDEV_APPROOT}/.ddev/.downloads/${site}.sql
      ddev drush --uri=${uri} cr
      ddev drush --uri=${uri} -y pmu simplesamlphp_auth
      ddev drush --uri=${uri} -y config-set system.performance css.preprocess 0
      ddev drush --uri=${uri} -y config-set system.performance js.preprocess 0
      

      我尝试按照建议在 db_pull_command 期间处理 db 导入,但在导入尚未使用 ddev import-db 导入的 DB 时,我无法获得过去的数据库权限错误。但是,使用自定义命令,我还可以合并通常仅在通过 config.yaml 完成时才会针对默认数据库运行的 post-db-import 步骤。

      我所做的另一项更改是将项目 ID 移动到 global_config.yaml 文件中的 Web 环境设置中。这样,如果我们想要更改我们想要从中提取的环境,我们只需在此处编辑项目 ID,而不必编辑提供程序文件。

      我没有回馈开源项目的经验,但如果这对其他人有帮助,我很乐意与某人合作,在文档或其所属的任何地方执行拉取请求。

      【讨论】:

      • 非常感谢分享这个!我不明白您如何使用 drush 来提取您需要的特定数据库。我只看到acli remote:drush -n ${ACQUIA_PROJECT_ID} -- sql-dump --extra-dump=--no-tablespaces --uri=${uri} &gt;${db_name}.sql - 但我看不到它是如何提取特定子站点所需的特定数据库的。
      • @rfay 它只是将国家站点的 uri 传递给 drush 命令,使该命令针对该数据库运行。 docs.drush.org/en/9.x/usage/…
      • 啊,URI 提示它进入哪个子站点。谢谢!
      【解决方案3】:

      我将继续回答一般性问题,但您可以在解决此问题后添加完整的答案。 (我无法访问 Acquia 多站点。)

      您走在正确的轨道上,但您可以在拉取脚本中完成所有这些操作。您遇到的问题是 ddev 只是假设一个数据库,而您有多个。

      这是您的 acquia.yaml 的策略:

      1. 创建所有数据库。你可以使用mysql -e "CREATE DATABASE IF NOT EXISTS &lt;dbname&gt;;,使用多行或一个for循环。
      2. 提取所有数据库。您可以使用单独的 acli 行来执行此操作,或使用 for 循环。
      3. 使用 mysql 命令导入不是主数据库的数据库。 mysql &lt;dbname&gt; &lt; &lt;dbname.sql 同样,这可以是几行代码或一个 for 循环。 (您也可以只导入主数据库,它会被 ddev 重新导入,如果它不大,也无妨。)

      感谢您提出的好问题,我希望您能在这里给出完整的答案。您的回答也可以合并到https://ddev.readthedocs.io/en/stable/users/providers/acquia/ - 您可以通过点击右上角的铅笔链接在那里进行 PR。

      【讨论】:

      • 对不起,我不太清楚我想用这个来完成什么。最初创建数据库很好,但作为我们工作流程的一部分,我们会定期为我们正在开发的特定国家网站获取新副本。这是一个大型企业网站,因此每个国家/地区的数据库都非常大,我们有 17 个数据库——每次拉出所有数据库可能需要几个小时。所以我真正想要完成的是针对一个特定的站点来刷新它的数据库。如果我可以将参数传递给ddev pull acquia 命令,我会很高兴。
      • 请记住,您可以拥有任意数量的这些集成。因此,命名一个 .ddev/providers/acquia-fr.yaml 将只拉法国。实际上,名为“acquia.yaml”的示例只是一个示例。您可能想要一个名为“france.yaml”和ddev pull france 或类似名称的名称。
      • 太完美了!我没有想过为不同的国家这样做。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      • 2018-06-28
      • 1970-01-01
      相关资源
      最近更新 更多