Devops-蓝鲸篇-05-蓝盾插件开发指引

news/2024/12/15 22:12:13/

写在前面

开发插件前,先进入插件工作台初始化一个插件,确定插件在平台中的唯一标识

工作台

可以在这里进行新增/发布/下架等管理插件的操作

功能区介绍

在这里插入图片描述

  1. 切换资源类型
  2. 新增插件
  3. 单个插件的管理入口
  4. 升级、下架、删除插件快捷入口
  5. 指引文档和插件 UI 调试工具入口

新增插件

在这里插入图片描述

  1. 标识
  • 插件在平台中的唯一标识,建议取和插件功能相关的可读性好的英文标识
  1. 调试项目
  • 插件发布过程中,可以在调试项目下将插件添加到流水线执行,对插件进行测试,保证插件功能满足预期。
  • 建议新增专用的插件调试项目,避免测试过程中影响到业务。
  1. 开发语言
  • 支持四种语言开发插件:
    • Java(推荐)
    • Python
    • Golang
    • Nodejs

开发插件

初始化好插件之后,可以开始开发插件

  • 根据开发语言参考对应的开发指引
    • Java 插件开发指引
    • Python 插件开发指引
    • Golang 插件开发指引
    • Nodejs 插件开发指引

插件私有配置

插件级别的敏感信息,如 token、用户名密码、IP、域名等,不建议直接提交到代码库,通过工作台私有配置界面管理

在这里插入图片描述

Golang 插件开发

插件开发框架说明

插件最终打包成一个命令行可执行的命令即可,对开发框架无硬性要求 下边以 demo 插件为例示范

示例插件代码工程的整体结构如下

|- <你的插件标识>|- cmd|- application|- main.go|- hello|- hello.go

如何开发插件:

参考 plugin-demo-golang

  • 创建插件代码工程
    • 插件代码建议企业下统一管理。 通用的开源插件可以联系蓝鲸官方放到 TencentBlueKing 下,供更多用户使用
  • 实现插件功能
  • 规范:
    • 插件开发规范
    • 插件配置规范
  • 插件前端不仅可以通过 task.json 进行标准化配置,也可以自定义开发:
    • 自定义插件 UI 交互指引
    • 插件输出规范
    • 插件错误码规范
    • 插件发布包规范

Demo示例研读

将 plugin-demo-golang clone到本地。
来看下项目结构:

.
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── go.sum
├── i18n
│   ├── message_en_US.properties
│   └── message_zh_CN.properties
├── main.go
├── task.json
└── translation└── translation.go3 directories, 11 files

咦!和上面说的插件代码工程的整体架构不一样:

|- <你的插件标识>|- cmd|- application|- main.go|- hello|- hello.go

不过,这不重要,只要插件最终能够打包成一个命令行可执行的命令即可。

这里i18n是实现中英文国际化使用的,

├── i18n
│   ├── message_en_US.properties
│   └── message_zh_CN.properties

看下内容对比:
message_en_US.properties:

input.desc.label=desc
100001=input param [{0}] invitated

message_zh_CN.properties

input.desc.label=描述
100001=输入参数[{0}]非法

那我们就可以猜测,这里是实现输入参数[{0}]非法这句话的中英文,其中[{0}]会使用具体的参数填充。

然后i18ngenerator则是根据properties文件的配置,生成translation代码,如translation.go:

// Code generated by "i18ngenerator"; DO NOT EDIT.package translation// Translations
var Translations map[string][][]string = make(map[string][][]string)func init() {Translations["en-US"] = [][]string{{"100001","input param [{0}] invitated",},{"input.desc.label","desc",},}Translations["zh-CN"] = [][]string{{"100001","输入参数[{0}]非法",},{"input.desc.label","描述",},}
}

该文件是由i18ngenerator自动生成的,不要自己改。

main函数内,实现了一个小的输出功能,简单看下源码,然后去进行测试:

