AWS CodeBuild buildspec bash语法错误:用if语句替换错误 使用hashicorp/terraform:0.12.28图片进行更新

如何解决AWS CodeBuild buildspec bash语法错误:用if语句替换错误 使用hashicorp/terraform:0.12.28图片进行更新

背景

我正在使用AWS CodeBuild buildspec.yml来遍历GitHub存储库中的目录。在遍历目录路径$TF_ROOT_DIR之前,我使用bash if语句检查GitHub分支名称$BRANCH_NAME是否在env变量$LIVE_BRANCHES中。如下面的错误屏幕快照所示,bash if语句输出错误Syntax error: bad substitution。当我在本地bash脚本中重现if语句时,if语句将按预期工作。

以下是CodeBuild项目中定义的env变量:

env

这是来自buildspec.yml的相关片段:

version: 0.2
env:
  shell: bash
phases:
  build:
    commands:
      - |
        if [[ " ${LIVE_BRANCHES[*]} " == *"$BRANCH_NAME"* ]]; then
          # Iterate only through BRANCH_NAME directory
          TF_ROOT_DIR=${TF_ROOT_DIR}/*/${BRANCH_NAME}/
        else
          # Iterate through both dev and prod directories
          TF_ROOT_DIR=${TF_ROOT_DIR}/*/
        fi
      - echo $TF_ROOT_DIR

以下是显示语法错误的构建日志:

enter image description here

这里是AWS CodeBuild项目JSON,用于再现CodeBuild项目:

{
    "projects": [
        {
            "name": "terraform_validate_plan","arn": "arn:aws:codebuild:us-west-2:xxxxx:project/terraform_validate_plan","description": "Perform terraform plan and terraform validator","source": {
                "type": "GITHUB","location": "https://github.com/marshall7m/sparkify_end_to_end.git","gitCloneDepth": 1,"gitSubmodulesConfig": {
                    "fetchSubmodules": false
                },"buildspec": "deployment/CI/dev/cfg/buildspec_terraform_validate_plan.yml","reportBuildStatus": false,"insecureSsl": false
            },"secondarySources": [],"secondarySourceVersions": [],"artifacts": {
                "type": "NO_ARTIFACTS","overrideArtifactName": false
            },"cache": {
                "type": "NO_CACHE"
            },"environment": {
                "type": "LINUX_CONTAINER","image": "hashicorp/terraform:0.12.28","computeType": "BUILD_GENERAL1_SMALL","environmentvariables": [
                    {
                        "name": "TF_ROOT_DIR","value": "deployment","type": "PLAINTEXT"
                    },{
                        "name": "LIVE_BRANCHES","value": "(dev,prod)","type": "PLAINTEXT"
                    }

以下是相关的buildspec文件内容:(buildspec_terraform_validate_plan.yml

version: 0.2
env:
  shell: bash
  parameter-store:
      AWS_ACCESS_KEY_ID_ParaM: TF_AWS_ACCESS_KEY_ID
      AWS_SECRET_ACCESS_KEY_ParaM: TF_AWS_SECRET_ACCESS_KEY_ID
phases:
  install:
    commands:
      # install/incorporate terraform validator? 
  pre_build:
    commands:
      # CodeBuild environment variables
      #   BRANCH_NAME -- GitHub branch that triggered the CodeBuild project
      #   TF_ROOT_DIR -- Directory within branch ($BRANCH_NAME) that will be iterated through for terraform planning and testing
      #   LIVE_BRANCHES -- Branches that represent a live cloud environment
      - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_ParaM
      - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_ParaM
      - bash -version || echo "${BASH_VERSION}" || bash --version
      - |
        if [[ -z "${BRANCH_NAME}" ]]; then
          # extract branch from github webhook
          BRANCH_NAME=$(echo $CODEBUILD_WEBHOOK_HEAD_REF | cut -d'/' -f 3)
        fi
      - "echo Triggered Branch: $BRANCH_NAME"
      - |
        if [[ " ${LIVE_BRANCHES[*]} " == *"$BRANCH_NAME"* ]]; then
          # Iterate only through BRANCH_NAME directory
          TF_ROOT_DIR=${TF_ROOT_DIR}/*/${BRANCH_NAME}/
        else
          # Iterate through both dev and prod directories
          TF_ROOT_DIR=${TF_ROOT_DIR}/*/
        fi
      - "echo terraform root directory: $TF_ROOT_DIR"
  build:
    commands:
      - |
        for dir in $TF_ROOT_DIR; do
          #get list of non-hidden directories within $dir/
          service_dir_list=$(find "${dir}" -type d | grep -v '/\.')
          for sub_dir in $service_dir_list; do
            #if $sub_dir contains .tf or .tfvars files
            if (ls ${sub_dir}/*.tf) > /dev/null 2>&1 || (ls ${sub_dir}/*.tfvars) > /dev/null 2>&1; then
              cd $sub_dir 
              echo ""
              echo "*************** terraform init ******************"
              echo "******* At directory: ${sub_dir} ********"
              echo "*************************************************"
              terraform init
              echo ""
              echo "*************** terraform plan ******************"
              echo "******* At directory: ${sub_dir} ********"
              echo "*************************************************"
              terraform plan
              cd - > /dev/null 
            fi
          done 
        done

鉴于这只是一个附带项目,所有可能与此问题相关的文件都在公共仓库here中。

更新

尝试添加#!/bin/bash shebang行,但导致CodeBuild错误

Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: #!/bin/bash
version: 0.2
env:
  shell: bash
phases:
  build:
    commands:
      - |
        #!/bin/bash
        if [[ " ${LIVE_BRANCHES[*]} " == *"$BRANCH_NAME"* ]]; then
          # Iterate only through BRANCH_NAME directory
          TF_ROOT_DIR=${TF_ROOT_DIR}/*/${BRANCH_NAME}/
        else
          # Iterate through both dev and prod directories
          TF_ROOT_DIR=${TF_ROOT_DIR}/*/
        fi
      - echo $TF_ROOT_DIR

解决方

如@marcin所述,我在Codebuild(aws / codebuild / standard:4.0)中使用了AWS托管映像,并在install阶段下载了terraform

phases:
  install:
    commands:
      - wget https://releases.hashicorp.com/terraform/${terraform_VERSION}/terraform_${terraform_VERSION}_linux_amd64.zip -q
      - unzip terraform_${terraform_VERSION}_linux_amd64.zip && mv terraform /usr/local/bin/

解决方法

我尝试重制您的问题,但对我来说一切正常。

我唯一注意到的是您正在使用$BRANCH_NAME,但未在任何地方定义它。但即使缺少$BRANCH_NAME,您发布的buildspec.yml也可以正常运行。

使用hashicorp/terraform:0.12.28图片进行更新

hashicorp/terraform:0.12.28

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?