Skip to content

Commit

Permalink
add http action support
Browse files Browse the repository at this point in the history
  • Loading branch information
mylxsw committed Dec 2, 2020
1 parent 74996f2 commit 16c347e
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 30 deletions.
3 changes: 2 additions & 1 deletion dashboard/src/plugins/editor-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@ let helpers = {
{text: 'CutoffLine(STR, MAX)', displayText: 'CutoffLine(val string, maxLine int) string | 字符串截取 maxLine 行'},
],
templates: [
{text: '.Events EVENT_COUNT', displayText: 'Events(limit int64) []repository.Message | 从事件组中获取 EVENT_COUNT 个 Events'},
{text: '.Events EVENT_COUNT', displayText: 'Events(limit int64) []repository.Event | 从事件组中获取 EVENT_COUNT 个 Events'},
{text: ".IsRecovery", displayText: "IsRecovery() bool | 判断当前事件组中的事件是否是恢复事件"},
{text: ".IsRecoverable", displayText: "IsRecoverable() bool | 判断当前事件组中的事件是否可恢复"},
{text: ".IsPlain", displayText: "IsPlain() bool | 判断当前事件组中的事件是否是普通事件"},
{text: ".EventType", displayText: "EventType() string | 判断当前事件组中的事件类型:recovery/plain/recoverable"},
{text: ".FirstEvent", displayText: "FirstEvent() repository.Event | 从当前事件组中获取第一个事件"},
{text: '{{ }}', displayText: '{{ }} | Golang 代码块'},
{text: '{{ range $i, $msg := ARRAY }}\n {{ $i }} {{ $msg }} \n{{ end }}', displayText: '{{ range }} | Golang 遍历对象'},
{text: '{{ range $i, $msg := .Messages 4 }} {{ end }}', displayText: '{{ range $i, $msg := .Messages 4 }} {{ end }} | Golang 遍历 Messages,只取 4 条作为摘要'},
Expand Down
107 changes: 90 additions & 17 deletions dashboard/src/views/RuleEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,43 @@
<TemplateHelp v-if="trigger.template_help" :helpers="helper.dingdingTemplateRules"/>
</b-form-group>
</div>
<div v-else-if="trigger.action === 'http'" class="adanos-sub-form">
<b-form-group label-cols="2" :id="'trigger_meta_method_' + i" label="请求方式" :label-for="'trigger_meta_method_' + i">
<b-form-select :id="'trigger_meta_method_' + i" v-model="trigger.meta_arr.method" placeholder="请求方式" :options="['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'PURGE']"/>
</b-form-group>
<b-form-group label-cols="2" :id="'trigger_meta_url_' + i" label="URL" :label-for="'trigger_meta_url_' + i">
<b-form-input :id="'trigger_meta_url_' + i" v-model="trigger.meta_arr.url" placeholder="URL"/>
</b-form-group>
<b-form-group label-cols="2" label="请求头" :label-for="'trigger_headers_' + i">
<b-btn variant="info" class="mb-3" @click="httpHeaderAdd(i)">添加字段</b-btn>
<b-input-group v-bind:key="index" v-for="(cf, index) in trigger.meta_arr.headers" class="mb-3">
<b-form-input v-model="trigger.meta_arr.headers[index].key" placeholder="字段名"></b-form-input>
<b-form-input v-model="trigger.meta_arr.headers[index].value" placeholder="字段值"></b-form-input>
<b-input-group-append>
<b-btn variant="danger" @click="httpHeaderDelete(i, index)">删除</b-btn>
</b-input-group-append>
</b-input-group>
</b-form-group>
<b-form-group label-cols="2" :id="'trigger_meta_template_' + i" label="请求体" :label-for="'trigger_meta_template_' + i">
<b-btn-group class="mb-2" v-if="!trigger.template_fold">
<b-btn variant="warning" @click="openDingdingTemplateSelector(i)">插入模板</b-btn>
<b-btn variant="dark" @click="trigger.template_help = !trigger.template_help">帮助</b-btn>
</b-btn-group>
<span class="text-muted" style="line-height: 2.5" v-if="trigger.template_fold">编辑区域已折叠,编辑请点 <b>展开</b> 按钮</span>

<b-btn-group class="mb-2 float-right">
<b-btn variant="primary" class="float-right" @click="checkTemplate(trigger.meta_arr.template)">检查</b-btn>
<b-btn variant="info" class="float-right" @click="trigger.template_fold = !trigger.template_fold">{{ trigger.template_fold ? '展开' : '收起' }}</b-btn>
</b-btn-group>
</b-form-group>
<b-form-group v-if="!trigger.template_fold">
<codemirror v-model="trigger.meta_arr.template" class="mt-3 adanos-code-textarea" :options="options.ding_template"></codemirror>
<small class="form-text text-muted">
语法提示 <code>Alt+/</code>,语法参考 <a href="https://golang.org/pkg/text/template/" target="_blank">https://golang.org/pkg/text/template/</a>
</small>
<TemplateHelp v-if="trigger.template_help" :helpers="helper.dingdingTemplateRules"/>
</b-form-group>
</div>
<div v-else-if="trigger.action === 'phone_call_aliyun'" class="adanos-sub-form">
<b-form-group label-cols="2" :id="'trigger_meta_content_' + i" label="通知标题" :label-for="'trigger_meta_content_' + i">
<b-form-textarea :id="'trigger_meta_content_' + i" class="adanos-code-textarea text-monospace" v-model="trigger.meta_arr.title" placeholder="通知标题,默认为规则名称"/>
Expand Down Expand Up @@ -523,9 +560,8 @@ export default {
action_options: [
{value: 'dingding', text: '钉钉'},
{value: 'phone_call_aliyun', text: '阿里云语音通知'},
{value: 'jira', text: 'Jira'},
// {value: 'http', text: 'HTTP'},
{value: 'jira', text: 'JIRA'},
{value: 'http', text: 'HTTP'},
// {value: 'email', text: '邮件'},
// {value: 'wechat', text: '微信'},
// {value: 'sms_aliyun', text: '阿里云短信'},
Expand Down Expand Up @@ -788,6 +824,18 @@ export default {
customFieldDelete(triggerIndex, index) {
this.form.triggers[triggerIndex].meta_arr.custom_fields.splice(index, 1);
},
/**
* 添加请求头
*/
httpHeaderAdd(triggerIndex) {
this.form.triggers[triggerIndex].meta_arr.headers.push({key: '', value: ''});
},
/**
* 删除请求头
*/
httpHeaderDelete(triggerIndex, index) {
this.form.triggers[triggerIndex].meta_arr.headers.splice(index, 1);
},
/**
* 为动作添加用户
*/
Expand All @@ -813,24 +861,33 @@ export default {
meta: '',
issue_type_options: [],
priority_options: [],
meta_arr: {
template: '',
robot_id: null,
title: '{{ .Rule.Title }}',
project_key: '',
summary: '{{ .Rule.Title }}',
issueType: '',
priority: '',
assignee: '',
custom_fields: []
},
meta_arr: this.createTriggerMeta(),
id: '',
user_refs: [],
help: false,
template_help: false,
template_fold: true,
});
},
/**
* 创建 Trigger Meta
*/
createTriggerMeta() {
return {
template: '',
robot_id: null,
title: '{{ .Rule.Title }}',
project_key: '',
summary: '{{ .Rule.Title }}',
issueType: '',
priority: '',
assignee: '',
custom_fields: [],
method: 'POST',
url: '',
headers: [],
};
},
/**
* 删除动作
* @param index
Expand Down Expand Up @@ -959,6 +1016,15 @@ export default {
trigger.user_refs = trigger.meta_arr.assignee !== '' ? [trigger.meta_arr.assignee] : null;
break;
}
case 'http': {
trigger.meta = JSON.stringify({
method: trigger.meta_arr.method,
url: trigger.meta_arr.url,
headers: trigger.meta_arr.headers,
body: trigger.meta_arr.template,
});
break;
}
default: {
trigger.meta = JSON.stringify(trigger.meta_arr);
}
Expand Down Expand Up @@ -1024,7 +1090,9 @@ export default {
let trigger = response.data.triggers[i];
trigger.help = false;
trigger.template_help = false;
trigger.meta_arr = {};
// 注意:这里的所有字段都必须要有,否则更新值后 UI 不会同步更新
trigger.meta_arr = this.createTriggerMeta();
trigger.priority_options = [];
trigger.issue_type_options = [];
Expand All @@ -1034,7 +1102,7 @@ export default {
let parsedMeta = JSON.parse(trigger.meta);
switch (trigger.action) {
case 'jira':{
trigger.meta_arr = parsedMeta['issue'];
trigger.meta_arr = Object.assign(trigger.meta_arr, parsedMeta['issue']);
trigger.meta_arr.template = trigger.meta_arr.description;
trigger.meta_arr.assignee = (trigger.user_refs != null && trigger.user_refs.length > 0) ? trigger.user_refs[0] : '';
let customFields = [];
Expand All @@ -1047,8 +1115,13 @@ export default {
triggerJiraLoaders.push(i);
break;
}
case 'http': {
trigger.meta_arr = Object.assign(trigger.meta_arr, parsedMeta);
trigger.meta_arr.template = parsedMeta.body;
break;
}
default: {
trigger.meta_arr = parsedMeta;
trigger.meta_arr = Object.assign(trigger.meta_arr, parsedMeta);
}
}
} catch (e) {
Expand Down
17 changes: 17 additions & 0 deletions internal/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive"
)

// Action 触发动作接口
type Action interface {
Validate(meta string, userRefs []string) error
Handle(rule repository.Rule, trigger repository.Trigger, grp repository.EventGroup) error
}

// Manager 动作管理器接口
type Manager interface {
Resolve(f interface{}) error
MustResolve(f interface{})
Expand All @@ -38,6 +40,7 @@ type actionManager struct {
actions map[string]Action
}

// NewManager create a new Manager
func NewManager(cc container.Container) Manager {
return &actionManager{cc: cc, actions: make(map[string]Action)}
}
Expand Down Expand Up @@ -78,16 +81,21 @@ func (manager *actionManager) Register(name string, action Action) {
manager.actions[name] = action
}

// QueueAction 动作队列
type QueueAction struct {
action string
manager Manager
}

// Validate 校验动作参数
func (q *QueueAction) Validate(meta string, userRefs []string) error {
return q.manager.Run(q.action).Validate(meta, userRefs)
}

// EventQuerier 事件查询接口
type EventQuerier func(groupID primitive.ObjectID, limit int64) []repository.Event

// Payload 事件描述生成时使用的对象,用于模板解析
type Payload struct {
eventQuerier EventQuerier
Action string `json:"action"`
Expand Down Expand Up @@ -141,6 +149,12 @@ func (payload *Payload) Events(limit int64) []repository.Event {
return payload.eventQuerier(payload.Group.ID, limit)
}

// FirstEvent get first event
func (payload *Payload) FirstEvent() repository.Event {
return payload.Events(1)[0]
}

// CreateRepositoryEventQuerier 创建仓库事件查询器
func CreateRepositoryEventQuerier(msgRepo repository.EventRepo) func(groupID primitive.ObjectID, limit int64) []repository.Event {
return func(groupID primitive.ObjectID, limit int64) []repository.Event {
messages, _, err := msgRepo.Paginate(bson.M{"group_ids": groupID}, 0, limit)
Expand All @@ -156,15 +170,18 @@ func CreateRepositoryEventQuerier(msgRepo repository.EventRepo) func(groupID pri
}
}

// Encode 将 Payload 编码
func (payload *Payload) Encode() []byte {
data, _ := json.Marshal(payload)
return data
}

// Decode 从字符串解析出 Payload 对象
func (payload *Payload) Decode(data []byte) error {
return json.Unmarshal(data, payload)
}

// Handle 动作处理
func (q *QueueAction) Handle(rule repository.Rule, trigger repository.Trigger, grp repository.EventGroup) error {
return q.manager.Resolve(func(queueManager queue.Manager, em event.Manager) error {
payload := Payload{
Expand Down
5 changes: 5 additions & 0 deletions internal/action/dingding.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive"
)

// DingdingAction 钉钉发送动作
type DingdingAction struct {
manager Manager
userRepo repository.UserRepo
}

// DingdingMeta 钉钉发送元数据
type DingdingMeta struct {
Template string `json:"template"`
RobotID string `json:"robot_id"`
}

// Validate 校验动作参数
func (d DingdingAction) Validate(meta string, userRefs []string) error {
var dingdingMeta DingdingMeta
if err := json.Unmarshal([]byte(meta), &dingdingMeta); err != nil {
Expand All @@ -38,6 +41,7 @@ func (d DingdingAction) Validate(meta string, userRefs []string) error {
return nil
}

// NewDingdingAction create a new dingdingAction
func NewDingdingAction(manager Manager) *DingdingAction {
dingdingAction := DingdingAction{manager: manager}
manager.MustResolve(func(userRepo repository.UserRepo) {
Expand All @@ -46,6 +50,7 @@ func NewDingdingAction(manager Manager) *DingdingAction {
return &dingdingAction
}

// Handle 钉钉动作处理
func (d DingdingAction) Handle(rule repository.Rule, trigger repository.Trigger, grp repository.EventGroup) error {

var meta DingdingMeta
Expand Down
Loading

0 comments on commit 16c347e

Please sign in to comment.