cloudevents.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package models
  15. import (
  16. "context"
  17. "time"
  18. "yunion.io/x/cloudmux/pkg/cloudprovider"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/util/rbacscope"
  23. "yunion.io/x/sqlchemy"
  24. "yunion.io/x/sqlchemy/backends/clickhouse"
  25. "yunion.io/x/onecloud/pkg/apis"
  26. api "yunion.io/x/onecloud/pkg/apis/cloudevent"
  27. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  28. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  29. "yunion.io/x/onecloud/pkg/mcclient"
  30. "yunion.io/x/onecloud/pkg/util/stringutils2"
  31. )
  32. type SCloudeventManager struct {
  33. db.SModelBaseManager
  34. db.SDomainizedResourceBaseManager
  35. }
  36. var CloudeventManager *SCloudeventManager
  37. func InitCloudevent() {
  38. if consts.OpsLogWithClickhouse {
  39. CloudeventManager = &SCloudeventManager{
  40. SModelBaseManager: db.NewModelBaseManagerWithDBName(
  41. SCloudevent{},
  42. "cloudevents_tbl",
  43. "cloudevent",
  44. "cloudevents",
  45. db.ClickhouseDB,
  46. ),
  47. }
  48. col := CloudeventManager.TableSpec().ColumnSpec("created_at")
  49. if clickCol, ok := col.(clickhouse.IClickhouseColumnSpec); ok {
  50. clickCol.SetTTL(consts.SplitableMaxKeepMonths(), "MONTH")
  51. }
  52. } else {
  53. CloudeventManager = &SCloudeventManager{
  54. SModelBaseManager: db.NewModelBaseManagerWithSplitable(
  55. SCloudevent{},
  56. "cloudevents_tbl",
  57. "cloudevent",
  58. "cloudevents",
  59. "event_id",
  60. "created_at",
  61. consts.SplitableMaxDuration(),
  62. consts.SplitableMaxKeepMonths(),
  63. ),
  64. }
  65. }
  66. CloudeventManager.SetVirtualObject(CloudeventManager)
  67. }
  68. type SCloudevent struct {
  69. db.SModelBase
  70. db.SDomainizedResourceBase
  71. EventId int64 `primary:"true" auto_increment:"true" list:"user" clickhouse_partition_by:"toInt64(event_id/100000000000)`
  72. Name string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user"`
  73. Service string `width:"64" charset:"utf8" nullable:"true" list:"user"`
  74. ResourceType string `width:"64" charset:"utf8" nullable:"true" list:"user"`
  75. Action string `width:"64" charset:"utf8" nullable:"true" list:"user"`
  76. RequestId string `width:"128" charset:"utf8" nullable:"true" list:"user"`
  77. Request jsonutils.JSONObject `charset:"utf8" nullable:"true" list:"user"`
  78. Account string `width:"64" charset:"utf8" nullable:"true" list:"user"`
  79. Success bool `nullable:"false" list:"user"`
  80. CreatedAt time.Time `nullable:"false" created_at:"true" index:"true" get:"user" list:"user" clickhouse_ttl:"6m"`
  81. CloudproviderId string `width:"64" charset:"utf8" nullable:"true" list:"user"`
  82. Manager string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user"`
  83. Provider string `width:"64" charset:"ascii" nullable:"false" list:"user"`
  84. Brand string `width:"64" charset:"ascii" list:"domain"`
  85. }
  86. func (event *SCloudevent) BeforeInsert() {
  87. t := time.Now().UTC()
  88. event.EventId = db.CurrentTimestamp(t)
  89. }
  90. func (manager *SCloudeventManager) CreateByInsertOrUpdate() bool {
  91. return false
  92. }
  93. // 云平台操作日志列表
  94. func (manager *SCloudeventManager) ListItemFilter(
  95. ctx context.Context,
  96. q *sqlchemy.SQuery,
  97. userCred mcclient.TokenCredential,
  98. input api.CloudeventListInput,
  99. ) (*sqlchemy.SQuery, error) {
  100. q, err := manager.SModelBaseManager.ListItemFilter(ctx, q, userCred, input.ModelBaseListInput)
  101. if err != nil {
  102. return nil, errors.Wrap(err, "SModelBaseManager.ListItemFilter")
  103. }
  104. q, err = manager.SDomainizedResourceBaseManager.ListItemFilter(ctx, q, userCred, input.DomainizedResourceListInput)
  105. if err != nil {
  106. return nil, errors.Wrap(err, "SDomainizedResourceBaseManager.ListItemFilter")
  107. }
  108. if len(input.Providers) > 0 {
  109. q = q.In("provider", input.Providers)
  110. }
  111. if len(input.Brands) > 0 {
  112. q = q.In("brand", input.Brands)
  113. }
  114. if len(input.Service) > 0 {
  115. q = q.In("service", input.Service)
  116. }
  117. if len(input.Manager) > 0 {
  118. q = q.In("manager", input.Manager)
  119. }
  120. if len(input.Account) > 0 {
  121. q = q.In("account", input.Account)
  122. }
  123. if len(input.Action) > 0 {
  124. q = q.In("action", input.Action)
  125. }
  126. if len(input.ResourceType) > 0 {
  127. q = q.In("resource_type", input.ResourceType)
  128. }
  129. if input.Success != nil {
  130. q = q.Equals("success", *input.Success)
  131. }
  132. if !input.Since.IsZero() {
  133. q = q.GT("created_at", input.Since)
  134. }
  135. if !input.Until.IsZero() {
  136. q = q.LE("created_at", input.Until)
  137. }
  138. return q, nil
  139. }
  140. func (manager *SCloudeventManager) FetchCustomizeColumns(
  141. ctx context.Context,
  142. userCred mcclient.TokenCredential,
  143. query jsonutils.JSONObject,
  144. objs []interface{},
  145. fields stringutils2.SSortedStrings,
  146. isList bool,
  147. ) []api.CloudeventDetails {
  148. rows := make([]api.CloudeventDetails, len(objs))
  149. base := manager.SModelBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  150. domainRows := manager.SDomainizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  151. for i := range rows {
  152. rows[i].ModelBaseDetails = base[i]
  153. rows[i].DomainizedResourceInfo = domainRows[i]
  154. }
  155. return rows
  156. }
  157. func (self *SCloudevent) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  158. return self.SModelBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
  159. }
  160. func (manager *SCloudeventManager) NamespaceScope() rbacscope.TRbacScope {
  161. return rbacscope.ScopeDomain
  162. }
  163. func (manager *SCloudeventManager) ResourceScope() rbacscope.TRbacScope {
  164. return rbacscope.ScopeDomain
  165. }
  166. func (self *SCloudevent) GetOwnerId() mcclient.IIdentityProvider {
  167. owner := db.SOwnerId{DomainId: self.DomainId}
  168. return &owner
  169. }
  170. func (manager *SCloudeventManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, man db.FilterByOwnerProvider, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
  171. return manager.SDomainizedResourceBaseManager.FilterByOwner(ctx, q, man, userCred, owner, scope)
  172. }
  173. func (manager *SCloudeventManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
  174. return manager.SDomainizedResourceBaseManager.FetchOwnerId(ctx, data)
  175. }
  176. func (manager *SCloudeventManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
  177. return manager.SDomainizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  178. }
  179. func (manager *SCloudeventManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  180. return manager.SDomainizedResourceBaseManager.QueryDistinctExtraField(q, field)
  181. }
  182. func (manager *SCloudeventManager) OrderByExtraFields(
  183. ctx context.Context,
  184. q *sqlchemy.SQuery,
  185. userCred mcclient.TokenCredential,
  186. query api.CloudeventListInput,
  187. ) (*sqlchemy.SQuery, error) {
  188. return manager.SDomainizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DomainizedResourceListInput)
  189. }
  190. func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred mcclient.TokenCredential, cloudprovider *SCloudprovider, iEvents []cloudprovider.ICloudEvent) int {
  191. count := 0
  192. for _, iEvent := range iEvents {
  193. event := &SCloudevent{
  194. Name: iEvent.GetName(),
  195. Service: iEvent.GetService(),
  196. ResourceType: iEvent.GetResourceType(),
  197. Action: iEvent.GetAction(),
  198. Account: iEvent.GetAccount(),
  199. RequestId: iEvent.GetRequestId(),
  200. Request: iEvent.GetRequest(),
  201. Success: iEvent.IsSuccess(),
  202. Manager: cloudprovider.Name,
  203. Provider: cloudprovider.Provider,
  204. Brand: cloudprovider.Brand,
  205. CloudproviderId: cloudprovider.Id,
  206. }
  207. event.DomainId = cloudprovider.DomainId
  208. if len(event.Brand) == 0 {
  209. event.Brand = event.Provider
  210. }
  211. for k, v := range map[string]string{
  212. "service": event.Service,
  213. "resoruce_type": event.ResourceType,
  214. "action": event.Action,
  215. "account": event.Account,
  216. "manager": event.Manager,
  217. "provider": event.Provider,
  218. "brand": event.Brand,
  219. } {
  220. db.DistinctFieldManager.InsertOrUpdate(ctx, manager, k, v)
  221. }
  222. event.CreatedAt = iEvent.GetCreatedAt()
  223. event.SetModelManager(manager, event)
  224. err := manager.TableSpec().Insert(ctx, event)
  225. if err != nil {
  226. log.Errorf("failed to insert event: %s for cloudprovider: %s(%s) error: %v", jsonutils.Marshal(event).PrettyString(), cloudprovider.Name, cloudprovider.Id, err)
  227. continue
  228. }
  229. count += 1
  230. }
  231. return count
  232. }
  233. func (manager *SCloudeventManager) GetPagingConfig() *db.SPagingConfig {
  234. return &db.SPagingConfig{
  235. Order: sqlchemy.SQL_ORDER_DESC,
  236. MarkerFields: []string{"created_at", "event_id"},
  237. DefaultLimit: 20,
  238. }
  239. }
  240. func (manager *SCloudeventManager) GetPropertyDistinctField(ctx context.Context, userCred mcclient.TokenCredential, input apis.DistinctFieldInput) (jsonutils.JSONObject, error) {
  241. fields, err := db.DistinctFieldManager.GetObjectDistinctFields(manager.Keyword())
  242. if err != nil {
  243. return nil, errors.Wrapf(err, "DistinctFieldManager.GetObjectDistinctFields")
  244. }
  245. fieldMaps := map[string][]string{}
  246. for _, field := range fields {
  247. _, ok := fieldMaps[field.Key]
  248. if !ok {
  249. fieldMaps[field.Key] = []string{}
  250. }
  251. fieldMaps[field.Key] = append(fieldMaps[field.Key], field.Value)
  252. }
  253. ret := map[string][]string{}
  254. for _, key := range input.Field {
  255. ret[key], _ = fieldMaps[key]
  256. }
  257. return jsonutils.Marshal(ret), nil
  258. }