目錄
1 本地啟動cmdb
2 cmdb數據庫表設計
3 代碼模塊介紹
4 功能介紹
5 請求調用流程
6 新增接口
7 cmdb如何操作mongo數據庫
一 本地啟動cmdb
服務器啟動回顧
部署cmdb的時候,輸入./start.sh 就可以啟動12個服務,那么針對這12個服務進行分析一下。首先看一下啟動后輸出的內容:
這里的配置參數,是根據運行的配置腳本所生成的,如:
生成配置文件位置:
configcenter/src/bin/build/3.2.17/cmdb_adminserver/configures/*
二 打開cmdb項目,把上一步cmdb_adminserver/configures/下生成的所有配置文件覆蓋到configcenter/resources/configures/目錄中 (即替換配置文件)。
然后修改configcenter/resources/configures/migrate.conf文件
三、本地啟動項目
cmdb是微服務框架,把平台拆分成了12個服務,本次我們啟動hostServer服務,其他服務啟動類似。
啟動hostServer的main方法(host.go文件):
啟動的的時候配置參數:Program arguments
例如:
--addrport=127.0.0.1:60001 --logtostderr=false --log-dir=./logs --v=3 --regdiscv=127.0.0.1:2181
每個服務啟動時 Program arguments 參數不同 可參考服務啟動時顯示的參數進行配置
二 cmdb數據庫表設計
表名 |
關聯業務 |
接口 |
備注 |
cc_ApplicationBase |
基礎資源-業務信息存儲 |
|
|
cc_AsstDes |
模型管理-關聯類型數據存儲 |
|
|
cc_History |
- |
|
|
cc_HostBase |
基礎資源-主機數據存儲 |
|
|
cc_HostFavourite |
- |
|
|
cc_idgenerator |
生成ID的,記錄每種記錄最大的ID,類似mysql 主鍵的auto_increment |
|
|
cc_InsAsst |
- |
|
|
cc_ModuleBase |
業務資源-業務拓撲中的葉子節點數據 |
|
|
cc_ModuleHostConfig |
主機分配到具體業務模塊表,bk_module_id是cc_ModuleBase.bk_module_id |
|
|
cc_Netcollect_Device |
- |
|
|
cc_Netcollect_Property |
- |
|
|
cc_ObjAsst |
模型與模型之間的關聯關系,見模型管理-模型拓撲 |
|
|
cc_ObjAttDes |
模型的所有字段 |
|
|
cc_ObjClassification |
存儲模型分組數據,針對模型管理-新建分組業務 |
|
|
cc_ObjDes |
存儲模型數據,針對模型管理-模型-新建模型業務 |
|
|
cc_ObjectBase |
自定義模型的實例 |
|
|
cc_ObjectUnique |
- |
|
|
cc_UserGroupPrivilege |
當添加用戶權限的時候, |
|
通過group_id字段關聯 |
cc_UserGroup |
添加用戶權限管理 |
|
|
cc_UserCustom |
用戶自定義收藏模塊 |
|
index_v4_recently |
|
- |
|
|
cc_TopoGraphics |
存儲模塊在拓撲圖中的位置 |
|
|
|
系統 |
|
|
cc_Subscription |
事件推送 |
|
|
cc_SetBase |
業務資源-> 業務拓撲 |
|
|
cc_PropertyGroup |
|
|
|
cc_Process |
業務資源-> 進程管理 存儲進程 |
|
bk_biz_id 對應 cc_ApplicationBase |
cc_ProcOpTask |
- |
|
|
cc_ProcInstanceModel |
- |
|
|
cc_ProcInstanceDetail |
- |
|
|
|
- |
|
|
cc_Privilege |
- |
|
|
cc_PlatBase |
- |
|
三 模塊介紹
ui: 前端代碼
web_server 后端服務,所有請求入口
api_server : 接口層,這一層是系統的api服務網關
scene_server/ 業務場景模塊,基於資源管理對應用場景的封裝
admin_server 把配置文件放入zk
event_server 事件訂閱
host_server 主機
topo_server 模型,實例,業務,模塊等
proc_server 進程
source_controller :源管理模塊,把資源類型進行了抽象,每一類資源由一類微服務進程來管理
auditController 審計
hostController 主機
objectController 對象
procController 進程
storage: 提供系統所需的資源存儲等系統服務
apimachinery : 根據要操作的資源生成新的url,調用source_controller
四、
請求執行過程:
藍鯨CMDB文檔
本地啟動cmdb
一、服務器啟動回顧
部署cmdb的時候,輸入./start.sh 就可以啟動12個服務,那么針對這12個服務進行分析一下。首先看一下啟動后輸出的內容:
這里的配置參數,是根據運行的配置腳本所生成的,如:
生成配置文件位置:
configcenter/src/bin/build/3.2.17/cmdb_adminserver/configures/*
二 打開cmdb項目,把上一步cmdb_adminserver/configures/下生成的所有配置文件覆蓋到configcenter/resources/configures/目錄中 (即替換配置文件)。
然后修改configcenter/resources/configures/migrate.conf文件
三、本地啟動項目
cmdb是微服務框架,把平台拆分成了12個服務,本次我們啟動hostServer服務,其他服務啟動類似。
啟動hostServer的main方法(host.go文件):
啟動的的時候配置參數:Program arguments
例如:
--addrport=127.0.0.1:60001 --logtostderr=false --log-dir=./logs --v=3 --regdiscv=127.0.0.1:2181
每個服務啟動時 Program arguments 參數不同 可參考服務啟動時顯示的參數進行配置
CMDB數據庫表設計
1表功能
表名 |
關聯業務 |
接口 |
備注 |
cc_ApplicationBase |
基礎資源-業務信息存儲 |
|
|
cc_AsstDes |
模型管理-關聯類型數據存儲 |
|
|
cc_History |
- |
|
|
cc_HostBase |
基礎資源-主機數據存儲 |
|
|
cc_HostFavourite |
- |
|
|
cc_idgenerator |
生成ID的,記錄每種記錄最大的ID,類似mysql 主鍵的auto_increment |
|
|
cc_InsAsst |
- |
|
|
cc_ModuleBase |
業務資源-業務拓撲中的葉子節點數據 |
|
|
cc_ModuleHostConfig |
主機分配到具體業務模塊表,bk_module_id是cc_ModuleBase.bk_module_id |
|
|
cc_Netcollect_Device |
- |
|
|
cc_Netcollect_Property |
- |
|
|
cc_ObjAsst |
模型與模型之間的關聯關系,見模型管理-模型拓撲 |
|
|
cc_ObjAttDes |
模型的所有字段 |
|
|
cc_ObjClassification |
存儲模型分組數據,針對模型管理-新建分組業務 |
|
|
cc_ObjDes |
存儲模型數據,針對模型管理-模型-新建模型業務 |
|
|
cc_ObjectBase |
自定義模型的實例 |
|
|
cc_ObjectUnique |
- |
|
|
cc_UserGroupPrivilege |
當添加用戶權限的時候, |
|
通過group_id字段關聯 |
cc_UserGroup |
添加用戶權限管理 |
|
|
cc_UserCustom |
用戶自定義收藏模塊 |
|
index_v4_recently |
|
- |
|
|
cc_TopoGraphics |
存儲模塊在拓撲圖中的位置 |
|
|
|
系統 |
|
|
cc_Subscription |
事件推送 |
|
|
cc_SetBase |
業務資源-> 業務拓撲 |
|
|
cc_PropertyGroup |
|
|
|
cc_Process |
業務資源-> 進程管理 存儲進程 |
|
bk_biz_id 對應 cc_ApplicationBase |
cc_ProcOpTask |
- |
|
|
cc_ProcInstanceModel |
- |
|
|
cc_ProcInstanceDetail |
- |
|
|
|
- |
|
|
cc_Privilege |
- |
|
|
cc_PlatBase |
- |
|
2 名詞介紹
資源名稱:
biz: 業務線
set:集群
module:模塊
host:主機
字段描述:
bk_supplier_id :供應商ID 默認為0 ,不做變動
bk_host_id : 主機id
bk_obj_id. : 模型id, 模型的唯一標識,如,szone,redis,set,module
關鍵詞:
association 關聯類型
object_association模型關聯
inst_association 實例關聯
privilege 權限
inst 模型實例
object 對象:如 module,set等
classification 模型分類
custom_query:userapi 自定義api
favorites 主機收藏
模塊介紹
ui: 前端代碼
web_server 后端服務,所有請求入口
api_server : 接口層,這一層是系統的api服務網關
scene_server/ 業務場景模塊,基於資源管理對應用場景的封裝
admin_server 把配置文件放入zk
event_server 事件訂閱
host_server 主機
topo_server 模型,實例,業務,模塊等
proc_server 進程
source_controller :源管理模塊,把資源類型進行了抽象,每一類資源由一類微服務進程來管理
auditController 審計
hostController 主機
objectController 對象
procController 進程
storage: 提供系統所需的資源存儲等系統服務
apimachinery : 根據要操作的資源生成新的url,調用source_controller
功能介紹
1 常用方法
法/文件 |
作用 |
位置 |
詳細位置 |
FindSingleObject(bk_obj_id) |
查找是否存在此模型 |
Topo_server |
topo_server /core/operation/object.go |
condition.CreateCondition() |
創建一個結構體存儲查詢條件 |
common/condition/condition.go |
|
dbInst := logic.Instance. Table(tName). Find(condition). Sort(sort). Start(uint64(skip)). Limit(uint64(limit)) |
將查詢條件賦值給結構體賦值 解析: logic 是一個結構體,Instance是結構體中的一個字段 Instance同時還是一個接口,Table是其中一個實現方法 Table()的返回值是Collection Collection是一個結構體,掛在其結體下的方法有find Sort,Start,Limit返回值是 Find這個結構體 |
src/source_controller/hostcontroller/logics/object.go |
GetObjectByCondition()方法 |
dbInst.All() 即Find.All() dbInst.One() 即Find.One() |
查詢數據庫 解析:one() 和All()這兩個方法都掛在Find結構體下,而在上一行中已經將查詢條件賦值給Find,所以當調用All方法時,可直接從Find中取值進行查詢盡行查詢 例如:f.dbc.DB(f.dbname).C(f.collName).Find(f.filter).One(result) |
src/storage/dal/mongo/mgo_mongo.go |
|
2 UI:
前端 VUE:
cmdb vue組件庫:https://magicbox.bk.tencent.com/components_vue/2.0/example/index.html#/
前端vue 代碼規范使用 Eslint插件,如不按照規范編寫則編譯報錯:
部分規則如下:
不要有多個連續空行。
關鍵字后面要有一個空格,
函數參數列表括號前面要有一個空格。
始終使用 === 不使用 ==,
逗號后面有一個空格。
else 與它的大括號同行
始終處理函數的 err 參數
瀏覽器全局變量始終添加前綴 window.
var 聲明,每個聲明占一行
無多余逗號
逗號必須放在當前行的末尾
. 應當與屬性同行
文件以空行結尾
鍵名和鍵值之間要有空格
構造函數的名字以大寫字母開始
…..等等
若要關閉Eslint驗證:
src/ui/build/webpack.base.conf.js 文件中 注釋掉eslint
前端請求示例:
請求調用流程: |
getHostList()------> |
search()—> getHostList() ———> |
searchHost() |
|
|
|
方法位置 |
ui/src/views/resource/index.vue |
ui/src/components/hosts/table/index.vue |
ui/src/store/modules/api/host-search.js |
|
|
|
功能 |
頁面:獲取所有主機 |
調用子組件中的方法 |
接收參數 ,發送http請求 |
|
|
|
文件介紹
位置 |
作用 |
|
|
|
|
src/ui/src/components |
Vue組件,方便復用 |
|
|
|
|
ui/src/store/modules/api/* |
封裝URL,接收參數,向后台發請求 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/ui/src/views /* |
所有頁面 |
|
|
|
|
ui/src/views/index/index.vue |
首頁 |
|
|
|
|
ui/src/views/business/index.vue |
基礎資源/業務 |
|
|
|
|
ui/src/views/resource/index.vue |
基礎資源/主機 |
|
|
|
|
ui/src/views/hosts/index.vue |
業務資源/主機 |
|
|
|
|
ui/src/views/eventpush/index.vue |
模型管理/事件推送 |
|
|
|
|
ui/src/views/topology/index.vue |
業務資源/業務拓撲 |
|
|
|
|
ui/src/views/custom-query/index.vue |
業務資源/動態分組 |
|
|
|
|
ui/src/views/process/index.vue |
業務資源/進程管理 |
|
|
|
|
ui/src/views/audit/index.vue |
審計與分析/操作審計 |
|
|
|
|
ui/src/views/model-association/index.vue |
模型管理/關聯模型 |
|
|
|
|
ui/src/views/model-manage/index.vue |
模型管理/模型 |
|
|
|
|
ui/src/views/model-topology/index.vue |
模型管理/模型拓撲 |
|
|
|
|
ui/src/views/business-model/index.vue |
模型管理/業務模型 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 web_server
文件 |
作用 |
|
|
|
|
src/web_server/service/service.go |
接收所有請求 |
|
|
|
|
src/web_server/middleware/login.go |
中間件:判斷請求是否已經登陸,以及是否需要轉發到api_server |
|
|
|
|
|
|
|
|
|
|
4 api_server:網關,對請求分類,轉發進入sence_server
文件 |
作用 |
||||
api_server/service/v3/uri.go |
對請求進行分類:topo,host,event,proc |
||||
api_server/service/v3/service.go |
根據請求類別,對請求進行轉發 |
||||
5 sence_server:業務處理,調用apimachinery 向資源層發起請求
文件 |
做用 |
隸屬接口 |
|
|
|
|
|||
XX__server/service/service.go |
接收路由請求,請求入口 |
|
|
|
|
||||
XX__server/service/* |
請求響應方法 |
|
|
|
|
|
|||
topo_server/service/* |
對set,module,biz,privite相關請求進行響應 |
|
|
|
|
|
|
|
|
topo_server/service/inst_module.go topo_server/service/inst_set.go topo_server/service/inst_business |
對模塊, 集群, 業務初步邏輯處理 |
|
|
|
|
||||
topo_server/core/operation/inst_module.go |
對modul進一步邏輯處理 |
ModuleOperationInterface |
|
|
|
|
|||
topo_server/core/operation/inst.go |
對邏輯處理結束的對象,向下級服務發起crud請求:module,set,biz,自定義模型,等對象 |
|
|
|
|
||||
topo_server/service/privilege.go |
用戶權限相關請求進行響應 |
|
|
|
|
||||
topo_server/core/privilege/privilege.go | 對用戶權限的邏輯處理 |
|
|
|
|
|
|
|
|
6 apimachinery :向資源層發起請求
文件/方法 |
作用 |
||||
apimachinery/objcontroller/inst/inst.go |
對object的增刪改查請求進行處理:module ,set,biz,自定義對象 等 |
||||
apimachinery/objcontroller/privilege/api.go |
權限,角色相關接口 |
||||
apimachinery/objcontroller/privilege/privilege.go |
權限,角色,相關接口實現方法 |
|
|
|
|
7 controller :對資源(數據庫)進行操作
操作方式:
在每個微服務下通常有三個文件夾 :app,service,logics
Service文件夾: 下主要是請求入口,已及請求的響應方法,進行邏輯處理,然后調用logics文件夾下的方法
Logics文件夾: 下通常有一個都有一個logics.go文件,logics.go文件中都有一個結構體Logics 如:
type Logics struct{
Instance dal.RDB
}
Logics文件夾中的所有方法都掛在結構體Logics下,如 func (lgc *Logics) DelModule();
Logics結構體中的Instance 是對數據操作的一些接口如:
type RDB interface {
Clone() RDB
// Table collection 操作
Table(collection string) Table
// StartTransaction 開啟新事務
StartTransaction(ctx context.Context) (RDB, error)
}
所以通過結構體Logics,Logics文件夾下的方法可以實現對數據庫的操作。
文件 |
作用 |
|
|
|
|
auditcontroller |
收集和查詢 操作記錄(審計) |
|
|
|
|
hostcontroller |
主機相關操作 |
|
|
|
|
objectcontroller |
Set, module,biz,自定義模型等操作 |
|
|
|
|
proccontroller |
進程相關操作 |
|
|
|
|
source_controller/objectcontroller/service/inst_action.go |
對實例進行增刪改查:module,set,biz等 |
|
|
|
|
source_controller/objectcontroller/service/common.go |
對數據庫操作的通用方法 |
|
|
|
|
objectcontroller/service/* |
對權限,角色,模型,biz相關接口進行響應 |
|
|
|
|
objectcontroller/service/privilege_action.go |
對用戶組權限進行增刪改查 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 common
文件 |
|
|
|
|
|
src/common/* |
封裝了對數據庫操作的方法 |
|
|
|
|
src/common/condition |
封裝查詢條件,如sort,limit,start,fiels |
|
|
|
|
src/common/conf |
讀取解析配置文件 |
|
|
|
|
src/common/mapstr |
將condition的fields字段轉換成map |
|
|
|
|
|
|
|
|
|
|
請求調用流程
1 執行流程
HTTP---- /* ----web_server
http請求首先進入web_server 在其中會驗證登陸等信息
web_server---------/api/v3/*--------> api_server
web_server中/api/v3的請求會被轉發到api_server,在api_server中請求被分類,以host資源為例:/api/v3/* 會轉換成/host/v3/* 向下一層服務發起請求
api_server----/host/v3/*------->scene_server----調用--->apimachinery(類似SDK)
api_server向scene_server發起請求,在scene_server中處理業務邏輯,scene_server調用apimachinery向下一級服務發起請求,在apimachinery中url會根據資源類型作出更改,以更改后的url向資源層發請求
apimachinery ---------> source_controller ---------調用------ storage
apimachinery向source_controller發起請求,在source_controller中調用storage封裝的方法完成對數據庫的操作
-------------------------------------------------------------------------------------------------------
ps:由於api_server只處理url路徑是 /api/v3/* 的請求,所以部分請求 url 不是 /api/v3/開頭則不會進入api_server,而是進入web_server進行處理。web_server通過調用apimachinery,向source_controller發起請求 來完成對資源的操作。
2 介紹
api_server 將收到的請求處理,分為四類轉發進入sence_server下的四個微服務,分別是,topo,host,proc,event 四大類。
例如:/api/v3/biz/...在api_server 中請求會被轉成 /topo/v3/biz/...
topo類包括:audit,biz,topo,identifier,inst,module,object,objects,/object/attr,objectatt,set, privilege
host類包括:host,hosts,userapi,usercustom,/findmany/modulehost
event類包括:event
proc類包括:proc
3 CMDB API請求示例
ps:每個微服務下都有一個../service/service.go文件作為請求入口
3.1 獲取主機基礎信息詳情
- API: GET /api/{version}/hosts/{bk_supplier_account}/{bk_host_id}
- http://localhost:8083/api/v3/hosts/0/77
- 功能說明:獲取77號主機基礎信息詳情
- input body: 無
http請求--------> api_server
api_server: 在src/api_server/service/v3/service.go 中接收所有跟路徑是/api/v3/ 的請求
請求變成/host/v3/hosts/0/77 進入下一個服務
api_server ------> scene_server :
scene_server: 在src/scene_server/host_server/service/service.go 接收所有跟路徑是/host/v3 的路由
其中/hosts/{bk_supplier_account}/{bk_host_id} 接收到請求 並調用
GetHostInstanceProperties()方法:獲取參數,處理參數
在 src/apimachinery/hostcontroller/host/api.go文件GetHostByID()方法中 進入下一級服務, 跳轉路徑:/host/v3/host/77
scene_server-------source_controller:
source_controller:在src/source_controller/hostcontroller/service/service.go文件中接收所有跟路徑
為/host/v3的路由,/host/v3/host/{bk_host_id} 接收請求,並調用GetHostByID()方法
最后調用storage,src/storage/dal/mongo/mgo_mongo.go文件中One()方法完成數據庫
查詢 。
3.2 查詢業務線
API: POST /api/{version}/biz/search/{bk_supplier_account}
參數:{ "condition": {}}
condition 參數為業務的任意屬性,如果不寫代表搜索全部數據
例: http://localhost:8083/api/v3/biz/search/0
apiServer 接收請求並轉換成:/topo/v3/app/search/0
topo_server 接收請求並調用 SearchBusiness方法------ 調用FindBusiness()(實現方法在本 頁)---- FindOriginInst(實現方法在本頁)......
最后調用在 src/apimachinery/objcontroller/inst/inst.go。SearchObjects方法
請求變成: /insts/biz/search
TopoConroller
調用SearchInstObjects方法響應,然后調用src/source_controller/objectcontroller/service/common.go GetObjectByCondition方法
3.3 查詢模型實例
API POST /api/{version}/inst/association/search/owner/{bk_supplier_account}/object/{bk_obj_id}
參數{
"condition":{
"bk_weblogic":[
{
"field":"bk_inst_name",
"operator":"$regex",
"value":"qq"
}
]
}
}
例:http://localhost:8083/api/v3/inst/association/search/owner/0/object/redis
api_server 收到請求轉化成 /topo/v3/inst/association/search/owner/0/object/redis進入下一服務
業務場景 :topo_server
src/scene_server/topo_server/service/service_initfunc.go 接收請求 轉到
SearchInstByAssociation方法--- FindInstByAssociationInst----FindInst----FindOriginInst---
c.clientSet.ObjectController().Instance().SearchObjects()----
src/apimachinery/objcontroller/inst/inst.go SearchObjects()生成URL:/insts/object/search 進入
下一級服務.
資源管理 :object_controller
/insts/{obj_type}/search 接收請求 調用響應方法SearchInstObjects()------ GetHostByCondition---all()
3.4 條件查詢主機
API: POST /api/{version}/hosts/search
參數:可根據根據set 、host、biz、module等模型屬性進行查詢
{ "page":{ "start":0, "limit":10, "sort":"bk_host_id" }, "pattern":"", "bk_biz_id":2, "ip":{ "flag":"bk_host_innerip|bk_host_outerip", "exact":1, "data":[ ] }, "condition":[ { "bk_obj_id":"host", "fields":[ ], "condition":[ ] }, { "bk_obj_id":"module", "fields":[ ], "condition":[ ] }, { "bk_obj_id":"set", "fields":[ ], "condition":[ ] }, { "bk_obj_id":"biz", "fields":[ ], "condition":[ { "field":"default", "operator":"$ne", "value":1 } ] } ] }
示例:
localhost:8083/api/v3/hosts/search
參數:{}
api_sever 接收請求 (生成url:/host/v3/hosts/search)---->
sence_service(src/scene_server/host_server/service/service.go )------SearchHost()---s.Logics.SearchHost()----SearchHostByConds()----sh.searchByHostConds()-------sh.lgc.CoreAPI.HostController().Host().GetHosts: path=src/apimachinery/hostcontroller/host/api.go
url==/hosts/search
進入 host_controller
src/source_controller/hostcontroller/service/service.go-----GetHosts()--GetObjectByCondition()---all()
3.5 創建模塊
POST /api/{version}/module/{bk_biz_id}/{bk_set_id}
input body:
{
"bk_module_name":"cc_module",
"bk_supplier_account":"0",
"bk_parent_id":0
}
示例:
localhost:8083/api/v3/module/3/2
參數:{ "bk_module_name":"devops"}
http ---------> api_server ---- 跳入下一服務,URL:/topo/v3/module/3/2
//查詢模型類型是否存在
topo_server :/module/{app_id}/{set_id} 接收上一請求------>CreateModule()方法
-------FindSingleObject()//查詢 --- 跳入下一服務,url:/insts/module/search
object_controller:/insts/{obj_type}/search 接收上一請求------>SearchInstObjects
//創建模型
topo_server: ------ModuleOperation().CreateModule()
object_controller: /insts/{obj_type}接收請求
3.6 創建集群
API: POST /api/{version}/set/{bk_biz_id}
參數
{
"bk_set_name":"wefd", 集群名字
"bk_parent_id":0, 集群上級id 可以是業務線 ,或者其他,具體參照拓撲模型
"bk_biz_id":1 業務線
}
示例:localhost:8083/api/v3/set/3
topo_server /set/{app_id} 接收請求
新增接口流程
1 簡介版
查詢主機:localhost:8083/api/v3/hosts/selectAll
1 url 設計: 以/api/v3/{type}/…. 開頭的請求會被web_server轉發進入 api_server
2 type 代表資源類型 根據type 類型 被轉發進入sence_server
3 在host_server中編寫請求 /host/v3/hosts/selectAll的入口,以及響應方法selectAll(),在selectAll()中處理
調用資源層完成,業務邏輯的處理
4 selectAll()方法調用src/apimachinery 中的httpclient 向controller發起請求
所以在src/apimachinery/hostcontroller/host/api.go 中編寫方法 ,使用httpClient向host_controller 發起請
求
請求的url 設計沒有規定 如 subPath := "/hosts/myJob”
則完整請求是 localhost:8083/host/v3/hosts/myJob
5 在hostcontroller中 編寫請求 /host/v3/hosts/myJob的 路由入口
6 編寫myJob的響應方法 查詢數據 返回數據
ps : 從第4步開始 src/apimachinery 中的httpclient 向controller發起請求 只是純粹的對資源進行操作,不包含業務邏輯,所以 一般情況下 只需要變動sence_server,無需變動apimachinery 和controller
2 實操版
1 url 設計: 以/api/v3/{type}/…. 開頭的請求會被web_server轉發進入 api_server
2 type 代表資源類型 可以為:
biz,topo,identifier,inst,module,objectset,privilege,host,hosts,userapi,usercustom, event proc等,具體請見src/api_server/service/v3/uri.go 中資源划分
3 新增接口查詢主機,假設 url設計為:localhost:8083/api/v3/hosts/selectAll,在api_server中 會根據url中的關鍵詞hosts ,判定要操作的資源是host,所以url 從 /api/v3/hosts/selectAll 變成 /host/v3/hosts/selectAll
4 在host_server中,src/scene_server/host_server/service/service.go 接收所有/host/{version}
的請求
所以在此文件中編寫/host/v3/hosts/selectAll請求入口
api.Route(api.POST("/hosts/selectAll").To(s.SelectAllHost))
----------------
響應方法:
func (s *Service) SelectAllHost(req *restful.Request, resp *restful.Response) {
//獲取頭信息
pheader := req.Request.Header
// new 出一個結構體 存儲查詢參數
body := new(meta.HostCommonSearch)
//獲取講請求中的參數 解析賦值到 結構體body中
json.NewDecoder(req.Request.Body).Decode(body)
// 獲得頭信息pheader 和 傳遞的參數body后 調用下個方法SearchHost() 進行查詢
host, err := s.Logics.SearchHost(pheader, body)
}
Ps: SearchHost()方法掛在結構體Logics下,Logics結構體中有接口可以調用下一個微服務
func (lgc *Logics)SearchHost(phader http.Header,body Body) (*metadata.GetHostsResult, error) {
//從傳入的body中 獲取到參數 賦值在 結構體 metadata.QueryInput中
query := metadata.QueryInput{
Start: body.start,
Limit: body.limit,
Sort: common.BKHostInnerIPField,
Fields: common.BKHostInnerIPField,
}
// 把查詢參數query 傳給apimacheniry,由apimacheniry 向controller發起請求
lgc.CoreAPI.HostController().Host().MyjobSpimachinery()
}
編寫 MyjobSpimachinery方法:
在src/apimachinery/hostcontroller/host/api.go 中編寫 方法 MyjobSpimachinery(),
在MyjobSpimachinery中
subPath為要跳轉的路由入口,可自己設計
metadata.GetHostsResult返回值類型
.Do() 進行跳轉
.Into() 把查詢結果放進new 出來的結構體,並return
代碼如下:
func (t *hostctrl) MyjobSpimachinery(ctx context.Context, h http.Header, opt *metadata.QueryInput) (resp *metadata.GetHostsResult, err error) { resp = new(metadata.GetHostsResult) subPath := "/hosts/myJob" err = t.client.Post(). WithContext(ctx). Body(opt). SubResource(subPath). WithHeaders(h). Do(). Into(resp) return }
-------------------------------------------------------------------
5 在src/source_controller/hostcontroller/service/service.go中接收所有請求是/host/v3 的請求
所以在此文件中編寫/hosts/myJob 的入口
api.Route(api.POST("/hosts/myJob").To(s.MyJob))
響應方法:
func (s *Service) MyJob(req *restful.Request, resp *restful.Response) {
//獲取參數調用數據庫進行查詢
}
6.
CMDB中對mongo的操作
1、
cmdb對mongo的常規操作進行了一層封裝,方便之后的CRUD,在代碼中發現最常見的一種查詢方式如下:
lgc.Instance.Table("表名"). Find(map) .All(ctx,&results);
map代表查詢條件,通過這行代碼完成查詢並且把查詢結果賦值給results,下面將對這行代碼進行解釋
2
觀察結構體Logics
type Logics struct {
Instance dal.RDB
Cache *redis.Client
*backbone.Engine
}
發現Logics下 Instance dal.RDB 是一個interface ,其實現方法 有對db的一些操作 如下
type RDB interface {
Clone() RDB
// Table collection 操作
Table(collection string) Table
// StartTransaction 開啟新事務
StartTransaction(ctx context.Context) (RDB, error)
// Commit 提交事務
Commit(context.Context) error
// Abort 取消事務
Abort(context.Context) error
}
其中Table(collection string) Table是一個interface,其實現方法有
type Table interface {
// Find 查詢多個並反序列化到 Result
Find(filter Filter) Find
// Aggregate 聚合查詢
AggregateOne(ctx context.Context, pipeline interface{}, result interface{}) error
AggregateAll(ctx context.Context, pipeline interface{}, result interface{}) error
// Insert 插入數據, docs 可以為 單個數據 或者 多個數據
Insert(ctx context.Context, docs interface{}) error
// Update 更新數據
Update(ctx context.Context, filter Filter, doc interface{}) error
// Delete 刪除數據
Delete(ctx context.Context, filter Filter) error
}
觀察上面結構體總結如下:
Logics 是一個結構體,Instance是結構體中的一個字段。
即:Logics.Instance
Instance同時還是一個接口,Table是其中一個實現方法。
即 :Logics.Instance.Table(“表名”)
Table(name String)的返回值是Collection,Collection是一個結構體指定了要操作的表名。
Find(map)方法掛在Collection結構體下,Find方法將Collection 和map(查詢條件)放入Find結構對應的字段。 返回Find結構體 。
即: inst := Logics.Instance.Table(“表名”).Find(map)
此時inst 是一個指定了查尋條件和 要操作的表名的Find結構體
All()方法 掛在Find結構體下:
Logics.Instance.Table(“表名”).Find(map).all(results)
進行最終查詢。
在以上的操作中只是為了將各種查詢條件放入Find結構中,最終All()方法從Find結構體中取出查詢條件進行查詢,將結果賦值給results;
All 方法代碼如下:
func (f *Find) All(result interface{}) error {
f.dbc.Refresh()
query := f.dbc.DB(f.dbname).C(f.collName).Find(f.filter)
query = query.Select(f.projection)
query = query.Skip(int(f.start))
query = query.Limit(int(f.limit))
query = query.Sort(f.sort...)
//執行查詢,若是查詢出錯 返回錯誤信息
return query.All(result)
}
實操:
1 查詢內網ip是121.21.13.14的主機
首先創建一個map存放查詢條件
condition:=make(map[string]interface{})
condition["bk_host_innerip"]="121.21.13.14"
condition["bk_host_id"]="host"
然后定義一個可變的 map數組接收查詢結果
results := make([]map[string]interface{}, 0)
最后進行查詢
lgc.Instance.
//指定查詢的表
Table("cc_HostBase").
//查詢條件
Find(condition)
//進行查詢
.All(ctx,&results);
find方法只是為了將查詢條件賦值給Find結構體,最后的All方法從Find結構體中取出查詢條件編寫查詢語句進行查詢
2 插入一條信息進入表cc_HostBase中
//創建插入信息
inputc := input.(map[string]interface{})
inputc[“name”]=“張三"
//開始插入
lgc.Instance.
//指定查詢的表
Table("cc_HostBase").
//進行查詢
.insert(ctx,inputc);
3 在上文查詢語句 Logics.Instance.Table(“表名”).Find(map).all(results)中,將查詢條件放在map中,但並不能完全滿足需求,例如:查詢主機id 不等於"23"的主機,或者大於/小於某個值時都無法用簡單的map進行封裝查詢條件,而在cmdb中還有另外一種存放查詢條件的結構體
3.1 查詢條件放在結構體condition中
type condition struct {
start int64
limit int64
sort string
fields []Field
or []OR
filterFields []string
}
// 上面這個結構體 調用下面這個接口的實現方法
type Condition interface {
SetPage(page types.MapStr) error
SetStart(start int64)
GetStart() int64
SetLimit(limit int64)
GetLimit() int64
SetSort(sort string)
GetSort() string
SetFields(fields []string)
GetFields() []string
Field(fieldName string) Field
NewOR() OR
Parse(data types.MapStr) error
ToMapStr() types.MapStr
}
接口Condition 有Field 字段,其中字段fields 是個interface 其實現方法有
type Field interface {
Eq(val interface{}) Condition
NotEq(val interface{}) Condition
Like(val interface{}) Condition
In(val interface{}) Condition
NotIn(val interface{}) Condition
Lt(val interface{}) Condition
Lte(val interface{}) Condition
Gt(val interface{}) Condition
NotGt(val interface{}) Condition
Gte(val interface{}) Condition
ToMapStr() types.MapStr
}
所以:cond.Field(“字段").NotEq("條件")
如:
// 創建condition結構體
cond := condition.CreateCondition()
//查詢內網ip不等於121.21.13.14的機器
cond.Field(“bk_host_innerIp").NotEq("121.21.13.14")
//創建結構體condMapStr
var condMapStr mapstr.MapStr= mapstr.New()
//將conf 進行一些轉化
condMapStr.Merge(cond.ToMapStr())
//condMapStr放着查詢條件,作為參數放入Find中進行查詢
err:= lgc.Instance.Table("cc_HostBase"). Find(condMapStr) .All(ctx,&results);
Redis在cmdb中的作用
redis在cmdb中主要用於事件訂閱:
1 redis的ident文件夾下中存放的信息有:
業務信息,主機信息,模塊信息,集群信息,進程信息
2 redis中的信息同步:
2.1 以上信息並非是實時更新,event_server負責從mongo數據庫中同步最新的數據,大概每隔1分鍾向redis中同步一次信息。
2.2 在event_server啟動時調用app.Run()方法------ errCh <- distribution.Start(ctx, cache, db, rpccli)------------chErr <- ih.StartHandleInsts()中代碼片段:
go func() {
ih.fetchHostCache()
for range time.Tick(time.Second * 60) {
ih.fetchHostCache()
}
}()
可設置redis中的信息多久和mongo同步一次
2.3 新增訂閱事件,刪除訂閱事件,會時時同步到redis,redis中記錄的只是 訂閱事件id
3 event_server 直接調用storage 操作數據庫,不再調用controller
event_server : 事件訂閱服務
請求入口:src/scene_server/event_server/service/service.go:
//查詢訂閱事件
api.Route(api.POST("/subscribe/search/{ownerID}/{appID}").To(s.Query))
//只測試連通性
api.Route(api.POST("/subscribe/ping").To(s.Ping))
//測試推送
api.Route(api.POST("/subscribe/telnet").To(s.Telnet))
//新增訂閱事件
api.Route(api.POST("/subscribe/{ownerID}/{appID}").To(s.Subscribe))
//刪除訂閱事件
api.Route(api.DELETE("/subscribe/{ownerID}/{appID}/{subscribeID}").To(s.UnSubscribe))
//修改訂閱事件
api.Route(api.PUT("/subscribe/{ownerID}/{appID}/{subscribeID}").To(s.Rebook))
4 生產者--消費者
1生產者:
type Service struct {
Core *backbone.Engine
Instance dal.RDB
Cache *redis.Client
}
在結構體Service中有 Cache *redis.Client
當對資源進行增刪改查時,在controller中操作成功后,會向redis中新增一個消息 如下:
ec := eventclient.NewEventContextByReq(req.Request.Header, cli.Cache)
ec.InsertEvent(metadata.EventTypeInstData, objType, metadata.EventActionUpdate, newData)
lpush(key,value) 將消息放入redis
這時在redis中,如圖4個消息存放於隊列中等待被消費:
2 消費者
在 src/scene_server/event_server/identifier/identifier.go :
handleInstLoop方法:
在服務啟動的時候 調用handleInstLoop()方法,其中for循環中ih.popEventInst()會和redis建立連接,並從redis中根據key獲取到值
for {
event := ih.popEventInst()
if nil == event {
time.Sleep(time.Second * 2)
continue
}
上面for循環內的代碼會不停的向redis建立連接取值,當value為空時,繼續建立連接會造成資源浪費,所以在ih.popEventInst()中,從redis中取值時並未使用rpop,而是使用了阻塞命令brpop,當value為空時線程會阻塞在那
審計信息的記錄
8/10
審計操作是在業務邏輯層完成的操作:
Sence_server ————調用———— src/apimachinery/auditcontroller ——跳轉——— audit_controller
在業務邏輯層中(server)處理業務后,根據返回的結果新增操作的審計信息
apimachinery 內封裝的有新增審計信息方法:
新增業務操作 AddBusinessLog()
查詢審計信息 GetAuditLog ()
新增主機操作 AddHostLog()
新增模塊操作 AddModuleLog()
新增對象操作 AddObjectLog()
新增進程操作 AddProcLog()
新增集群操作 AddSetLog()
server 調用apimachinery 封裝的方法,上述方法之外的操作不記錄審計。
具體新增審計代碼(1):
type Service struct {
*options.Config
*backbone.Engine
*logics.Logics
disc discovery.DiscoveryInterface
}
type Engine struct {
sync.Mutex
ServerInfo types.ServerInfo
CoreAPI apimachinery.ClientSetInterface
SvcDisc ServiceDiscoverInterface
Language language.CCLanguageIf
CCErr errors.CCErrorIf
}
aResult, err := service.CoreAPI.AuditController().AddHostLogs(context.Background(), common.BKDefaultOwnerID, appID, user, pheader, log)
通過結構體Service 調用CoreAPI 即apimachinery 內封裝的方法
9/10
具體新增審計代碼(2)
在topo_server 中
src/scene_server/topo_server/service/service_initfunc.go 可以接收請求有:
新增biz,
新增module,
新增set,
新增Inst
以上請求的響應方法處理邏輯之后,最終都要調用src/scene_server/topo_server/core/operation/inst.go下的
func (c *commonInst) CreateInst(){}方法。
在CreateInst中 新增審計信息 如下:
NewSupplementary().Audit(...).CommitCreateLog(...)
CommitCreateLog方法———commitSnapshot()在commitSnapshot中根據參數不同調用AuditController()中封裝好的審計方法
src/common/tablenames.go 所用到的表名,每個表名在這里都有一個變量表示;數據庫查詢時不直接寫查詢的表名,而是使用表名所代表的變量
association 關聯關系
在topo_server;
src/scene_server/topo_server/service/service_initfunc.go:中有着所有關聯關系的入口,分類如下
1 關聯類型:創建一種關聯關系用於實例間關聯事被引用
查詢關聯類型
"/topo/association/type/action/search
新增關聯類型
"/topo/association/type/action/create”
更新一個關聯類型
"/topo/association/type/{id}/action/update”
刪除一個關聯類型
"/topo/association/type/{id}/action/delete”
2 主機和模型實例關聯關系
/inst/association/action/search
/inst/association/action/create
/inst/association/{association_id}/action/delete
10/10
3模型拓撲關聯關系
/object/association/action/search
/object/association/action/create
/object/association/{id}/action/update
/object/association/{id}/action/delete
權限管理
1 創建角色,添加成員
創建角色時,選擇擁有此角色的成員; 也稱新建用戶分組
topo_server. API: POST /api/{version}/topo/privilege/group/{bk_supplier_account}
參數:分組名,分組成員
{
"group_name":"管理員",
"user_list":"owen;tt"
}
src/apimachinery/objcontroller/privilege/privilege.go: CreateUserGroup() 跳轉進入object——controller
src/source_controller/objectcontroller/service/service.go:接收請求
api.Route(api.POST("/privilege/group/{bk_supplier_account}").To(s.CreateUserGroup))
表:cc_Usergroup
2 添加的成員必須時 已經存在的賬戶 :查詢現有的的用戶
web_server :ws.GET("/user/list", s.GetUserList)
————— src/web_server/middleware/user/public.go :GetUserList
———— — — src/web_server/middleware/user/plugins/method/self/userinfo.go :GetUserList
在cmdb開源代碼中,不支持多用戶,在代碼固定了一個 admin 用戶
3 編輯用戶分組權限
API: POST /api/{version}/topo/privilege/group/detail/{bk_supplier_account}/{group_id}
參數:
{bk_middleware: {
bk_tomcat: ["search", "update", "delete"],
redis: ["search", "update", "delete”]
}
}
4 查詢用戶權限:
API: GET /api/{version}/topo/privilege/user/detail/{bk_supplier_account}/{user_name}
http://localhost:8083/api/v3/topo/privilege/user/detail/0/admin 獲取用戶admin的權限