在 AWS CodePipeline 中集成 SonarQube:连接被拒绝

Integrating SonarQube within AWS CodePipeline: Connection Refused

tl;dr

CodePipeline 在我的 buildspec.yml 文件的 mvn sonar:sonar 行崩溃,日志如下(我对其进行了一些格式化以提高可读性):

[ERROR] SonarQube server [http://localhost:9000] can not be reached 
...
[ERROR] Failed to execute goal 
        org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar 
        (default-cli) on project myproject: 
        Unable to execute SonarQube: 
        Fail to get bootstrap index from server: 
        Failed to connect to localhost/127.0.0.1:9000: 
        Connection refused (Connection refused) -> [Help 1] 

目标

这是我使用 AWS 的第一个项目,如果我提供了不相关的信息,我们深表歉意。

我正在尝试部署我的后端 API,以便 public 可以访问它。除其他事项外,我希望 CI/CD 设置为自动 运行 测试并在失败或未通过某个质量门时中止。如果一切顺利,那么新版本应该会自动部署上线。


当前状态

当其中一项测试失败时,我的管道会自动中止,但这就是我必须正确完成的所有工作。

我还没有弄清楚如何部署(甚至手动)API 以便能够向它发送请求。也许它已经完成了,但我只是不知道要使用哪个 URL。

无论如何,CodePipeline 在我的 buildspec.yml 文件的 mvn sonar:sonar 行崩溃了。

文件

这是我的 buildspec.yml:

version: 0.2 

phases: 
  install: 
    runtime-versions: 
      java: openjdk8 
    commands: 
      ############################################################################################## 
      ##### "cd / && ls" returns: [bin, boot, codebuild, dev, etc, go, home, lib, lib32, lib64, 
      #####                        media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var] 
      ##### Initial directory where this starts is $CODEBUILD_SRC_DIR 
      ##### That variable contains something like "/codebuild/output/src511423169/src"
      ############################################################################################## 
      # Upgrade AWS CLI to the latest version 
      - pip install --upgrade awscli 
      # Folder organization 
      - cd /root 
      - codeAnalysisFolder="Sonar" # todo: refactor to include "/root" 
      - mkdir $codeAnalysisFolder && cd $codeAnalysisFolder 
      # Get SonarQube 
      - wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-8.1.0.31237.zip 
      - unzip ./sonarqube-8.1.0.31237.zip 
      # Launch SonarQube server locally 
      - cd ./sonarqube-8.1.0.31237/bin/linux-x86-64 
      - sh ./sonar.sh start 
      # Get SonarScanner 
      - cd /root/$codeAnalysisFolder 
      - wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.2.0.1873-linux.zip 
      - unzip ./sonar-scanner-cli-4.2.0.1873-linux.zip 
      - export PATH=$PATH:/root/$codeAnalysisFolder/sonar-scanner-cli-4.2.0.1873-linux.zip/bin/ # todo: .zip ?! 
  pre_build: 
    commands: 
      - cd $CODEBUILD_SRC_DIR 
      - mvn clean compile test 
      - mvn sonar:sonar 
  build: 
    commands: 
      - mvn war:exploded 
  post_build: 
    commands: 
      - cp -r .ebextensions/ target/ROOT/ 
      - aws cloudformation package --template template.yml --s3-bucket $S3_BUCKET --output-template-file template-export.yml 
      # Do not remove this statement. This command is required for AWS CodeStar projects. 
      # Update the AWS Partition, AWS Region, account ID and project ID in the project ARN on template-configuration.json file so AWS CloudFormation can tag project resources. 
      - sed -i.bak 's/$PARTITION$/'${PARTITION}'/g;s/$AWS_REGION$/'${AWS_REGION}'/g;s/$ACCOUNT_ID$/'${ACCOUNT_ID}'/g;s/$PROJECT_ID$/'${PROJECT_ID}'/g' template-configuration.json 
artifacts: 
  type: zip 
  files: 
    - 'template-export.yml' 
    - 'template-configuration.json' 

以下是失败构建日志的最后几行:

[INFO] User cache: /root/.sonar/cache 
[ERROR] SonarQube server [http://localhost:9000] can not be reached 
[INFO] ------------------------------------------------------------------------ 
[INFO] BUILD FAILURE 
[INFO] ------------------------------------------------------------------------ 
[INFO] Total time:  6.071 s 
[INFO] Finished at: 2019-12-18T21:27:23Z 
[INFO] ------------------------------------------------------------------------ 
[ERROR] Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.7.0.1746:sonar (default-cli) on project myproject: Unable to execute SonarQube: Fail to get bootstrap index from server: Failed to connect to localhost/127.0.0.1:9000: Connection refused (Connection refused) -> [Help 1] 
[ERROR]  
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. 
[ERROR] Re-run Maven using the -X switch to enable full debug logging. 
[ERROR]  
[ERROR] For more information about the errors and possible solutions, please read the following articles: 
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException 

[Container] 2019/12/18 21:27:23 Command did not exit successfully mvn sonar:sonar exit status 1 
[Container] 2019/12/18 21:27:23 Phase complete: PRE_BUILD State: FAILED 
[Container] 2019/12/18 21:27:23 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: mvn sonar:sonar. Reason: exit status 1

并且因为您可能也有兴趣了解与 sh ./sonar.sh start 命令相关的构建日志:

[Container] 2019/12/18 21:25:49 Running command sh ./sonar.sh start 
Starting SonarQube... 
Started SonarQube. 

此外,这是我的 sonar-project.properties 文件:

# SONAR SCANNER CONFIGS 
sonar.projectKey=bullhubs 
# SOURCES 
sonar.java.source=8 
sonar.sources=src/main/java 
sonar.java.binaries=target/classes 
sonar.sourceEncoding=UTF-8 
# EXCLUSIONS 
# (exclusion of Lombok-generated stuff comes from the `lombok.config` file) 
sonar.coverage.exclusions=**/*Exception.java
# TESTS 
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml 
sonar.junit.reportsPath=target/surefire-reports/TEST-*.xml 
sonar.tests=src/test/java 

环境

(对于隐藏的信息,我们深表歉意:不确定什么应该保密,我是为了安全起见。如果您需要任何具体信息,请告诉我!)

我有一个 Elastic Beanstalk 设置,具有以下属性:

我还有一个 EC2 实例和 运行ning:

我也用了一个VPC


我试过的

我尝试在我的 EC2 的入站规则中添加一堆条目 Security Group:

我从 0.0.0.0/0 : 9000 开始,然后尝试 127.0.0.1/32 : 9000,最后尝试 All traffic。 None 有效,所以问题似乎出在其他地方。

我还尝试更改 sonar-project.properties 文件的一些属性,即 sonar.web.hostsonar.host.url,以尝试重定向托管 SonarQube 服务器的位置(我想也许我应该将其指向 EC2 的 IPv4 Public IP 地址或其附加的 Public DNS (IPv4)),但在尝试联系时,失败的构建日志以某种方式不断显示 localhost:9000 上的连接失败SonarQube 服务器。

我想通了。

不知何故,SonarQube 报告已正确启动,尽管事实并非如此。因此,当您在执行 运行 您的 sh ./sonar.sh start 命令后看到此日志时:

[Container] 2019/12/18 21:25:49 Running command sh ./sonar.sh start 
Starting SonarQube... 
Started SonarQube.

不一定是SonarQube的本地服务器已经成功启动。需要进入SonarQube安装文件夹的logs文件夹,阅读sonar.log 文件以查明确实有问题并且服务器已停止...

在我的例子中,它报告了一个错误,即 运行 服务器需要 JDK11。为了解决这个问题,我将 buildspec.ymljava: openjdk8 行更改为 java: openjdk11

然后,我不得不弄清楚现在可以读取一个新的日志文件:es.log。在控制台中打印该文件时,我发现最新的 ElasticSearch 版本(由最新的 SonarQube 服务器版本使用)不允许 root 用户 运行。因此,我必须创建一个新的用户组并编辑一些配置文件以 运行 具有该用户的服务器:

  # Set up non-root user to run SonarQube
  - groupadd sonar
  - useradd -c "Sonar System User" -d $sonarPath/$sonarQube -g sonar -s /bin/bash sonar
  - chown -R sonar:sonar $sonarPath/$sonarQube  # recursively changing the folder's ownership
  # Launch SonarQube server locally
  - cd ./$sonarQube/bin/linux-x86-64
  - sed -i 's/#RUN_AS_USER=/RUN_AS_USER=sonar/g' sonar.sh  # enabling user execution of server
  - sh ./sonar.sh start

完整的解决方案

这为我们提供了 buildspec.yml 的以下工作版本:

version: 0.2

phases:
  install:
    runtime-versions:
      java: openjdk11
    commands:
      ##############################################################################################
      ##### "cd / && ls" returns: [bin, boot, codebuild, dev, etc, go, home, lib, lib32, lib64,
      #####                        media, mnt, opt, proc, root, run, sbin, srv, sys, tmp, usr, var]
      ##### Initial directory where this starts is $CODEBUILD_SRC_DIR
      ##### That variable contains something like "/codebuild/output/src511423169/src"
      ##### This folder contains the whole structure of the CodeCommit repository. This means that
      ##### the actual Java classes are accessed through "cd src" from there, for example.
      ##############################################################################################
      # Upgrade AWS CLI to the latest version
      - pip install --upgrade awscli
      # Folder organization
      - preSonarPath="/opt/"
      - codeAnalysisFolder="Sonar"
      - sonarPath="$preSonarPath$codeAnalysisFolder"
      - cd $preSonarPath && mkdir $codeAnalysisFolder
      # Get SonarQube
      - cd $sonarPath
      - sonarQube="sonarqube-8.1.0.31237"
      - wget https://binaries.sonarsource.com/Distribution/sonarqube/$sonarQube.zip
      - unzip ./$sonarQube.zip
      # Set up non-root user to run SonarQube
      - groupadd sonar
      - useradd -c "Sonar System User" -d $sonarPath/$sonarQube -g sonar -s /bin/bash sonar
      - chown -R sonar:sonar $sonarPath/$sonarQube  # recursively changing the folder's ownership
      # Launch SonarQube server locally
      - cd ./$sonarQube/bin/linux-x86-64
      - sed -i 's/#RUN_AS_USER=/RUN_AS_USER=sonar/g' sonar.sh  # enabling user execution of server
      - sh ./sonar.sh start
      # Get SonarScanner and add to PATH
      - sonarScanner="sonar-scanner-cli-4.2.0.1873-linux"
      - cd $sonarPath
      - wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/$sonarScanner.zip
      - unzip ./$sonarScanner.zip
      - export PATH=$PATH:$sonarPath/$sonarScanner.zip/bin/ # todo: .zip ?!
  pre_build:
    commands:
      - cd $CODEBUILD_SRC_DIR
      - mvn clean compile test
#      - cd $sonarPath/$sonarQube/logs
#      - cat access.log
#      - cat es.log
#      - cat sonar.log
#      - cat web.log
#      - cd $CODEBUILD_SRC_DIR
      - mvn sonar:sonar
  build:
    commands:
      - mvn war:exploded
  post_build:
    commands:
      - cp -r .ebextensions/ target/ROOT/
      - aws cloudformation package --template template.yml --s3-bucket $S3_BUCKET --output-template-file template-export.yml
      # Do not remove this statement. This command is required for AWS CodeStar projects.
      # Update the AWS Partition, AWS Region, account ID and project ID in the project ARN on template-configuration.json file so AWS CloudFormation can tag project resources.
      - sed -i.bak 's/$PARTITION$/'${PARTITION}'/g;s/$AWS_REGION$/'${AWS_REGION}'/g;s/$ACCOUNT_ID$/'${ACCOUNT_ID}'/g;s/$PROJECT_ID$/'${PROJECT_ID}'/g' template-configuration.json
artifacts:
  type: zip
  files:
    - 'template-export.yml'
    - 'template-configuration.json'

干杯!