package mainimport ("fmt""io/ioutil""os""runtime""time""github.com/ci-plugins/golang-plugin-sdk/api""github.com/ci-plugins/golang-plugin-sdk/log""github.com/ci-plugins/plugin-demo-golang/translation"
)//go:generate i18ngenerator i18n ./translation/translation.gotype greetingParam struct {UserName string `json:"userName"`Greeting string `json:"greeting"`
}func (a *greetingParam) String() string {return fmt.Sprintf("userName: %v, greeting: %v", a.UserName, a.Greeting)
}func main() {runtime.GOMAXPROCS(4)log.Info("atom-demo-glang starts")defer func() {if err := recover(); err != nil {log.Error("panic: ", err)api.FinishBuild(api.StatusError, "panic occurs")}}()api.InitI18n(translation.Translations, api.GetRuntimeLanguage())msg, err := api.Localize("input.desc.label")if err != nil {log.Error(err)}log.Info(msg)helloBuild()
}func helloBuild() {// 获取单个输入参数userName := api.GetInputParam("userName")log.Info("userName: ", userName)// 打屏log.Info("\nBuildInfo:")log.Info("Project Name:     ", api.GetProjectDisplayName())log.Info("Pipeline Id:      ", api.GetPipelineId())log.Info("Pipeline Name:    ", api.GetPipelineName())log.Info("Pipeline Version: ", api.GetPipelineVersion())log.Info("Build Id:         ", api.GetPipelineBuildId())log.Info("Build Num:        ", api.GetPipelineBuildNumber())log.Info("Start Type:       ", api.GetPipelineStartType())log.Info("Start UserId:     ", api.GetPipelineStartUserId())log.Info("Start UserName:   ", api.GetPipelineStartUserName())log.Info("Start Time:       ", api.GetPipelineStartTimeMills())log.Info("Workspace:        ", api.GetWorkspace())// 输入参数解析到对象paramData := new(greetingParam)api.LoadInputParam(paramData)log.Info(fmt.Sprintf("\n%v,%v\n", paramData.Greeting, paramData.UserName))// 业务逻辑log.Info("start build")build()time.Sleep(2 * time.Second)// 输出// 字符串输出strData := api.NewStringData("test")api.AddOutputData("strData_01", strData)// 文件归档输出artifactData := api.NewArtifactData()artifactData.AddArtifact("result.dat")api.AddOutputData("artifactData_02", artifactData)// 报告输出reportData := api.NewReportData("label_01", api.GetWorkspace()+"/report", "report.htm")api.AddOutputData("report_01", reportData)api.WriteOutput()log.Info("build done")
}func build() {log.Info("write result.dat")ioutil.WriteFile(api.GetWorkspace()+"/result.dat", []byte("content"), 0644)log.Info("write report.htm")os.Mkdir(api.GetWorkspace()+"/report", os.ModePerm)ioutil.WriteFile(api.GetWorkspace()+"/report/report.htm", []byte("<html><head><title>Report</title></head><body><H1>This is a Report</H1></body></html>"), 0644)
}

在根目录下已经给我们预设了一个task.json文件,后面可以简单修改下这个文件来实现测试:

{"atomCode": "goDemo","execution": {"language": "golang","packagePath": "goDemo","demands": ["chmod +x goDemo"],"target": "./goDemo"},"input": {"greeting": {"label": "欢迎词","default": "Glad to see you","placeholder": "欢迎词","type": "vuex-input","desc": "欢迎词","required": true,"disabled": false,"hidden": false,"isSensitive": false},"userName": {"label": "姓名","default": "Mr. Huang","placeholder": "姓名","type": "vuex-input","desc": "姓名","required": true,"disabled": false,"hidden": false,"isSensitive": false}},"output": {"strData_01": {"description": "测试","type": "string","isSensitive": false}}
}

如何打包发布

1、进入插件代码工程目录下
2、打包
2.1、如果按照正常的demo的目录结构是需要进入cmd/application内执行build命令,因为main在此

cd cmd/application
GO111MODULE=on GOOS=linux GOARCH=amd64 go build -o bin/${executable}

2.2、这次用的demo则直接在根目录下执行build命令,因为main在根目录下

GO111MODULE=on GOOS=linux GOARCH=amd64 go build -o bin/${executable}

这里go build -o bin/ e x e c u t a b l e 会在 b i n 目录下,生成可执行文件,文件名是 {executable}会在bin目录下,生成可执行文件,文件名是 executable会在bin目录下,生成可执行文件,文件名是{executable},即项目名。

