├── .mvn
├── maven.config
└── extensions.xml
├── .github
├── CODEOWNERS
├── release-drafter.yml
├── dependabot.yml
└── workflows
│ ├── release-drafter.yml
│ └── jenkins-security-scan.yml
├── .gitignore
├── src
├── main
│ ├── resources
│ │ ├── io
│ │ │ └── jenkins
│ │ │ │ └── plugins
│ │ │ │ └── alibabacloud
│ │ │ │ └── pkg
│ │ │ │ └── deployment
│ │ │ │ ├── OssUploadAndOosExecStep
│ │ │ │ ├── help-batchNumber_zh_CN.html
│ │ │ │ ├── help-localPath_zh_CN.html
│ │ │ │ ├── help-objectName_zh_CN.html
│ │ │ │ ├── help-invokeScript_zh_CN.html
│ │ │ │ ├── help-resourceType_zh_CN.html
│ │ │ │ ├── help-destinationDir_zh_CN.html
│ │ │ │ ├── help-batchNumber.html
│ │ │ │ ├── help-objectName.html
│ │ │ │ ├── help-invokeScript.html
│ │ │ │ ├── help-localPath.html
│ │ │ │ ├── help-region.html
│ │ │ │ ├── help-region_zh_CN.html
│ │ │ │ ├── help-destinationDir.html
│ │ │ │ ├── help-resourceType.html
│ │ │ │ ├── help-bucket_zh_CN.html
│ │ │ │ ├── help-resourceId_zh_CN.html
│ │ │ │ ├── help-bucket.html
│ │ │ │ ├── help-mode_zh_CN.html
│ │ │ │ ├── help-pausePolicy_zh_CN.html
│ │ │ │ ├── help-resourceId.html
│ │ │ │ ├── help-mode.html
│ │ │ │ ├── help-pausePolicy.html
│ │ │ │ └── config.jelly
│ │ │ │ ├── AliyunEcsOpsByOssFilePublisher
│ │ │ │ ├── help-batchNumber_zh_CN.html
│ │ │ │ ├── help-localPath_zh_CN.html
│ │ │ │ ├── help-objectName_zh_CN.html
│ │ │ │ ├── help-resourceType_zh_CN.html
│ │ │ │ ├── help-destinationDir_zh_CN.html
│ │ │ │ ├── help-invokeScript_zh_CN.html
│ │ │ │ ├── help-objectName.html
│ │ │ │ ├── help-batchNumber.html
│ │ │ │ ├── help-localPath.html
│ │ │ │ ├── help-invokeScript.html
│ │ │ │ ├── help-region_zh_CN.html
│ │ │ │ ├── help-destinationDir.html
│ │ │ │ ├── help-resourceType.html
│ │ │ │ ├── help-bucket_zh_CN.html
│ │ │ │ ├── help-region.html
│ │ │ │ ├── help-bucket.html
│ │ │ │ ├── help-resourceId_zh_CN.html
│ │ │ │ ├── help-resourceId.html
│ │ │ │ └── config.jelly
│ │ │ │ ├── OosExecuteNotifyStep
│ │ │ │ ├── help-notifyType_zh_CN.html
│ │ │ │ ├── help-executeId_zh_CN.html
│ │ │ │ ├── help-executeId.html
│ │ │ │ ├── help-notifyType.html
│ │ │ │ ├── help-region_zh_CN.html
│ │ │ │ ├── help-region.html
│ │ │ │ └── config.jelly
│ │ │ │ ├── OosStatusQueryStep
│ │ │ │ ├── help-executeId_zh_CN.html
│ │ │ │ ├── help-executeId.html
│ │ │ │ ├── help-region_zh_CN.html
│ │ │ │ ├── config.jelly
│ │ │ │ └── help-region.html
│ │ │ │ └── PluginImpl
│ │ │ │ └── config.jelly
│ │ └── index.jelly
│ └── java
│ │ └── io
│ │ └── jenkins
│ │ └── plugins
│ │ └── alibabacloud
│ │ └── pkg
│ │ └── deployment
│ │ ├── utils
│ │ ├── Status.java
│ │ ├── ResourceType.java
│ │ ├── StepUtils.java
│ │ └── AliyunClientFactory.java
│ │ ├── PluginImpl.java
│ │ ├── OosStatusQueryStep.java
│ │ ├── OosExecuteNotifyStep.java
│ │ ├── AliyunEcsOpsByOssFilePublisher.java
│ │ └── OssUploadAndOosExecStep.java
└── test
│ └── java
│ └── io
│ └── jenkins
│ └── plugins
│ └── alibabacloud
│ └── pkg
│ └── deployment
│ ├── OosStatusQueryStepTest.java
│ ├── AliyunEcsOpsTest.java
│ ├── OosExecuteNotifyStepTest.java
│ ├── AliyunEcsOpsByOssFilePublisherTest.java
│ └── OssUploadAndOosExecStepTest.java
├── Jenkinsfile
├── LICENSE
├── README.md
└── pom.xml
/.mvn/maven.config:
--------------------------------------------------------------------------------
1 | -Pconsume-incrementals
2 | -Pmight-produce-incrementals
3 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @jenkinsci/alibabacloud-pkg-deployment-plugin-developers
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | *.classpath
3 | *.settings
4 | *.project
5 | *.iml
6 | *.idea
7 | target
8 | logs
9 | work
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | _extends: .github
2 | tag-template: ${artifactId}-$NEXT_MINOR_VERSION
3 | template: |
4 | # What's Changed
5 | $CHANGES
6 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-batchNumber_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS执行模版执行批数。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-localPath_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | Jenkins已构建项目的目录路径。
3 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | buildPlugin(
2 | useContainerAgent: true,
3 | configurations: [
4 | [platform: 'linux', jdk: 11],
5 | [platform: 'windows', jdk: 11],
6 | ])
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-batchNumber_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS模版任务执行批数。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-objectName_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 上传至OSS bucket 的文件名。
3 |
--------------------------------------------------------------------------------
/src/main/resources/index.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 | This plugin integrates Jenkins with Alibabacloud Package Deployment.
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-localPath_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | Jenkins已构建项目的目录路径。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-objectName_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 上传至OSS bucket 的文件名。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-invokeScript_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | ECS下载 OOS 文件后部署项目脚本。
3 |
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-resourceType_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 目前只支持操作两种资源:ESS 和 ECS。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-resourceType_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 目前只支持操作两种资源:ESS 和 ECS。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-destinationDir_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | ECS用于下载 OSS 文件以及部署项目的位置。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-destinationDir_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | ECS用于下载 OSS 文件以及部署项目的位置。
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-invokeScript_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | ECS下载 OOS 文件后部署项目脚本。
3 |
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-batchNumber.html:
--------------------------------------------------------------------------------
1 |
2 | The OOS template execution batch Number.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-objectName.html:
--------------------------------------------------------------------------------
1 |
2 | The file name uploaded to the OSS bucket.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-objectName.html:
--------------------------------------------------------------------------------
1 |
2 | The file name uploaded to the OSS bucket.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-batchNumber.html:
--------------------------------------------------------------------------------
1 |
2 | The OOS template task execution batch Number.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-invokeScript.html:
--------------------------------------------------------------------------------
1 |
2 | The deploy script run after ECS download OOS File.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-localPath.html:
--------------------------------------------------------------------------------
1 |
2 | The directory path of the built project for jenkins.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-region.html:
--------------------------------------------------------------------------------
1 |
2 | 阿里云 ECS 、ESS、OSS、OOS资源所在的地域。
3 | 样例: cn-hangzhou。
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-localPath.html:
--------------------------------------------------------------------------------
1 |
2 | The directory path of the built project for jenkins.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-region_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 阿里云 ECS 、ESS、OSS、OOS资源所在的地域。
3 | 样例: cn-hangzhou。
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-invokeScript.html:
--------------------------------------------------------------------------------
1 |
2 | The deploy script run after ECS download OOS File.
3 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-region_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 阿里云 ECS 、ESS、OSS、OOS资源所在的地域。
3 | 样例: cn-hangzhou。
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-destinationDir.html:
--------------------------------------------------------------------------------
1 |
2 | The Location of ECS used to download OSS file and deloy project.
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-resourceType.html:
--------------------------------------------------------------------------------
1 |
2 | Currently,only two resources are supported.
3 | Example: ESS and ECS.
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-destinationDir.html:
--------------------------------------------------------------------------------
1 |
2 | The Location of ECS used to download OSS file and deloy project.
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-resourceType.html:
--------------------------------------------------------------------------------
1 |
2 | Currently,only two resources are supported.
3 | Example: ESS and ECS.
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-bucket_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 阿里云OSSbucket名称
3 | 登陆OSS控制台
配置
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-bucket_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 阿里云OSS bucket 名称
3 | 登陆 OSS 控制台
配置
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-region.html:
--------------------------------------------------------------------------------
1 |
2 | Specifies the geographic region in which your ESS or ECS or OSS or OOS will run.
3 | Example: cn-hangzhou.
4 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/help-notifyType_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS 模版暂停任务运行的下一步骤
3 | 取值如下:
4 |
5 | - Approve: 暂停任务继续执行下一批次。
6 | - Cancelled: 暂停任务取消。
7 |
8 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStep/help-executeId_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS模版任务ID
3 | 查看
4 |
详情登陆OOS控制台
5 |
6 | 样例: exec-XXXXXXX
7 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-resourceId_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 资源Id
3 | 样例如下:
4 | ESS:asg-sdsfbhdxxxxxxxxxx
5 | ECS:i-dbhcbxxxxxxxxxxx 或者 i-dbhcbxxxxxxxxxxx,i-dbhcbxxxxxxx (ECS 支持多个实例Id以逗号分割拼接)
6 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/help-executeId_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS模版暂停任务ID
3 | 查看
4 |
详情登陆OOS控制台
5 |
6 | 样例: exec-XXXXXXX
7 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-bucket.html:
--------------------------------------------------------------------------------
1 |
2 | Aliyun OSS BucketName
3 |
config
4 | You can upload the built project to OSS bucket
5 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-bucket.html:
--------------------------------------------------------------------------------
1 |
2 | Aliyun OSS BucketName
3 |
config
4 | You can upload the built project to OSS bucket.
5 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-resourceId_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | 资源Id
3 | 样例如下:
4 | ESS:asg-sdsfbhdxxxxxxxxxx
5 | ECS:i-dbhcbxxxxxxxxxxx 或者 i-dbhcbxxxxxxxxxxx,i-dbhcbxxxxxxx (ECS 支持多个实例Id以逗号分割拼接)
6 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStep/help-executeId.html:
--------------------------------------------------------------------------------
1 |
2 | OOS template task id.
3 |
Details
4 | Please login OOS console
5 | Example: exec-XXXXX
6 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-mode_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS 模版执行模式
3 | 取值如下:
4 |
5 | - Automatic(默认值):自动执行。
6 | - FailurePause:失败暂停
7 | - Debug:单步执行
8 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/help-executeId.html:
--------------------------------------------------------------------------------
1 |
2 | OOS template pause task id.
3 |
Details
4 | Please login OOS console.
5 | Example: exec-XXXXX
6 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/utils/Status.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment.utils;
2 |
3 | /**
4 | * oss template execution status.
5 | */
6 | public enum Status {
7 | Success,
8 | Failed,
9 | Waiting,
10 | Cancelled,
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStep/help-region_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS模版任务所在地域
3 | 查看
OOS支持地域获取所有支持的地域列表
5 |
6 | 样例: 华东1(杭州)
7 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-pausePolicy_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS 模版执行的循环模式
3 | 取值如下:
4 |
5 | - Automatic(默认值):不暂停
6 | - FirstBatchPause:第一批暂停
7 | - EveryBatchPause:每批暂停
8 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/help-notifyType.html:
--------------------------------------------------------------------------------
1 |
2 | The OOS template pause task next step.
3 | Valid values:
4 |
5 | - Approve: pause task run next batch.
6 | - Cancelled: pause task cancel .
7 |
8 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/help-region_zh_CN.html:
--------------------------------------------------------------------------------
1 |
2 | OOS模版暂停任务执行地域
3 | 查看
OOS支持地域获取所有支持的地域列表
5 |
6 | 样例: 华东1(杭州)
7 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-resourceId.html:
--------------------------------------------------------------------------------
1 |
2 | ID of resource.
3 | Example:
4 | ESS:asg-sdsfbhdxxxxxxxxxx
5 | ECS:i-dbhcbxxxxxxxxxxx or i-dbhcbxxxxxxxxxxx,i-dbhcbxxxxxxx (ECS supports comma separated concatenation of multiple instance IDs)
6 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/help-resourceId.html:
--------------------------------------------------------------------------------
1 |
2 | ID of resource.
3 | Example:
4 | ESS:asg-sdsfbhdxxxxxxxxxx
5 | ECS:i-dbhcbxxxxxxxxxxx or i-dbhcbxxxxxxxxxxx,i-dbhcbxxxxxxx (ECS supports comma separated concatenation of multiple instance IDs)
6 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates
2 |
3 | version: 2
4 | updates:
5 | - package-ecosystem: maven
6 | directory: /
7 | schedule:
8 | interval: monthly
9 | - package-ecosystem: github-actions
10 | directory: /
11 | schedule:
12 | interval: monthly
13 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStep/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStep/help-region.html:
--------------------------------------------------------------------------------
1 |
2 | Specifies the geographic region in which your OOS template task.
3 |
OOS support region
4 | for more about what regions are.
5 | Example: China (Hangzhou)
6 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/help-region.html:
--------------------------------------------------------------------------------
1 |
2 | Specifies the geographic region in which your OOS template pause task.
3 |
OOS support region
4 | for more about what regions are.
5 | Example: China (Hangzhou)
6 |
--------------------------------------------------------------------------------
/.mvn/extensions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | io.jenkins.tools.incrementals
4 | git-changelist-maven-extension
5 | 1.6
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-mode.html:
--------------------------------------------------------------------------------
1 |
2 | The OOS template execution mode.
3 | Valid values:
4 |
5 | - Automatic: automatically starts the execution of the template. This is the default value.
6 | - FailurePause: suspends the execution of the template upon a failure.
7 | - Debug: manually starts the execution of the template.
8 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/help-pausePolicy.html:
--------------------------------------------------------------------------------
1 |
2 | The OOS template loop mode.
3 | Valid values:
4 |
5 | - Automatic: does not suspend the execution of the template. This is the default value.
6 | - FirstBatchPause: suspends the execution of the template after the first batch is complete.
7 | - EveryBatchPause: suspends the execution of the template after each batch is complete.
8 |
9 |
--------------------------------------------------------------------------------
/src/test/java/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStepTest.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class OosStatusQueryStepTest {
7 | @Test
8 | public void gettersWorkAsExpected() {
9 | OosStatusQueryStep step = new OosStatusQueryStep("cn-hangzhou","exec-xxxxxx");
10 | Assert.assertEquals("cn-hangzhou", step.getRegion());
11 | Assert.assertEquals("exec-xxxxxx", step.getExecuteId());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | # Automates creation of Release Drafts using Release Drafter
2 | # More Info: https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc
3 |
4 | on:
5 | push:
6 | branches:
7 | - master
8 | - main
9 |
10 | jobs:
11 | update_release_draft:
12 | runs-on: ubuntu-latest
13 | steps:
14 | # Drafts your next Release notes as Pull Requests are merged into the default branch
15 | - uses: release-drafter/release-drafter@v5
16 | env:
17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/utils/ResourceType.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment.utils;
2 |
3 | public enum ResourceType {
4 |
5 | ESS("ESS", "ESS ScalingGroup"),
6 | ECS("ECS", "ECS Instance");
7 |
8 | String type;
9 | String name;
10 |
11 | ResourceType(String type, String name) {
12 | this.type = type;
13 | this.name = name;
14 | }
15 |
16 | public String getType() {
17 | return type;
18 | }
19 |
20 | public String getName() {
21 | return name;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsTest.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import com.gargoylesoftware.htmlunit.WebAssert;
4 | import com.gargoylesoftware.htmlunit.html.HtmlPage;
5 | import org.junit.Rule;
6 | import org.jvnet.hudson.test.JenkinsRule;
7 |
8 | public class AliyunEcsOpsTest {
9 | @Rule
10 | public JenkinsRule j = new JenkinsRule();
11 | public void testConfig() throws Exception {
12 | HtmlPage page = j.new WebClient().goTo("configure");
13 | WebAssert.assertTextPresent(page, "Alibaba Cloud");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStepTest.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class OosExecuteNotifyStepTest {
7 | @Test
8 | public void gettersWorkAsExpected(){
9 | OosExecuteNotifyStep step = new OosExecuteNotifyStep("cn-hangzhou","exec-xxxxxx","Approve");
10 | Assert.assertEquals("cn-hangzhou", step.getRegion());
11 | Assert.assertEquals("exec-xxxxxx", step.getExecuteId());
12 | Assert.assertEquals("Approve", step.getNotifyType());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/utils/StepUtils.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment.utils;
2 |
3 | import hudson.EnvVars;
4 | import hudson.model.TaskListener;
5 |
6 | import java.util.Arrays;
7 | import java.util.HashSet;
8 | import java.util.Set;
9 |
10 | public class StepUtils {
11 | public static > Set requires(T... classes) {
12 | return new HashSet<>(Arrays.asList(classes));
13 | }
14 |
15 | public static Set extends Class>> requiresDefault() {
16 | return requires(EnvVars.class, TaskListener.class);
17 | }
18 |
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/.github/workflows/jenkins-security-scan.yml:
--------------------------------------------------------------------------------
1 | # More information about the Jenkins security scan can be found at the developer docs: https://www.jenkins.io/redirect/jenkins-security-scan/
2 |
3 | name: Jenkins Security Scan
4 | on:
5 | push:
6 | branches:
7 | - "master"
8 | - "main"
9 | pull_request:
10 | types: [ opened, synchronize, reopened ]
11 | workflow_dispatch:
12 |
13 | permissions:
14 | security-events: write
15 | contents: read
16 | actions: read
17 |
18 | jobs:
19 | security-scan:
20 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2
21 | with:
22 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate.
23 | java-version: 11 # What version of Java to set up for the build.
24 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/PluginImpl/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | You must be provide an AccessKey pair
7 | See
8 |
9 | Alibaba Cloud documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Alibaba Cloud
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/test/java/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisherTest.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import hudson.model.FreeStyleProject;
4 | import org.junit.Rule;
5 | import org.junit.Test;
6 | import org.jvnet.hudson.test.JenkinsRule;
7 | import org.jvnet.hudson.test.recipes.LocalData;
8 |
9 | import static org.hamcrest.Matchers.containsString;
10 | import static org.hamcrest.Matchers.not;
11 | import static org.junit.Assert.assertThat;
12 |
13 | public class AliyunEcsOpsByOssFilePublisherTest {
14 | @Rule
15 | public JenkinsRule j = new JenkinsRule();
16 |
17 | @Test
18 | public void testRoundTripConfiguration() throws Exception {
19 | final AliyunEcsOpsByOssFilePublisher publisher = new AliyunEcsOpsByOssFilePublisher(
20 | "cn-hangzhou",
21 | "ESS",
22 | "asg-XXXXXXXX",
23 | "testBucket",
24 | "/testLocation",
25 | "/",
26 | "/root",
27 | 1,
28 | "");
29 | final AliyunEcsOpsByOssFilePublisher afterPublisher = j.configRoundtrip(publisher);
30 | j.assertEqualDataBoundBeans(publisher, afterPublisher);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/test/java/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStepTest.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class OssUploadAndOosExecStepTest {
7 | @Test
8 | public void gettersWorkAsExpected() {
9 | OssUploadAndOosExecStep step = new OssUploadAndOosExecStep("cn-hangzhou","ESS",
10 | "asg-XXXX","bucketTest","workspace/Test.zip","/","Automatic","EveryBatchPause",1,"/root/ceshi.zip",
11 | "");
12 | Assert.assertEquals("cn-hangzhou", step.getRegion());
13 | Assert.assertEquals("ESS", step.getResourceType());
14 | Assert.assertEquals("asg-XXXX", step.getResourceId());
15 | Assert.assertEquals("bucketTest", step.getBucket());
16 | Assert.assertEquals("workspace/Test.zip", step.getObjectName());
17 | Assert.assertEquals("/", step.getLocalPath());
18 | Assert.assertEquals("Automatic", step.getMode());
19 | Assert.assertEquals("EveryBatchPause", step.getPausePolicy());
20 | Assert.assertEquals(1, step.getBatchNumber());
21 | Assert.assertEquals("/root/ceshi.zip", step.getDestinationDir());
22 | Assert.assertEquals("", step.getInvokeScript());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/resources/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/utils/AliyunClientFactory.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment.utils;
2 |
3 | import com.aliyun.oss.OSS;
4 | import com.aliyun.oss.OSSClientBuilder;
5 | import com.aliyuncs.DefaultAcsClient;
6 | import com.aliyuncs.IAcsClient;
7 | import com.aliyuncs.profile.DefaultProfile;
8 | import io.jenkins.plugins.alibabacloud.pkg.deployment.PluginImpl;
9 |
10 | /**
11 | * product oos client and oss client.
12 | */
13 | public class AliyunClientFactory {
14 | private static final String endpointFormat = "https://oss-%s.aliyuncs.com";
15 |
16 | private OSS ossClient;
17 | private IAcsClient oosClient;
18 |
19 | public OSS getOssClient() {
20 | return ossClient;
21 | }
22 |
23 | public void setOssClient(OSS ossClient) {
24 | this.ossClient = ossClient;
25 | }
26 |
27 | public IAcsClient getOosClient() {
28 | return oosClient;
29 | }
30 |
31 | public void setOosClient(IAcsClient oosClient) {
32 | this.oosClient = oosClient;
33 | }
34 |
35 | public void build(String region) {
36 | String accessKeyId = PluginImpl.getInstance().getAccessKeyId();
37 | String accessKeySecret = PluginImpl.getInstance().getAccessKeySecret();
38 | this.ossClient = new OSSClientBuilder().build(String.format(endpointFormat, region), accessKeyId, accessKeySecret);
39 | DefaultProfile profile = DefaultProfile.getProfile(
40 | region, accessKeyId, accessKeySecret
41 | );
42 | this.oosClient = new DefaultAcsClient(profile);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/PluginImpl.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import hudson.Extension;
4 | import hudson.ExtensionList;
5 | import hudson.util.Secret;
6 | import jenkins.model.GlobalConfiguration;
7 | import net.sf.json.JSONObject;
8 | import org.jenkinsci.Symbol;
9 | import org.kohsuke.stapler.DataBoundConstructor;
10 | import org.kohsuke.stapler.DataBoundSetter;
11 | import org.kohsuke.stapler.StaplerRequest;
12 |
13 | /**
14 | * plugin extension:
15 | * global setting
16 | */
17 | @Extension
18 | @Symbol("pipelineStepsAliyun")
19 | public class PluginImpl extends GlobalConfiguration {
20 | @SuppressWarnings("lgtm[jenkins/plaintext-storage]")
21 | private String accessKeyId;
22 | private Secret accessKeySecret;
23 |
24 | @DataBoundConstructor
25 | public PluginImpl() {
26 | load();
27 | }
28 |
29 | @DataBoundSetter
30 | public void setAccessKeyId(String accessKeyId) {
31 | this.accessKeyId = accessKeyId;
32 | }
33 |
34 | @DataBoundSetter
35 | public void setAccessKeySecret(Secret accessKeySecret) {
36 | this.accessKeySecret = accessKeySecret;
37 | }
38 |
39 | @Override
40 | public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
41 | accessKeyId = json.getString("accessKeyId");
42 | accessKeySecret = Secret.fromString(json.getString("accessKeySecret"));
43 | save();
44 | return true;
45 | }
46 |
47 | public static PluginImpl getInstance() {
48 | return ExtensionList.lookup(PluginImpl.class).get(0);
49 | }
50 |
51 | public String getAccessKeyId() {
52 | return this.accessKeyId;
53 | }
54 |
55 | public String getAccessKeySecret() {
56 | return Secret.toString(this.accessKeySecret);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Alibabacloud Package Deployment Jenkins plugin
2 | =============================
3 |
4 | Plugins for deployment package on Alibaba Cloud.
5 | * The plugin provides a post-build step:upon a successful build,it will compress the specified working directory, upload it to OSS, and then download OSS files to ECS through OOS for deployment
6 | * This plugins adds Jenkins pipeline steps to interact with the Aliyun API.
7 |
8 |
9 | Setting up
10 | ----------
11 |
12 | After building and installing the plugin, some simple configuration is needed
13 | for your project.Please set global configuration of Aliyun Ak/Sk.
14 |
15 | # How to use post-build step
16 |
17 | ### Freestyle
18 |
19 | 1. Open up your project configuration
20 | 2. In the `Post-build Actions` section, select "Alibabacloud Automatic Package Deployment"
21 | 3. ResourceType,ResourceId, objectName, bucket, and region are so on all
22 | required options.
23 | 4. Temporary access keys. These will use the global keys from the Jenkins
24 | instance.
25 |
26 | ### Pipeline
27 |
28 | 1. Create a [Jenkins Pipeline](https://plugins.jenkins.io/workflow-aggregator/) project
29 | 2. Use the Pipeline Snippet Generator
30 | 3. For 'Sample Step', choose 'step: General Build Step'
31 | 4. For 'Build Step', choose 'Alibabacloud Automatic Package Deployment'
32 | 5. populate variables and then 'Generate Groovy'
33 |
34 | Here is a rather blank example:
35 |
36 | step([$class: 'AliyunEcsOpsByOssFilePublisher', region: 'cn-hangzhou', resourceType: 'ESS', resourceId: '', bucket: '', objectName: '', localPath: '', destinationDir: '', batchNumber: 1, invokeScript: ''])
37 |
38 | # How to use pipeline steps to interact with the Aliyun API
39 |
40 | * [ossUploadAndOosExec](####ossUploadAndOosExec)
41 | * [oosStatusQuery](####oosStatusQuery)
42 | * [oosExecuteNotify](####oosExecuteNotify)
43 |
44 | #### ossUploadAndOosExec
45 |
46 | Upload built project to OSS and execution OOS template download OSS file to smartly deploy on ECS instances.
47 |
48 | ```groovy
49 | executeId = ossUploadAndOosExec(batchNumber: 3, mode: 'FailurePause', bucket: 'testBucket', destinationDir: '/root/test.zip', invokeScript: '', localPath: '/', objectName: 'test.zip', pausePolicy: 'EveryBatchPause', region: 'cn-hangzhou', resourceId: 'asg-bp15XXXXX', resourceType: 'ESS')
50 | ```
51 |
52 | ##### oosStatusQuery
53 |
54 | Query OOS template task status by OSS template task id.
55 |
56 | ```groovy
57 | oosStatusQuery(executeId: "exec-XXXXXXXXX", region: 'cn-hangzhou')
58 | ```
59 |
60 | #### oosExecuteNotify
61 |
62 | Oos template pause task execution next step,like Approve or Cancelled.
63 |
64 | ```groovy
65 | oosExecuteNotify(executeId: "exec-XXXXXXXXX", region: 'cn-hangzhou', notifyType: "Approve")
66 | ```
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/OosStatusQueryStep.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import com.aliyuncs.IAcsClient;
4 | import com.aliyuncs.oos.model.v20190601.ListExecutionsRequest;
5 | import com.aliyuncs.oos.model.v20190601.ListExecutionsResponse;
6 | import edu.umd.cs.findbugs.annotations.NonNull;
7 | import hudson.Extension;
8 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.AliyunClientFactory;
9 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.StepUtils;
10 | import org.jenkinsci.plugins.workflow.steps.*;
11 | import org.kohsuke.stapler.DataBoundConstructor;
12 | import java.util.List;
13 | import java.util.Set;
14 |
15 | /**
16 | * This class is a pipeline step:
17 | * query oos template execution status by oos template execute id.
18 | */
19 | public class OosStatusQueryStep extends Step {
20 | //oos template execute region.
21 | private final String region;
22 | //oos template execute id.
23 | private final String executeId;
24 |
25 | // getXXX functions are obtain data.
26 | public String getExecuteId() {
27 | return executeId;
28 | }
29 |
30 | public String getRegion() {
31 | return region;
32 | }
33 |
34 | // bind data
35 | @DataBoundConstructor
36 | public OosStatusQueryStep(String region, String executeId) {
37 | this.executeId = executeId;
38 | this.region = region;
39 | }
40 |
41 | // step execution point.
42 | @Override
43 | public StepExecution start(StepContext stepContext) throws Exception {
44 | return new Execution(stepContext, this);
45 | }
46 |
47 | //plugin extension
48 | @Extension
49 | public static class DescriptorImpl extends StepDescriptor {
50 |
51 | @Override
52 | public Set extends Class>> getRequiredContext() {
53 | return StepUtils.requiresDefault();
54 | }
55 |
56 | @Override
57 | public String getFunctionName() {
58 | return "oosStatusQuery";
59 | }
60 |
61 | @NonNull
62 | @Override
63 | public String getDisplayName() {
64 | return "query oos execute status";
65 | }
66 | }
67 |
68 | // specific behavior of execution and return oos template execute status.
69 | public static class Execution extends SynchronousNonBlockingStepExecution {
70 | private static final long serialVersionUID = 175374543031461563L;
71 | private final transient OosStatusQueryStep step;
72 |
73 | protected Execution(@NonNull StepContext context, OosStatusQueryStep step) {
74 | super(context);
75 | this.step = step;
76 | }
77 |
78 | /**
79 | * run include:
80 | * query oos template execute status by oos template execute id.
81 | */
82 | @Override
83 | protected String run() throws Exception {
84 | AliyunClientFactory instance = new AliyunClientFactory();
85 | instance.build(this.step.region);
86 | IAcsClient oosClient = instance.getOosClient();
87 | ListExecutionsRequest request = new ListExecutionsRequest();
88 | request.setExecutionId(this.step.executeId);
89 | String status = null;
90 | // avoid frequent queries.
91 | Thread.sleep(500);
92 | List executions = oosClient.getAcsResponse(request).getExecutions();
93 | if (executions.size() > 0) {
94 | status = executions.get(0).getStatus();
95 | } else {
96 | throw new Exception("oos executeId:" + this.step.executeId + " is not exist");
97 | }
98 | return status;
99 | }
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/OosExecuteNotifyStep.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import com.aliyuncs.IAcsClient;
4 | import com.aliyuncs.oos.model.v20190601.CancelExecutionRequest;
5 | import com.aliyuncs.oos.model.v20190601.ListExecutionsRequest;
6 | import com.aliyuncs.oos.model.v20190601.ListExecutionsResponse;
7 | import com.aliyuncs.oos.model.v20190601.NotifyExecutionRequest;
8 | import edu.umd.cs.findbugs.annotations.NonNull;
9 | import hudson.Extension;
10 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.AliyunClientFactory;
11 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.Status;
12 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.StepUtils;
13 | import org.jenkinsci.plugins.workflow.steps.*;
14 | import org.kohsuke.stapler.DataBoundConstructor;
15 |
16 | import java.util.List;
17 | import java.util.Set;
18 |
19 | /**
20 | * This class is a pipeline step:
21 | * oos template execution direction,like approve or cancle.
22 | */
23 | public class OosExecuteNotifyStep extends Step {
24 | private final String region;
25 | //oos template execute id.
26 | private final String executeId;
27 | //oos template execution direction,like approve or cancle.
28 | private final String notifyType;
29 |
30 | public String getRegion() {
31 | return region;
32 | }
33 |
34 | public String getExecuteId() {
35 | return executeId;
36 | }
37 |
38 | public String getNotifyType() {
39 | return notifyType;
40 | }
41 |
42 | // bind data
43 | @DataBoundConstructor
44 | public OosExecuteNotifyStep(String region, String executeId, String notifyType) {
45 | this.region = region;
46 | this.executeId = executeId;
47 | this.notifyType = notifyType;
48 | }
49 |
50 | // step execution point.
51 | @Override
52 | public StepExecution start(StepContext stepContext) throws Exception {
53 | return new Execution(stepContext, this);
54 | }
55 |
56 | //plugin extension
57 | @Extension
58 | public static class DescriptorImpl extends StepDescriptor {
59 | @Override
60 | public Set extends Class>> getRequiredContext() {
61 | return StepUtils.requiresDefault();
62 | }
63 |
64 | @Override
65 | public String getFunctionName() {
66 | return "oosExecuteNotify";
67 | }
68 |
69 | @NonNull
70 | @Override
71 | public String getDisplayName() {
72 | return "notify oos Execute";
73 | }
74 | }
75 |
76 | //oos template execution direction,like approve or cancle.
77 | public static class Execution extends SynchronousNonBlockingStepExecution {
78 | private static final long serialVersionUID = -6033716865337394259L;
79 | private final transient OosExecuteNotifyStep step;
80 |
81 | protected Execution(@NonNull StepContext context, OosExecuteNotifyStep step) {
82 | super(context);
83 | this.step = step;
84 | }
85 |
86 | /**
87 | * run include:
88 | * oos template execution direction.
89 | */
90 | @Override
91 | protected Void run() throws Exception {
92 | AliyunClientFactory instance = new AliyunClientFactory();
93 | instance.build(this.step.region);
94 | IAcsClient oosClient = instance.getOosClient();
95 | ListExecutionsRequest request = new ListExecutionsRequest();
96 | request.setExecutionId(this.step.executeId);
97 | String status = null;
98 | List executions = oosClient.getAcsResponse(request).getExecutions();
99 | if (executions.size() > 0) {
100 | status = executions.get(0).getStatus();
101 | } else {
102 | throw new Exception("oos executeId:" + this.step.executeId + "is not exist");
103 | }
104 | if ("Approve".equalsIgnoreCase(this.step.notifyType)) {
105 | if (Status.Waiting.name().equalsIgnoreCase(status)) {
106 | NotifyExecutionRequest notifyExecutionRequest = new NotifyExecutionRequest();
107 | notifyExecutionRequest.setExecutionId(this.step.executeId);
108 | notifyExecutionRequest.setNotifyType(this.step.notifyType);
109 | oosClient.getAcsResponse(notifyExecutionRequest);
110 | }
111 | }
112 | if ("Cancelled".equalsIgnoreCase(this.step.notifyType)) {
113 | if (!Status.Success.name().equalsIgnoreCase(status) && !Status.Failed.name().equalsIgnoreCase(status) && !Status.Cancelled.name().equalsIgnoreCase(status)) {
114 | CancelExecutionRequest cancelExecutionRequest = new CancelExecutionRequest();
115 | cancelExecutionRequest.setExecutionId(this.step.executeId);
116 | oosClient.getAcsResponse(cancelExecutionRequest);
117 | }
118 | }
119 | return null;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.jenkins-ci.plugins
7 | plugin
8 | 4.59
9 |
10 |
11 | io.jenkins.plugins
12 | alibabacloud-pkg-deployment
13 | 1.0-SNAPSHOT
14 | hpi
15 |
16 | 2.361.4
17 | 1.6.5
18 |
19 | Alibabacloud Package Deployment
20 | Plugins for deployment package on Alibaba Cloud
21 |
22 |
23 | MIT License
24 | http://opensource.org/licenses/MIT
25 | repo
26 |
27 |
28 |
29 |
30 | linan.zln
31 | Linan Zhang
32 | wb-zln530580@alibaba-inc.com
33 |
34 |
35 |
36 | scm:git:https://github.com/jenkinsci/${project.artifactId}-plugin.git
37 | scm:git:https://github.com/jenkinsci/${project.artifactId}-plugin
38 | scm:git:https://github.com/jenkinsci/${project.artifactId}-plugin
39 |
40 |
41 |
42 | org.jenkins-ci.plugins.workflow
43 | workflow-step-api
44 |
45 |
46 | com.alibaba
47 | fastjson
48 | 2.0.27
49 |
50 |
51 | com.aliyun.oss
52 | aliyun-sdk-oss
53 | 3.16.2
54 |
55 |
56 | org.codehaus.jettison
57 | jettison
58 |
59 |
60 | com.aliyun
61 | aliyun-java-sdk-kms
62 |
63 |
64 | com.aliyun
65 | aliyun-java-sdk-ram
66 |
67 |
68 | com.aliyun
69 | aliyun-java-sdk-core
70 |
71 |
72 |
73 |
74 | com.aliyun
75 | aliyun-java-sdk-core
76 | 4.5.10
77 |
78 |
79 | org.ini4j
80 | ini4j
81 |
82 |
83 | org.slf4j
84 | slf4j-api
85 |
86 |
87 | org.jacoco
88 | org.jacoco.agent
89 |
90 |
91 | org.apache.httpcomponents
92 | httpclient
93 |
94 |
95 | org.apache.httpcomponents
96 | httpcore
97 |
98 |
99 | com.google.code.gson
100 | gson
101 |
102 |
103 |
104 |
105 | com.aliyun
106 | aliyun-java-sdk-oos
107 | 1.5.10
108 |
109 |
110 |
111 |
112 |
113 | io.jenkins.tools.bom
114 | bom-2.361.x
115 | 1981.v17df70e84a_a_1
116 | import
117 | pom
118 |
119 |
120 |
121 |
122 |
123 | repo.jenkins-ci.org
124 | https://repo.jenkins-ci.org/public/
125 |
126 |
127 |
128 |
129 | repo.jenkins-ci.org
130 | https://repo.jenkins-ci.org/public/
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/AliyunEcsOpsByOssFilePublisher.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.aliyun.oss.model.*;
5 | import com.aliyuncs.exceptions.ClientException;
6 | import com.aliyuncs.oos.model.v20190601.ListExecutionsRequest;
7 | import com.aliyuncs.oos.model.v20190601.StartExecutionRequest;
8 | import com.aliyuncs.oos.model.v20190601.StartExecutionResponse;
9 | import edu.umd.cs.findbugs.annotations.NonNull;
10 | import hudson.*;
11 | import hudson.model.AbstractProject;
12 | import hudson.model.Run;
13 | import hudson.model.TaskListener;
14 | import hudson.tasks.BuildStepDescriptor;
15 | import hudson.tasks.BuildStepMonitor;
16 | import hudson.tasks.Publisher;
17 | import hudson.util.FormValidation;
18 | import hudson.util.ListBoxModel;
19 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.AliyunClientFactory;
20 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.ResourceType;
21 | import jenkins.tasks.SimpleBuildStep;
22 | import org.apache.commons.lang.StringUtils;
23 | import org.jenkinsci.Symbol;
24 | import org.kohsuke.stapler.DataBoundConstructor;
25 | import org.kohsuke.stapler.QueryParameter;
26 | import org.kohsuke.stapler.interceptor.RequirePOST;
27 |
28 | import java.io.*;
29 | import java.util.*;
30 |
31 | /**
32 | * This class is a jenkins execute step:
33 | * apply to freestyle job post bulid or pipeline step
34 | */
35 | public class AliyunEcsOpsByOssFilePublisher extends Publisher implements SimpleBuildStep {
36 | /**
37 | * ESS_TEMPLATE_NAME and ECS_TEMPLATE_NAME are OOS template name.
38 | */
39 | private final static String ESS_TEMPLATE_NAME = "ACS-ESS-RollingUpdateByDownloadOSSFileAndRunCommand";
40 | private final static String ECS_TEMPLATE_NAME = "ACS-ECS-BulkyDownloadOSSFileAndRunCommand";
41 |
42 | //ess or ecs resource location
43 | private final String region;
44 |
45 | //resource type: ESS or ECS
46 | private final String resourceType;
47 |
48 | /**
49 | * resource id:
50 | * ESS:scalingGroupId
51 | * ECS: instanceIds by comma separated
52 | */
53 | private final String resourceId;
54 |
55 | // oss bucket name.
56 | private final String bucket;
57 |
58 | // bulit project upload OSS bucket specific path.
59 | private final String objectName;
60 |
61 | //package project path:must be directory.
62 | private final String localPath;
63 |
64 | //OOS template download OSS bucket File to ECS specific file path
65 | private final String destinationDir;
66 |
67 | //OOS template number of execution batches.
68 | private final int batchNumber;
69 |
70 | //OOS template execute script on ECS after download OSS bucket File to ECS specific file path.
71 | private final String invokeScript;
72 |
73 | // bind data
74 | @DataBoundConstructor
75 | public AliyunEcsOpsByOssFilePublisher(String region, String resourceType, String resourceId, String bucket, String objectName, String localPath, String destinationDir, int batchNumber, String invokeScript) {
76 | this.region = region;
77 | this.resourceType = resourceType;
78 | this.resourceId = resourceId;
79 | this.bucket = bucket;
80 | this.objectName = objectName;
81 | this.localPath = localPath;
82 | this.destinationDir = destinationDir;
83 | this.batchNumber = batchNumber;
84 | this.invokeScript = invokeScript;
85 | }
86 |
87 | // getXXX functions are obtain data.
88 | public int getBatchNumber() {
89 | return batchNumber;
90 | }
91 |
92 | public String getRegion() {
93 | return region;
94 | }
95 |
96 | public String getResourceType() {
97 | return resourceType;
98 | }
99 |
100 | public String getResourceId() {
101 | return resourceId;
102 | }
103 |
104 | public String getBucket() {
105 | return bucket;
106 | }
107 |
108 | public String getObjectName() {
109 | return objectName;
110 | }
111 |
112 | public String getLocalPath() {
113 | return localPath;
114 | }
115 |
116 | public String getDestinationDir() {
117 | return destinationDir;
118 | }
119 |
120 | public String getInvokeScript() {
121 | return invokeScript;
122 | }
123 |
124 | /**
125 | * perform is core function: it can be automatically executed based on the project built.
126 | */
127 | @Override
128 | public void perform(@NonNull Run, ?> build, @NonNull FilePath workspace, @NonNull EnvVars env, @NonNull Launcher launcher, @NonNull TaskListener listener) throws InterruptedException, IOException {
129 | /**
130 | * get and check localPath
131 | * */
132 | final Map envVars = build.getEnvironment(listener);
133 | String localPathFromEnv = getLocalPathFromEnv(envVars);
134 | String localPath = StringUtils.trimToEmpty(localPathFromEnv);
135 | if (!localPath.isEmpty() && !localPath.startsWith("/")) {
136 | localPath = "/" + localPath;
137 | }
138 | FilePath sourcePath = workspace.withSuffix(localPath).absolutize();
139 | if (!sourcePath.isDirectory() || !isSubDirectory(workspace, sourcePath)) {
140 | throw new IllegalArgumentException("Provided path (resolved as '" + sourcePath
141 | + "') is not a subdirectory of the workspace (resolved as '" + workspace + "')");
142 | }
143 | final FilePath sourceDirectory = sourcePath;
144 | //acquired build name
145 | final String projectName = build.getDisplayName();
146 | //log util
147 | final PrintStream logger = listener.getLogger();
148 | listener.getLogger().println("resourceType:" + resourceType);
149 | AliyunClientFactory instance = new AliyunClientFactory();
150 | instance.build(this.region);
151 | // Compress and upload the specific path of the built project.
152 | zipAndUpload(instance, projectName, sourceDirectory, logger);
153 | //batch automatic execution oos template according to resource type.
154 | String executionId = null;
155 | StartExecutionRequest request = new StartExecutionRequest();
156 | //query execute status until execution end.
157 | ListExecutionsRequest executionsRequest = new ListExecutionsRequest();
158 | if ("ESS".equals(resourceType)) {
159 | // ess resource execute template.
160 | executionId = essResourceExec(request, instance, listener);
161 | executionsRequest.setExecutionId(executionId);
162 | executionsRequest.setTemplateName(ESS_TEMPLATE_NAME);
163 | } else {
164 | // ecs resource execute template.
165 | executionId = ecsResourceExec(request, instance, listener);
166 | executionsRequest.setExecutionId(executionId);
167 | executionsRequest.setTemplateName(ECS_TEMPLATE_NAME);
168 | }
169 |
170 | String status = null;
171 | while (!"Success".equalsIgnoreCase(status) && !"Failed".equalsIgnoreCase(status) && !"Cancelled".equalsIgnoreCase(status)) {
172 | try {
173 | Thread.sleep(500);
174 | status = instance.getOosClient().getAcsResponse(executionsRequest).getExecutions().get(0).getStatus();
175 | listener.getLogger().println("ExecutionId Status:" + status);
176 | } catch (ClientException e) {
177 | e.printStackTrace();
178 | }
179 | }
180 | }
181 |
182 | // ess resource execute oos Template : ESS_TEMPLATE_NAME
183 | private String essResourceExec(StartExecutionRequest request, AliyunClientFactory instance, TaskListener listener) {
184 | request.setTemplateName(ESS_TEMPLATE_NAME);
185 | String parameter =
186 | "{\"invokeDestinationDir\":\"" +
187 | "" + destinationDir + "" +
188 | "\"," +
189 | "\"scalingGroupId\":\"" +
190 | "" + resourceId + "" +
191 | "\"," +
192 | "\"invokeScript\":\"" +
193 | invokeScript +
194 | "\"," +
195 | "\"OSSRegion\":\"" +
196 | "" + region + "" +
197 | "\"," +
198 | "\"whetherSaveToFile\":true," +
199 | "\"URLExpirationTime\":6000," +
200 | "\"batchNumber\":" +
201 | "" +
202 | this.batchNumber +
203 | "" +
204 | "," +
205 | "\"rollbackBucketName\":\"" +
206 | "" + bucket + "" +
207 | "\"," +
208 | "\"rollbackObjectName\":\"" +
209 | "" + objectName + "" +
210 | "\"," +
211 | "\"rollbackDestinationDir\":\"" +
212 | "" + destinationDir + "" +
213 | "\"," +
214 | "\"invokeBucketName\":\"" +
215 | "" + bucket + "" +
216 | "\"," +
217 | "\"invokeObjectName\":\"" +
218 | "" + objectName + "" +
219 | "\"," +
220 | "\"invokeType\":\"" +
221 | "" + "invoke" + "" +
222 | "\"}";
223 | request.setParameters(parameter);
224 | StartExecutionResponse response = null;
225 | String executionId = null;
226 | try {
227 | response = instance.getOosClient().getAcsResponse(request);
228 | executionId = response.getExecution().getExecutionId();
229 | listener.getLogger().println("you can login aliyun oos console to query oos template implementation progress:" + "https://oos.console.aliyun.com/" + region + "/execution/detail/" + executionId);
230 | } catch (ClientException e) {
231 | listener.getLogger().println("execute oos template error info:");
232 | listener.getLogger().println(e);
233 | }
234 | return executionId;
235 | }
236 |
237 | // ecs resource execute oos Template : ECS_TEMPLATE_NAME
238 | private String ecsResourceExec(StartExecutionRequest request, AliyunClientFactory instance, TaskListener listener) {
239 | request.setTemplateName(ECS_TEMPLATE_NAME);
240 | String[] instanceIdString = this.resourceId.split(",");
241 | HashSet hashSet = new HashSet<>(Arrays.asList(instanceIdString));
242 | int ids = hashSet.size();
243 | int batchNumber = this.batchNumber;
244 | if(ids < batchNumber){
245 | batchNumber = ids;
246 | }
247 | int base = ids / batchNumber;
248 | int[] batchArray = new int[batchNumber];
249 | Arrays.fill(batchArray, base);
250 | for (int i = ids % batchNumber; i > 0; i--) {
251 | batchArray[i - 1]++;
252 | }
253 | String batchSpeed = JSON.toJSON(batchArray).toString();
254 | List list = new ArrayList<>(hashSet);
255 | String instanceIds = JSON.toJSON(list).toString();
256 | String parameter =
257 | "{\"bucketName\":\"" +
258 | this.bucket +
259 | "\"," +
260 | "\"objectName\":\"" +
261 | this.objectName +
262 | "\"," +
263 | " \"rateControl\": " +
264 | "{\"Mode\": \"Batch\"," +
265 | " \"MaxErrors\": 0, " +
266 | "\"BatchPauseOption\": \"" +
267 | "Automatic" +
268 | "\", " +
269 | "\"Batch\": " +
270 | batchSpeed +
271 | "}, " +
272 | "" +
273 | "\"destinationDir\":\"" +
274 | this.destinationDir +
275 | "\"," +
276 | "\"commandContent\":\"" +
277 | this.invokeScript +
278 | "\"," +
279 | "\"targets\":" +
280 | "{\"ResourceIds\":" +
281 | instanceIds +
282 | "," +
283 | "\"RegionId\":\"" +
284 | this.region +
285 | "\"," +
286 | "\"Type\":\"ResourceIds\"}," +
287 | "\"OSSRegion\":\"" +
288 | this.region +
289 | "\"}";
290 | request.setParameters(parameter);
291 | StartExecutionResponse response = null;
292 | String executionId = null;
293 | try {
294 | response = instance.getOosClient().getAcsResponse(request);
295 | executionId = response.getExecution().getExecutionId();
296 | listener.getLogger().println("you can login aliyun oos console to query oos template implementation progress:" + "https://oos.console.aliyun.com/" + region + "/execution/detail/" + executionId);
297 | } catch (ClientException e) {
298 | listener.getLogger().println("execute oos template error info:");
299 | listener.getLogger().println(e);
300 | }
301 | return executionId;
302 | }
303 |
304 | //compress directory of localPath and upload to OSS.
305 | private void zipAndUpload(AliyunClientFactory instance, String projectName, FilePath sourceDirectory, PrintStream logger) throws InterruptedException, IOException {
306 | File zipFile = zipProject(projectName, sourceDirectory, logger);
307 | uploadOssFile(instance, zipFile, logger);
308 | }
309 |
310 | private File zipProject(String projectName, FilePath sourceDirectory, PrintStream logger) throws IOException, InterruptedException {
311 | File zipFile = null;
312 | File versionFile;
313 | versionFile = new File(sourceDirectory + "/");
314 | InputStreamReader reader = null;
315 | String version = null;
316 | try {
317 | reader = new InputStreamReader(new FileInputStream(versionFile), "UTF-8");
318 | char[] chars = new char[(int) versionFile.length() - 1];
319 | reader.read(chars);
320 | version = new String(chars);
321 | reader.close();
322 | } catch (IOException e) {
323 | e.printStackTrace();
324 | } finally {
325 | if (reader != null) {
326 | reader.close();
327 | }
328 | }
329 | if (version != null) {
330 | zipFile = new File("/tmp/" + projectName + "-" + version + ".zip");
331 | final boolean fileCreated = zipFile.createNewFile();
332 | if (!fileCreated) {
333 | logger.println("File already exists, overwriting: " + zipFile.getPath());
334 | }
335 | } else {
336 | zipFile = File.createTempFile(projectName + "-", ".zip");
337 | }
338 | logger.println("Zipping files into " + zipFile.getAbsolutePath());
339 |
340 | FileOutputStream outputStream = new FileOutputStream(zipFile);
341 | try {
342 | sourceDirectory.zip(
343 | outputStream,
344 | new FileFilter() {
345 | @Override
346 | public boolean accept(File pathname) {
347 | return true;
348 | }
349 | }
350 | );
351 | } finally {
352 | outputStream.close();
353 | }
354 | return zipFile;
355 | }
356 |
357 | private void uploadOssFile(AliyunClientFactory instance, File zipFile, PrintStream logger) {
358 | String bucketName = this.bucket;
359 | try {
360 | InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
361 | InitiateMultipartUploadResult upresult = instance.getOssClient().initiateMultipartUpload(request);
362 | String uploadId = upresult.getUploadId();
363 | List partETags = new ArrayList();
364 | final long partSize = 1 * 1024 * 1024L;
365 | long fileLength = zipFile.length();
366 | int partCount = (int) (fileLength / partSize);
367 | if (fileLength % partSize != 0) {
368 | partCount++;
369 | }
370 | for (int i = 0; i < partCount; i++) {
371 | long startPos = i * partSize;
372 | long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
373 | InputStream instream = new FileInputStream(zipFile);
374 | instream.skip(startPos);
375 | UploadPartRequest uploadPartRequest = new UploadPartRequest();
376 | uploadPartRequest.setBucketName(bucketName);
377 | uploadPartRequest.setKey(objectName);
378 | uploadPartRequest.setUploadId(uploadId);
379 | uploadPartRequest.setInputStream(instream);
380 | uploadPartRequest.setPartSize(curPartSize);
381 | uploadPartRequest.setPartNumber(i + 1);
382 | UploadPartResult uploadPartResult = instance.getOssClient().uploadPart(uploadPartRequest);
383 | partETags.add(uploadPartResult.getPartETag());
384 | }
385 | CompleteMultipartUploadRequest completeMultipartUploadRequest =
386 | new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
387 | CompleteMultipartUploadResult completeMultipartUploadResult = instance.getOssClient().completeMultipartUpload(completeMultipartUploadRequest);
388 | logger.println(completeMultipartUploadResult.getETag());
389 | } catch (Exception e) {
390 | logger.println(e);
391 | } finally {
392 | final boolean deleted = zipFile.delete();
393 | if (!deleted) {
394 | logger.println("Failed to clean up file " + zipFile.getPath());
395 | }
396 | if (instance.getOssClient() != null) {
397 | instance.getOssClient().shutdown();
398 | }
399 | }
400 | }
401 |
402 | @Override
403 | public DescriptorImpl getDescriptor() {
404 | return (DescriptorImpl) super.getDescriptor();
405 | }
406 |
407 | private boolean isSubDirectory(FilePath parent, FilePath child) {
408 | FilePath parentFolder = child;
409 | while (parentFolder != null) {
410 | if (parent.equals(parentFolder)) {
411 | return true;
412 | }
413 | parentFolder = parentFolder.getParent();
414 | }
415 | return false;
416 | }
417 |
418 | public String getLocalPathFromEnv(Map envVars) {
419 | return Util.replaceMacro(this.localPath, envVars);
420 | }
421 |
422 | @Override
423 | public BuildStepMonitor getRequiredMonitorService() {
424 | return BuildStepMonitor.NONE;
425 | }
426 |
427 | /**
428 | * extension build step descriptor:
429 | * accessKeyId and accessKeySecret set global configuration in system management.
430 | * can set select component.
431 | */
432 | @Extension
433 | @Symbol("Alibabacloud Automatic Package Deployment")
434 | public static final class DescriptorImpl extends BuildStepDescriptor {
435 | @RequirePOST
436 | @SuppressWarnings("lgtm[jenkins/no-permission-check]")
437 | public FormValidation doCheckObjectName(@QueryParameter String objectName) {
438 | if (objectName.startsWith("/"))
439 | return FormValidation.error("objectName can not start with '/'");
440 | return FormValidation.ok();
441 | }
442 |
443 | // select component about region.
444 | public ListBoxModel doFillRegionItems() throws ClientException {
445 | ListBoxModel model = new ListBoxModel();
446 | model.add("华东1(杭州)", "cn-hangzhou");
447 | model.add("华北1(青岛)", "cn-qingdao");
448 | model.add("华北2(北京)", "cn-beijing");
449 | model.add("华北3(张家口)", "cn-zhangjiakou");
450 | model.add("华北5(呼和浩特)", "cn-huhehaote");
451 | model.add("华北6(乌兰察布)", "cn-wulanchabu");
452 | model.add("华东2(上海)", "cn-shanghai");
453 | model.add("华南1(深圳)", "cn-shenzhen");
454 | model.add("华南2(河源)", "cn-heyuan");
455 | model.add("华南3(广州)", "cn-guangzhou");
456 | model.add("西南1(成都)", "cn-chengdu");
457 | model.add("中国(香港)", "cn-hongkong");
458 | model.add("亚太东北 1 (东京)", "ap-northeast-1");
459 | model.add("韩国(首尔)", "ap-northeast-2");
460 | model.add("亚太东南 1 (新加坡)", "ap-southeast-1");
461 | model.add("亚太东南 2 (悉尼)", "ap-southeast-2");
462 | model.add("亚太东南 3 (吉隆坡)", "ap-southeast-3");
463 | model.add("菲律宾(马尼拉)", "ap-southeast-6");
464 | model.add("亚太东南 5 (雅加达)", "ap-southeast-5");
465 | model.add("亚太南部 1 (孟买)", "ap-south-1");
466 | model.add("泰国(曼谷)", "ap-southeast-7");
467 | model.add("美国东部 1 (弗吉尼亚)", "us-east-1");
468 | model.add("美国西部 1 (硅谷)", "us-west-1");
469 | model.add("英国 (伦敦)", "eu-west-1");
470 | model.add("中东东部 1 (迪拜)", "me-east-1");
471 | model.add("沙特(利雅得)", "me-central-1");
472 | model.add("欧洲中部 1 (法兰克福)", "eu-central-1");
473 | return model;
474 | }
475 |
476 | // select component about resource type.
477 | @RequirePOST
478 | @SuppressWarnings("lgtm[jenkins/no-permission-check]")
479 | public ListBoxModel doFillResourceTypeItems() throws ClientException {
480 | ListBoxModel items = new ListBoxModel();
481 | for (ResourceType resourceType : ResourceType.values()) {
482 | items.add(resourceType.getName(), resourceType.getType());
483 | }
484 | return items;
485 | }
486 |
487 |
488 | @Override
489 | public boolean isApplicable(Class extends AbstractProject> jobType) {
490 | return true;
491 | }
492 |
493 | //extension plugin name.
494 | @NonNull
495 | @Override
496 | public String getDisplayName() {
497 | return "Alibabacloud Automatic Package Deployment";
498 | }
499 | }
500 |
501 | }
502 |
--------------------------------------------------------------------------------
/src/main/java/io/jenkins/plugins/alibabacloud/pkg/deployment/OssUploadAndOosExecStep.java:
--------------------------------------------------------------------------------
1 | package io.jenkins.plugins.alibabacloud.pkg.deployment;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.aliyun.oss.OSS;
5 | import com.aliyun.oss.model.*;
6 | import com.aliyuncs.IAcsClient;
7 | import com.aliyuncs.exceptions.ClientException;
8 | import com.aliyuncs.oos.model.v20190601.ListExecutionsRequest;
9 | import com.aliyuncs.oos.model.v20190601.StartExecutionRequest;
10 | import com.aliyuncs.oos.model.v20190601.StartExecutionResponse;
11 | import edu.umd.cs.findbugs.annotations.NonNull;
12 | import hudson.Extension;
13 | import hudson.FilePath;
14 | import hudson.Util;
15 | import hudson.model.Run;
16 | import hudson.model.TaskListener;
17 | import hudson.util.FormValidation;
18 | import hudson.util.ListBoxModel;
19 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.AliyunClientFactory;
20 | import io.jenkins.plugins.alibabacloud.pkg.deployment.utils.StepUtils;
21 | import org.apache.commons.lang.StringUtils;
22 | import org.jenkinsci.plugins.workflow.steps.*;
23 | import org.kohsuke.stapler.DataBoundConstructor;
24 | import org.kohsuke.stapler.QueryParameter;
25 | import org.kohsuke.stapler.interceptor.RequirePOST;
26 |
27 | import java.io.*;
28 | import java.util.*;
29 | /**
30 | * This class is a pipeline step:
31 | * 1.compress specific directory
32 | * 2.upload to oss
33 | * 3.execute oos template (download oss file to ecs specific path)
34 | */
35 | public class OssUploadAndOosExecStep extends Step {
36 | /**
37 | * ESS_TEMPLATE_NAME and ECS_TEMPLATE_NAME are OOS template name.
38 | */
39 | private final static String ESS_TEMPLATE_NAME = "ACS-ESS-RollingUpdateByDownloadOSSFileAndRunCommand";
40 | private final static String ECS_TEMPLATE_NAME = "ACS-ECS-BulkyDownloadOSSFileAndRunCommand";
41 |
42 | //ess or ecs resource location
43 | private final String region;
44 |
45 | //resource type: ESS or ECS
46 | private final String resourceType;
47 |
48 | /**
49 | * resource id:
50 | * ESS:scalingGroupId
51 | * ECS: instanceIds by comma separated
52 | */
53 | private final String resourceId;
54 | // oss bucket name.
55 | private final String bucket;
56 | // bulit project upload OSS bucket specific path.
57 | private final String objectName;
58 | //package project path:must be directory.
59 | private final String localPath;
60 | //the OOS template execution mode. Valid values:Automatic、FailurePause、Debug.
61 | private final String mode;
62 | //the OOS template loop mode. Valid values: Automatic、FirstBatchPause、EveryBatchPause.
63 | private final String pausePolicy;
64 | //OOS template number of execution batches.
65 | private final int batchNumber;
66 | //OOS template download OSS bucket File to ECS specific file path
67 | private final String destinationDir;
68 | //OOS template execute script on ECS after download OSS bucket File to ECS specific file path.
69 | private final String invokeScript;
70 |
71 | // getXXX functions are obtain data.
72 | public String getRegion() {
73 | return region;
74 | }
75 |
76 | public String getResourceType() {
77 | return resourceType;
78 | }
79 |
80 | public String getResourceId() {
81 | return resourceId;
82 | }
83 |
84 | public String getBucket() {
85 | return bucket;
86 | }
87 |
88 | public String getObjectName() {
89 | return objectName;
90 | }
91 |
92 | public String getLocalPath() {
93 | return localPath;
94 | }
95 |
96 | public String getMode() {
97 | return mode;
98 | }
99 |
100 | public String getPausePolicy() {
101 | return pausePolicy;
102 | }
103 |
104 | public int getBatchNumber() {
105 | return batchNumber;
106 | }
107 |
108 | public String getDestinationDir() {
109 | return destinationDir;
110 | }
111 |
112 | public String getInvokeScript() {
113 | return invokeScript;
114 | }
115 |
116 | // bind data
117 | @DataBoundConstructor
118 | public OssUploadAndOosExecStep(String region, String resourceType, String resourceId, String bucket, String objectName, String localPath, String mode, String pausePolicy, int batchNumber, String destinationDir, String invokeScript) {
119 | this.region = region;
120 | this.resourceType = resourceType;
121 | this.resourceId = resourceId;
122 | this.bucket = bucket;
123 | this.objectName = objectName;
124 | this.localPath = localPath;
125 | this.mode = mode;
126 | this.pausePolicy = pausePolicy;
127 | this.batchNumber = batchNumber;
128 | this.destinationDir = destinationDir;
129 | this.invokeScript = invokeScript;
130 | }
131 |
132 | // step execution point.
133 | @Override
134 | public StepExecution start(StepContext stepContext) throws Exception {
135 | return new Execution(stepContext, this);
136 | }
137 |
138 | //plugin extension
139 | @Extension
140 | public static class DescriptorImpl extends StepDescriptor {
141 |
142 | @Override
143 | public Set extends Class>> getRequiredContext() {
144 | return StepUtils.requires(TaskListener.class, Run.class, FilePath.class);
145 | }
146 |
147 | @Override
148 | public String getFunctionName() {
149 | return "ossUploadAndOosExec";
150 | }
151 |
152 | @NonNull
153 | @Override
154 | public String getDisplayName() {
155 | return "OSS upload built project and OOS execute";
156 | }
157 |
158 | public ListBoxModel doFillRegionItems() {
159 | ListBoxModel model = new ListBoxModel();
160 | model.add("华东1(杭州)", "cn-hangzhou");
161 | model.add("华北1(青岛)", "cn-qingdao");
162 | model.add("华北2(北京)", "cn-beijing");
163 | model.add("华北3(张家口)", "cn-zhangjiakou");
164 | model.add("华北5(呼和浩特)", "cn-huhehaote");
165 | model.add("华北6(乌兰察布)", "cn-wulanchabu");
166 | model.add("华东2(上海)", "cn-shanghai");
167 | model.add("华南1(深圳)", "cn-shenzhen");
168 | model.add("华南2(河源)", "cn-heyuan");
169 | model.add("华南3(广州)", "cn-guangzhou");
170 | model.add("西南1(成都)", "cn-chengdu");
171 | model.add("中国(香港)", "cn-hongkong");
172 | model.add("亚太东北 1 (东京)", "ap-northeast-1");
173 | model.add("韩国(首尔)", "ap-northeast-2");
174 | model.add("亚太东南 1 (新加坡)", "ap-southeast-1");
175 | model.add("亚太东南 2 (悉尼)", "ap-southeast-2");
176 | model.add("亚太东南 3 (吉隆坡)", "ap-southeast-3");
177 | model.add("菲律宾(马尼拉)", "ap-southeast-6");
178 | model.add("亚太东南 5 (雅加达)", "ap-southeast-5");
179 | model.add("亚太南部 1 (孟买)", "ap-south-1");
180 | model.add("泰国(曼谷)", "ap-southeast-7");
181 | model.add("美国东部 1 (弗吉尼亚)", "us-east-1");
182 | model.add("美国西部 1 (硅谷)", "us-west-1");
183 | model.add("英国 (伦敦)", "eu-west-1");
184 | model.add("中东东部 1 (迪拜)", "me-east-1");
185 | model.add("沙特(利雅得)", "me-central-1");
186 | model.add("欧洲中部 1 (法兰克福)", "eu-central-1");
187 | return model;
188 | }
189 |
190 | public ListBoxModel doFillResourceTypeItems() {
191 | ListBoxModel model = new ListBoxModel();
192 | model.add("ESS ScalingGroup", "ESS");
193 | model.add("ECS Instance", "ECS");
194 | return model;
195 | }
196 |
197 | public ListBoxModel doFillModeItems() {
198 | ListBoxModel model = new ListBoxModel();
199 | model.add("自动执行", "Automatic");
200 | model.add("失败暂停", "FailurePause");
201 | model.add("单步执行", "Debug");
202 | return model;
203 | }
204 |
205 | @RequirePOST
206 | @SuppressWarnings("lgtm[jenkins/no-permission-check]")
207 | public FormValidation doCheckObjectName(@QueryParameter String objectName) {
208 | if (objectName.startsWith("/"))
209 | return FormValidation.error("objectName can not start with '/'");
210 | return FormValidation.ok();
211 | }
212 |
213 | public ListBoxModel doFillPausePolicyItems() {
214 | ListBoxModel model = new ListBoxModel();
215 | model.add("不暂停", "Automatic");
216 | model.add("第一批暂停", "FirstBatchPause");
217 | model.add("每批暂停", "EveryBatchPause");
218 | return model;
219 | }
220 |
221 | }
222 |
223 | // specific behavior of execution and return oos template execute id.
224 | public static class Execution extends SynchronousNonBlockingStepExecution {
225 | private static final long serialVersionUID = 1L;
226 | private final transient OssUploadAndOosExecStep step;
227 |
228 | protected Execution(@NonNull StepContext context, OssUploadAndOosExecStep step) {
229 | super(context);
230 | this.step = step;
231 | }
232 |
233 | /**
234 | * run include:
235 | * 1.compress specific directory
236 | * 2.upload compressed file to oss
237 | * 3.OOS template execute script on ECS after OOS template download OSS bucket File to ECS specific file path.
238 | */
239 | @Override
240 | protected String run() throws Exception {
241 | AliyunClientFactory instance = new AliyunClientFactory();
242 | instance.build(this.step.region);
243 | IAcsClient oosClient = instance.getOosClient();
244 | OSS ossClient = instance.getOssClient();
245 | TaskListener listener = getContext().get(TaskListener.class);
246 | Run build = getContext().get(Run.class);
247 | FilePath workspace = getContext().get(FilePath.class);
248 | final Map envVars = build.getEnvironment(listener);
249 | String localPathFromEnv = getLocalPathFromEnv(envVars);
250 | String localPath = StringUtils.trimToEmpty(localPathFromEnv);
251 | if (!this.step.localPath.isEmpty() && !this.step.localPath.startsWith("/")) {
252 | localPath = "/" + this.step.localPath;
253 | }
254 | FilePath sourcePath = workspace.withSuffix(localPath).absolutize();
255 | if (!sourcePath.isDirectory() || !isSubDirectory(workspace, sourcePath)) {
256 | throw new IllegalArgumentException("Provided path (resolved as '" + sourcePath
257 | + "') is not a subdirectory of the workspace (resolved as '" + workspace + "')");
258 | }
259 | final FilePath sourceDirectory = sourcePath;
260 | final String projectName = build.getDisplayName();
261 | final PrintStream logger = listener.getLogger();
262 | zipAndUpload(ossClient, projectName, sourceDirectory, logger);
263 | String executionId = null;
264 | StartExecutionRequest request = new StartExecutionRequest();
265 | request.setMode(this.step.mode);
266 | ListExecutionsRequest executionsRequest = new ListExecutionsRequest();
267 | if ("ESS".equals(this.step.resourceType)) {
268 | executionId = essResourceExec(request, oosClient, listener);
269 | executionsRequest.setExecutionId(executionId);
270 | executionsRequest.setTemplateName(ESS_TEMPLATE_NAME);
271 | } else {
272 | executionId = ecsResourceExec(request, oosClient, listener);
273 | executionsRequest.setExecutionId(executionId);
274 | executionsRequest.setTemplateName(ECS_TEMPLATE_NAME);
275 | }
276 | String status = null;
277 | while (!"Success".equalsIgnoreCase(status) && !"Failed".equalsIgnoreCase(status) && !"Cancelled".equalsIgnoreCase(status) && !"Waiting".equalsIgnoreCase(status)) {
278 | try {
279 | Thread.sleep(5000);
280 | status = oosClient.getAcsResponse(executionsRequest).getExecutions().get(0).getStatus();
281 | listener.getLogger().println("ExecutionId Status:" + status);
282 | } catch (ClientException e) {
283 | e.printStackTrace();
284 | }
285 | }
286 | return executionId;
287 | }
288 |
289 | // ecs resource execute oos Template : ECS_TEMPLATE_NAME
290 | private String ecsResourceExec(StartExecutionRequest request, IAcsClient oosClient, TaskListener listener) {
291 | request.setTemplateName(ECS_TEMPLATE_NAME);
292 | String[] instanceIdString = this.step.resourceId.split(",");
293 | HashSet hashSet = new HashSet<>(Arrays.asList(instanceIdString));
294 | int ids = hashSet.size();
295 | int batchNumber = this.step.batchNumber;
296 | if(ids < batchNumber){
297 | batchNumber = ids;
298 | }
299 | int base = ids / batchNumber;
300 | int[] batchArray = new int[batchNumber];
301 | Arrays.fill(batchArray, base);
302 | for (int i = ids % batchNumber; i > 0; i--) {
303 | batchArray[i - 1]++;
304 | }
305 | String batchSpeed = JSON.toJSON(batchArray).toString();
306 | List list = new ArrayList<>(hashSet);
307 | String instanceIds = JSON.toJSON(list).toString();
308 | String parameter =
309 | "{\"bucketName\":\"" +
310 | this.step.bucket +
311 | "\"," +
312 | "\"objectName\":\"" +
313 | this.step.objectName +
314 | "\"," +
315 | " \"rateControl\": " +
316 | "{\"Mode\": \"Batch\"," +
317 | " \"MaxErrors\": 0, " +
318 | "\"BatchPauseOption\": \"" +
319 | this.step.pausePolicy +
320 | "\", " +
321 | "\"Batch\": " +
322 | batchSpeed +
323 | "}, " +
324 | "" +
325 | "\"destinationDir\":\"" +
326 | this.step.destinationDir +
327 | "\"," +
328 | "\"commandContent\":\"" +
329 | this.step.invokeScript +
330 | "\"," +
331 | "\"targets\":" +
332 | "{\"ResourceIds\":" +
333 | instanceIds +
334 | "," +
335 | "\"RegionId\":\"" +
336 | this.step.region +
337 | "\"," +
338 | "\"Type\":\"ResourceIds\"}," +
339 | "\"OSSRegion\":\"" +
340 | this.step.region +
341 | "\"}";
342 | request.setParameters(parameter);
343 | StartExecutionResponse response = null;
344 | String executionId = null;
345 | try {
346 | response = oosClient.getAcsResponse(request);
347 | executionId = response.getExecution().getExecutionId();
348 | listener.getLogger().println("you can login aliyun oos console to query oos template implementation progress:" + "https://oos.console.aliyun.com/" + this.step.region + "/execution/detail/" + executionId);
349 | } catch (ClientException e) {
350 | listener.getLogger().println("execute oos template error info:");
351 | listener.getLogger().println(e);
352 | }
353 | return executionId;
354 | }
355 |
356 | // ess resource execute oos Template : ESS_TEMPLATE_NAME
357 | private String essResourceExec(StartExecutionRequest request, IAcsClient oosClient, TaskListener listener) {
358 | request.setTemplateName(ESS_TEMPLATE_NAME);
359 | String parameter =
360 | "{\"invokeDestinationDir\":\"" +
361 | "" + this.step.destinationDir + "" +
362 | "\"," +
363 | "\"scalingGroupId\":\"" +
364 | "" + this.step.resourceId + "" +
365 | "\"," +
366 | "\"invokeScript\":\"" +
367 | this.step.invokeScript +
368 | "\"," +
369 | "\"OSSRegion\":\"" +
370 | "" + this.step.region + "" +
371 | "\"," +
372 | "\"batchPauseOption\":\"" +
373 | "" + this.step.pausePolicy + "" +
374 | "\"," +
375 | "\"whetherSaveToFile\":true," +
376 | "\"URLExpirationTime\":" +
377 | "6000" +
378 | "," +
379 | "\"batchNumber\":" +
380 | "" +
381 | this.step.batchNumber +
382 | "" +
383 | "," +
384 | "\"rollbackBucketName\":\"" +
385 | "" + this.step.bucket + "" +
386 | "\"," +
387 | "\"rollbackObjectName\":\"" +
388 | "" + this.step.objectName + "" +
389 | "\"," +
390 | "\"rollbackDestinationDir\":\"" +
391 | "" + this.step.destinationDir + "" +
392 | "\"," +
393 | "\"invokeBucketName\":\"" +
394 | "" + this.step.bucket + "" +
395 | "\"," +
396 | "\"invokeObjectName\":\"" +
397 | "" + this.step.objectName + "" +
398 | "\"," +
399 | "\"invokeType\":\"" +
400 | "" + "invoke" + "" +
401 | "\"}";
402 | request.setParameters(parameter);
403 | StartExecutionResponse response = null;
404 | String executionId = null;
405 | try {
406 | response = oosClient.getAcsResponse(request);
407 | executionId = response.getExecution().getExecutionId();
408 | listener.getLogger().println("you can login aliyun oos console to query oos template implementation progress:" + "https://oos.console.aliyun.com/" + this.step.region + "/execution/detail/" + executionId);
409 | } catch (ClientException e) {
410 | listener.getLogger().println("execute oos template error info:");
411 | listener.getLogger().println(e);
412 | }
413 | return executionId;
414 | }
415 |
416 | //compress directory of localPath and upload to OSS.
417 | private void zipAndUpload(OSS ossClient, String projectName, FilePath sourceDirectory, PrintStream logger) throws InterruptedException, IOException {
418 | File zipFile = null;
419 | File versionFile;
420 | versionFile = new File(sourceDirectory + "/");
421 | InputStreamReader reader = null;
422 | String version = null;
423 | try {
424 | reader = new InputStreamReader(new FileInputStream(versionFile), "UTF-8");
425 | char[] chars = new char[(int) versionFile.length() - 1];
426 | reader.read(chars);
427 | version = new String(chars);
428 | reader.close();
429 | } catch (IOException e) {
430 | e.printStackTrace();
431 | } finally {
432 | if (reader != null) {
433 | reader.close();
434 | }
435 | }
436 | if (version != null) {
437 | zipFile = new File("/tmp/" + projectName + "-" + version + ".zip");
438 | final boolean fileCreated = zipFile.createNewFile();
439 | if (!fileCreated) {
440 | logger.println("File already exists, overwriting: " + zipFile.getPath());
441 | }
442 | } else {
443 | zipFile = File.createTempFile(projectName + "-", ".zip");
444 | }
445 |
446 | FileOutputStream outputStream = new FileOutputStream(zipFile);
447 | try {
448 | sourceDirectory.zip(
449 | outputStream,
450 | new FileFilter() {
451 | @Override
452 | public boolean accept(File pathname) {
453 | return true;
454 | }
455 | }
456 | );
457 | } finally {
458 | outputStream.close();
459 | }
460 | String bucketName = this.step.bucket;
461 |
462 | try {
463 | InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, this.step.objectName);
464 | InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
465 | String uploadId = upresult.getUploadId();
466 | List partETags = new ArrayList();
467 | final long partSize = 1 * 1024 * 1024L;
468 | long fileLength = zipFile.length();
469 | int partCount = (int) (fileLength / partSize);
470 | if (fileLength % partSize != 0) {
471 | partCount++;
472 | }
473 | for (int i = 0; i < partCount; i++) {
474 | long startPos = i * partSize;
475 | long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
476 | InputStream instream = new FileInputStream(zipFile);
477 | instream.skip(startPos);
478 | UploadPartRequest uploadPartRequest = new UploadPartRequest();
479 | uploadPartRequest.setBucketName(bucketName);
480 | uploadPartRequest.setKey(this.step.objectName);
481 | uploadPartRequest.setUploadId(uploadId);
482 | uploadPartRequest.setInputStream(instream);
483 | uploadPartRequest.setPartSize(curPartSize);
484 | uploadPartRequest.setPartNumber(i + 1);
485 | UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
486 | partETags.add(uploadPartResult.getPartETag());
487 | }
488 | CompleteMultipartUploadRequest completeMultipartUploadRequest =
489 | new CompleteMultipartUploadRequest(bucketName, this.step.objectName, uploadId, partETags);
490 | CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
491 | logger.println(completeMultipartUploadResult.getETag());
492 | } catch (Exception e) {
493 | logger.println(e);
494 | } finally {
495 | final boolean deleted = zipFile.delete();
496 | if (!deleted) {
497 | logger.println("Failed to clean up file " + zipFile.getPath());
498 | }
499 | if (ossClient != null) {
500 | ossClient.shutdown();
501 | }
502 | }
503 | }
504 |
505 | private boolean isSubDirectory(FilePath parent, FilePath child) {
506 | FilePath parentFolder = child;
507 | while (parentFolder != null) {
508 | if (parent.equals(parentFolder)) {
509 | return true;
510 | }
511 | parentFolder = parentFolder.getParent();
512 | }
513 | return false;
514 | }
515 |
516 | public String getLocalPathFromEnv(Map envVars) {
517 | return Util.replaceMacro(this.step.localPath, envVars);
518 | }
519 | }
520 |
521 | }
522 |
--------------------------------------------------------------------------------