额, 我感觉我还是很努力的在写文章了。 基本上平均 2 个礼拜更新一次
用一段我写故障注入的注释来说明一下吧。
基本上就是 jenkins 也是用 exec 这个方式来像容器发送命令的,基本上是读取不到你定义的环境变量的。 这个问题我至今还没有找到原因。 所以你还是用 jenkins pipeline 中的环境变量语法,来搞这些事把
我是用 xml 哈哈哈, 这玩意随意了, 想用啥用啥
恩 很强, 我们测接口都用这玩意
你也可以用这个, 只不过你要测试什么版本就搭建什么虚拟机 + 浏览器。 然后注册到 grid hub 上就好了
尽量不要拿 docker 做兼容性测试, 它用的毕竟是 linux 内核。 用户是不会用 linux 系统访问你们的产品的。
kubectl 的命令不是这么用的~~~ kubectl exec -it podname bash 这个命令是使用 tty 打开了容器的 bash shell 窗口。 脚本不是你在 shell 里做命令交互~~ exec 是让容器执行命令的, 所以你直接用 kubectl exec podname 你要执行的命令 就行了
就 nfs 就行了吧
java 界 无可争议的 接口测试工具: rest-assured
只做过 web 端的, 就是用 grid 做
效果图如下:
这个很简单啊, allure 在 jenkins 上的插件也是用 allure command line 启动的一个服务。 暴露了 http 接口。 你可以从中获取测试结果的。我是写了一段 groovy 脚本来抓取 allure report 的结果的。 可以使用 pipeline 来 执行 groovy 脚本,你也可以在其他 job 中添加 groovy script 这个步骤。 你可以参考我这里的脚本。代码如下:
/**
* Created by sungaofei on 20/2/8.
*/
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import groovy.transform.Field
//global variable
@Field jenkinsURL = "http://auto.4paradigm.com"
@Field failed = "FAILED"
@Field success = "SUCCESS"
@Field inProgress = "IN_PROGRESS"
@Field abort = "ABORTED"
@NonCPS
def String checkJobStatus() {
def url = ""
if (env.BRANCH_NAME!= "" && env.BRANCH_NAME != null){
String jobName = "${JOB_NAME}".split("/")[0]
url = "/view/API/job/${jobName}/job/${env.BRANCH_NAME}/${BUILD_NUMBER}/wfapi/describe"
}else {
url = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/wfapi/describe"
}
HTTPBuilder http = new HTTPBuilder(jenkinsURL)
String status = success
println("1111111111")
println("${JOB_NAME}")
println(url)
http.get(path: url) { resp, json ->
if (resp.status != 200) {
throw new RuntimeException("请求 ${url} 返回 ${resp.status} ")
}
List stages = json.stages
for (int i = 0; i < stages.size(); i++) {
def stageStatus = json.stages[i].status
if (stageStatus == failed) {
status = failed
break
}
if (stageStatus == abort) {
status = abort
break
}
}
}
return status;
}
@NonCPS
def call(String to) {
println("邮件列表:${to}")
def reportURL = ""
String jobName = "${JOB_NAME}"
String blueOCeanURL = ""
if (env.BRANCH_NAME!= "" && env.BRANCH_NAME != null){
jobName = "${JOB_NAME}".split("/")[0]
reportURL = "/view/API/job/${jobName}/job/${env.BRANCH_NAME}/${BUILD_NUMBER}/allure/"
// http://auto.4paradigm.com/blue/organizations/jenkins/gitlabtest/detail/master/217/pipeline
blueOCeanURL = "${jenkinsURL}/blue/organizations/jenkins/${jobName}/detail/${env.BRANCH_NAME}/${BUILD_NUMBER}/pipeline"
}else{
reportURL = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/allure/"
blueOCeanURL = "${jenkinsURL}/blue/organizations/jenkins/${JOB_NAME}/detail/${JOB_NAME}/${BUILD_NUMBER}/pipeline"
}
def sendSuccess = {
// blueOCeanURL = "${jenkinsURL}/blue/organizations/jenkins/${JOB_NAME}/detail/${JOB_NAME}/${BUILD_NUMBER}/pipeline"
def fileContents = ""
def passed = ""
def failed = ""
def skipped = ""
def broken = ""
def unknown = ""
def total = ""
HTTPBuilder http = new HTTPBuilder('http://auto.4paradigm.com')
//根据responsedata中的Content-Type header,调用json解析器处理responsedata
http.get(path: "${reportURL}widgets/summary.json") { resp, json ->
println resp.status
passed = json.statistic.passed
failed = json.statistic.failed
skipped = json.statistic.skipped
broken = json.statistic.broken
unknown = json.statistic.unknown
total = json.statistic.total
}
println(passed)
emailext body: """
<html>
<style type="text/css">
<!--
${fileContents}
-->
</style>
<body>
<div id="content">
<h1>Summary</h1>
<div id="sum2">
<h2>Jenkins Build</h2>
<ul>
<li>Job 地址 : <a href='${BUILD_URL}'>${BUILD_URL}</a></li>
<li>测试报告地址 : <a href='${jenkinsURL}${reportURL}'>${jenkinsURL}${reportURL}</a></li>
<li>Pipeline 流程地址 : <a href='${blueOCeanURL}'>${blueOCeanURL}</a></li>
</ul>
<h2>测试结果汇总</h2>
<ul>
<li>用例总数 : ${total}</li>
<li>pass数量 : ${passed}</li>
<li>failed数量 :${failed} </li>
<li>skip数量 : ${skipped}</li>
<li>broken数量 : ${broken}</li>
</ul>
</div>
</div></body></html>
""", mimeType: 'text/html', subject: "${JOB_NAME} 测试结束", to: to
}
def send = { String subject ->
emailext body: """
<html>
<style type="text/css">
<!--
-->
</style>
<body>
<div id="sum2">
<h2>Jenkins Build</h2>
<ul>
<li>Job 地址 : <a href='${BUILD_URL}'>${BUILD_URL}</a></li>
<li>测试报告地址 : <a href='${jenkinsURL}${reportURL}'>${jenkinsURL}${reportURL}</a></li>
<li>Pipeline 流程地址 : <a href='${blueOCeanURL}'>${blueOCeanURL}</a></li>
</ul>
</div>
</div></body></html>
""", mimeType: 'text/html', subject: subject, to: to
}
String status = checkJobStatus()
// String status = $BUILD_STATUS
println("当前job 的运行状态为: ${status}")
switch (status) {
case ["SUCCESS", "UNSTABLE"]:
sendSuccess()
break
case "FAILED":
send("Job运行失败")
break
case "ABORTED":
send("Job在运行中被取消")
break
default:
send("Job运行结束")
}
}
不要在 jnlp 容器里用 cat 命令~~~ 加 cat 命令的目的是让其他容器能一直持续运行~~ jnlp 是 slave 容器, 不用加
我们很无脑的用的 nfs 哈哈哈哈。 ceph 现在没在用了。 因为我们没那么高的性能要求
额, 6 楼是我, 楼主可以去翻我写的 spark 的帖子。 刚才忘了解除匿名了
部署的时候配置域名跟 ingress 集成起来是这样的。 首先需要到你们的 dns 中添加一个泛域名解析。 解析地址填写你 ingress controller 的地址。 比如我们做的凡是以 testenv.4pd.io 为结尾的域名全部解析成我们 ingress controller 的 ip 地址。 然后为每一个环境创建一个 ingress 规则。 比如我们曾经做的:
def create_ingress_yaml(config):
document = """
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: %s
annotations:
nginx/client_max_body_size: 10240m
nginx.org/client-max-body-size: "10240m"
ingress.kubernetes.io/proxy-body-size: 10240m
spec:
rules:
- host: %s.testenv.4pd.io
http:
paths:
- path: /
backend:
serviceName: %s
servicePort: 8888
- host: %s.preditor.testenv.4pd.io
http:
paths:
- path: /
backend:
serviceName: %s
servicePort: 8090
- host: %s.history.testenv.4pd.io
http:
paths:
- path: /
backend:
serviceName: %s
servicePort: 18080
""" % (config.pht_pod_name, config.name_prefix, config.pht_pod_name, config.name_prefix, config.pht_pod_name,
config.name_prefix, config.pht_pod_name)
data = yaml.load_all(document)
with open(config.ingress_conf_path, 'w') as stream:
yaml.dump_all(data, stream)
在部署环境的时候就把 ingress 创建好。 然后配合泛域名解析,ingress controller 会自动的帮我们转发请求到具体的环境上。 就可以达到每个环境都自动的有一个域名对应上了。
部署其实很简单, 就像我上面做的那样就好。 维护一套 yaml 模板动态的去生成部署这些模块的 k8s 配置就可以了。
go 就直接用 vendor 吧, 直接在项目里把依赖打成 vendor 就好了。 不要用 go mod 下载或去 worksapce 里找依赖。
后续如何跟 ingress 集成起来是这样的。 首先需要到你们的 dns 中添加一个泛域名解析。 解析地址填写你 ingress controller 的地址。 比如我们做的凡是以 testenv.4pd.io 为结尾的域名全部解析成我们 ingress controller 的 ip 地址。 然后为每一个环境创建一个 ingress。 比如我们曾经做的:
def create_ingress_yaml(config):
document = """
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: %s
annotations:
nginx/client_max_body_size: 10240m
nginx.org/client-max-body-size: "10240m"
ingress.kubernetes.io/proxy-body-size: 10240m
spec:
rules:
- host: %s.testenv.4pd.io
http:
paths:
- path: /
backend:
serviceName: %s
servicePort: 8888
- host: %s.preditor.testenv.4pd.io
http:
paths:
- path: /
backend:
serviceName: %s
servicePort: 8090
- host: %s.history.testenv.4pd.io
http:
paths:
- path: /
backend:
serviceName: %s
servicePort: 18080
""" % (config.pht_pod_name, config.name_prefix, config.pht_pod_name, config.name_prefix, config.pht_pod_name,
config.name_prefix, config.pht_pod_name)
data = yaml.load_all(document)
with open(config.ingress_conf_path, 'w') as stream:
yaml.dump_all(data, stream)
在部署环境的时候就把 ingress 创建好。 然后配合泛域名解析, 就可以达到每个环境都自动的有一个域名对应上了。
不过我们之前使用搭建一个 ceph, 然后在 k8s 启动 pod 的时候, 把 maven 的本地缓存仓库挂载出来, 放到 ceph 里来解决动态依赖的问题。 但是我 python 很渣, 还不知道 pip 安装的依赖怎么挂载出来
你这两个问题其实我也还没解决~~~ 好在我们对时间的要求不大
单 slave 最大的缺陷就是没有高可用能力, 出现单点故障以后整个流程就会不可用的。
我们测 IE 浏览器的时候也没办法, 老老实实在 windows 上部署~
希望对你有帮助哈~
allure 这种这么好用的 report 框架~~~~ 大家用起来啊