也可以自定义一个名字,如GO111MODULE=on GOOS=linux GOARCH=amd64 go build -o bin/kingtest

  1. 在任意位置新建文件夹,命名示例:release_pkg = <你的插件标识>_release
  2. 将步骤 2 生产的执行包拷贝到 <release_pkg> 下
  3. 添加 task.json 文件到 <release_pkg> 下 task.json 见示例,按照插件功能配置。
mkdir kingtest_release
cp bin/kingtest kingtest_release/kingtest
touch kingtest_release/task.json

插件配置规范: 插件配置规范
task.json 示例:

{"atomCode": "king-test",                  # atomCode 要与工作台录入的一致"execution": {"language": "golang","packagePath": "kingtest",              # 发布包中插件安装包的相对路径"demands": ["echo start run chmod +x kingtest",   # 插件启动前需要执行的安装命令,顺序执行"chmod +x kingtest",                  # 插件启动前需要执行的安装命令,顺序执行"echo stop run chmod +x kingtest",    # 插件启动前需要执行的安装命令,顺序执行],"target": "./kingtest"},"input": {"greeting": {"label": "欢迎词","default": "Glad to see you","placeholder": "欢迎词","type": "vuex-input","desc": "欢迎词","required": true,"disabled": false,"hidden": false,"isSensitive": false},"userName": {"label": "姓名","default": "Mr. Huang","placeholder": "姓名","type": "vuex-input","desc": "姓名","required": true,"disabled": false,"hidden": false,"isSensitive": false}},"output": {"strData_01": {"description": "测试","type": "string","isSensitive": false}}
}
  1. 在 <release_pkg> 目录下,把所有文件打成 zip 包即可
cd kingtest_release && zip kingtest_release.zip kingtest task.json

zip包结构示例:

|- kingtest_release.zip         # 发布包|- kingtest                  # 插件执行包|- task.json                 # 插件配置文件

打包完成后,在插件工作台提单发布,即可测试或发布插件

上传一个流水线插件

开发好插件之后,通过研发商店工作台,将插件发布到研发商店,提供给用户添加到流水线中使用。

入口

在工作台列表,点击如下入口发起发布流程:
在这里插入图片描述
首次发布时,入口名为上架
后续更新版本时,入口名为升级

或者在插件发布管理->版本管理界面发起发布流程:
在这里插入图片描述

填写插件相关信息/上传插件发布包

上架/升级插件时,可以修改插件的基本信息,如下所示:
在这里插入图片描述

  1. 适用 Job 类型:
  • 和流水线 Job 类型对应,请按照插件实际适用情况选择
  • 若选错,需新增版本修改
  1. 发布包:
  • task.json 中的 atomCode 需和 新增插件时填写的标识一致,否则上传会失败

测试/发布插件

填写好信息,提交后,进入发布流程,可以测试->重新传包->测试,直至插件满足预期后,手动继续流程将插件发布到研发商店

在这里插入图片描述

  1. 测试:点击后跳转到插件调试项目的流水线服务下,可以将当前插件添加到流水线,验证 UI、功能是否满足预期
  2. 重新传包:当测试发现问题,修复后,重新上传发布包,再次进行测试
  3. 继续:测试 OK,满足预期后,确认提交发布
  4. 取消发布:发布过程中,随时可以终止发布

遇见的几个错误

无权限执行

在测试中遇见一个问题:无权限执行
在这里插入图片描述
execution->demands增加一个命令chmod +x kingtest即可解决

发布进度里重新传包持续报错task.json格式错误

还有个问题,在发布进度里重新传包时,一直报错task.json格式错误,但实际格式是对的!
触发的原因暂不知道,但是确实是一个隐藏的bug。

在这里插入图片描述
直接点击继续,然后走升级插件的方式可以正常使用。

cannot execute binary file: Exec format error

这里的问题是我造成的,最初我在mac环境下编译的可执行文件,命令是:

# mac下执行
go build -o bin/kingtest

但是插件里选择的编译环境是linux。
在这里插入图片描述
解决方式:让插件选择的编译环境和可执行文件的平台统一。

我这里选择重新编译下可执行文件,采用在mac平台交叉编译linux平台可执行文件的方式。

GO111MODULE=on GOOS=linux GOARCH=amd64 go build -o bin/kingtest

也可以新建一个插件,编译环境选择mac。

运行结果

流水线结果:
在这里插入图片描述
输出结果:

[Plugin info]
=====================================================================
Task           : king-test
Description    : bk插件测试
Version        : 1.0.3
Author         : huari
Help           : More Information
=====================================================================
-----
[Input]
input(normal): (欢迎词)greeting=Glad to see you
input(normal): (姓名)userName=Mr. Huang
-----
[Install plugin]
-----
start run chmod +x kingtest
stop run chmod +x kingtest
atom-demo-glang starts
描述
userName:  Mr. HuangBuildInfo:
Project Name:      GOPS
Pipeline Id:       p-8967ed52b08847c8a5b0140937db0975
Pipeline Name:     king-test
Pipeline Version:  11
Build Id:          b-78947b5c39f34b32bbafb803042d1e22
Build Num:         15
Start Type:        MANUAL
Start UserId:      huari
Start UserName:    huari
Start Time:        1733298107286
Workspace:         /data/devops/workspaceGlad to see you,Mr. Huang
start build
write result.dat
write report.htm
build done
[Output]
1 file match: /data/devops/workspace/result.dat
prepare to upload 7 B
1/1 file(s) finished
output(except): artifactData_02=result.dat
入口文件检测完成
上传自定义产出物成功,共产生了1个文件
output(except): report_01=report.htm
output(normal): strData_01=test
-----

http://www.ppmy.cn/news/1555425.html

相关文章

一键学懂BurpSuite(8)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

基于SpringBoot和PostGIS的全球城市信息管理实践

目录 前言 一、业务需求介绍 1、功能思维导图 二、业务系统后台实现 1、Model层实现 2、业务层的实现 3、控制层的实现 三、前端管理业务的实现 1、全球城市列表的实现 2、详情页面实现 3、实际城市定位 四、总结 前言 在全球化和信息化时代背景下&#xff0c;城市作…

记录一次golang中关于值传递和引用传递,内存逃逸的学习笔记

起因:最近在翻看代码时,发现有的同时在使用golang gorm库查询单条数据时,和官方文档中有点区别: 同事的代码大致长这样: // 依据商品id查询商品详情 func (m GoodsModel) FindOneById(id uint32, field string) (*Goods, error) {info : &Goods{}db : mysqldriver.GetDB(…

Flink是什么?Flink技术介绍

官方参考资料&#xff1a;Apache Flink — Stateful Computations over Data Streams | Apache Flink Flink是一个分布式流处理和批处理计算框架&#xff0c;具有高性能、容错性和灵活性。以下是关于Flink技术的详细介绍&#xff1a; 一、Flink概述 ‌定义‌&#xff1a;Fli…

MongoDB 分片

MongoDB 分片 MongoDB 分片是一种数据库架构&#xff0c;用于将大量数据分布存储在多个服务器上。这种设计允许数据库扩展&#xff0c;以处理大量数据和高吞吐量操作。分片通过将数据集分割成小块&#xff0c;称为分片&#xff0c;并将这些分片分布到多个服务器上来工作。每个…

Python列表与字典的性能比较:如何选择最适合的数据结构

在Python中&#xff0c;列表&#xff08;List&#xff09;和字典&#xff08;Dictionary&#xff09;是最常用的数据结构之一。它们都能够有效地存储数据&#xff0c;并提供高效的操作方式&#xff0c;但它们在内部实现、操作复杂度以及应用场景上存在显著的差异。在进行程序设…

docker开启远程访问

1、编辑docker.server文件 vi /usr/lib/systemd/system/docker.service 找到 [Service] 节点&#xff0c;修改 ExecStart 属性&#xff0c;增加 -H tcp://0.0.0.0:2375 ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock -H tcp://0.0.0.0:2…

微信小程序5-图片实现点击动作和动态加载同类数据

搜索 微信小程序 “动物觅踪” 观看效果 感谢阅读&#xff0c;初学小白&#xff0c;有错指正。 一、功能描述 a. 原本想通过按钮加载背景图片&#xff0c;来实现一个可以点击的搜索button&#xff0c;但是遇到两个难点&#xff0c;一是按钮大小调整不方便&#xff08;网上搜索…