app.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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. "fmt"
  18. "time"
  19. "yunion.io/x/cloudmux/pkg/cloudprovider"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/tristate"
  24. "yunion.io/x/pkg/util/compare"
  25. "yunion.io/x/sqlchemy"
  26. "yunion.io/x/onecloud/pkg/apis"
  27. api "yunion.io/x/onecloud/pkg/apis/compute"
  28. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  30. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  31. "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
  32. "yunion.io/x/onecloud/pkg/compute/options"
  33. "yunion.io/x/onecloud/pkg/httperrors"
  34. "yunion.io/x/onecloud/pkg/mcclient"
  35. "yunion.io/x/onecloud/pkg/util/stringutils2"
  36. )
  37. // +onecloud:swagger-gen-model-singular=webapp
  38. // +onecloud:swagger-gen-model-plural=webapps
  39. type SAppManager struct {
  40. db.SVirtualResourceBaseManager
  41. db.SExternalizedResourceBaseManager
  42. db.SEnabledResourceBaseManager
  43. SManagedResourceBaseManager
  44. SCloudregionResourceBaseManager
  45. SNetworkResourceBaseManager
  46. }
  47. type SApp struct {
  48. db.SVirtualResourceBase
  49. db.SExternalizedResourceBase
  50. db.SEnabledResourceBase
  51. SManagedResourceBase
  52. SCloudregionResourceBase
  53. SNetworkResourceBase
  54. TechStack string `width:"64" charset:"ascii" nullable:"false" get:"user" list:"user"`
  55. OsType string `width:"12" charset:"ascii" nullable:"true" get:"user" list:"user"`
  56. IpAddr string `width:"32" charset:"ascii" nullable:"true" list:"user"`
  57. Hostname string `width:"256" charset:"utf8" nullable:"true" list:"user"`
  58. ServerFarm string `width:"64" charset:"utf8" nullable:"true" list:"user"`
  59. PublicNetworkAccess string `width:"32" charset:"utf8" nullable:"true" list:"user"`
  60. }
  61. var AppManager *SAppManager
  62. func init() {
  63. AppManager = &SAppManager{
  64. SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
  65. SApp{},
  66. "apps_tbl",
  67. "webapp",
  68. "webapps",
  69. ),
  70. }
  71. AppManager.SetVirtualObject(AppManager)
  72. }
  73. func (am *SAppManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.AppListInput) (*sqlchemy.SQuery, error) {
  74. q, err := am.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.VirtualResourceListInput)
  75. if err != nil {
  76. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
  77. }
  78. q, err = am.SEnabledResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledResourceBaseListInput)
  79. if err != nil {
  80. return nil, errors.Wrap(err, "SEnabledResourceBaseManager.ListItemFilter")
  81. }
  82. q, err = am.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  83. if err != nil {
  84. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  85. }
  86. q, err = am.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
  87. if err != nil {
  88. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
  89. }
  90. q, err = am.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
  91. if err != nil {
  92. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
  93. }
  94. if query.TechStack != "" {
  95. q = q.Equals("tech_stack", query.TechStack)
  96. }
  97. return q, nil
  98. }
  99. func (am *SAppManager) OrderByExtraFields(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.AppListInput) (*sqlchemy.SQuery, error) {
  100. var err error
  101. q, err = am.SVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.VirtualResourceListInput)
  102. if err != nil {
  103. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.OrderByExtraFields")
  104. }
  105. q, err = am.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
  106. if err != nil {
  107. return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
  108. }
  109. q, err = am.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
  110. if err != nil {
  111. return nil, errors.Wrap(err, "CloudregionResourceBaseManager.OrderByExtraFields")
  112. }
  113. return q, nil
  114. }
  115. func (am *SAppManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  116. var err error
  117. q, err = am.SVirtualResourceBaseManager.QueryDistinctExtraField(q, field)
  118. if err == nil {
  119. return q, nil
  120. }
  121. q, err = am.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
  122. if err == nil {
  123. return q, nil
  124. }
  125. q, err = am.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
  126. if err == nil {
  127. return q, nil
  128. }
  129. switch field {
  130. case "tech_stack":
  131. q = am.Query("tech_stack").Distinct()
  132. }
  133. return q, nil
  134. }
  135. func (manager *SAppManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  136. var err error
  137. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
  138. if err == nil {
  139. return q, nil
  140. }
  141. return q, httperrors.ErrNotFound
  142. }
  143. func (am *SAppManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
  144. var err error
  145. q, err = am.SVirtualResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  146. if err != nil {
  147. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemExportKeys")
  148. }
  149. if keys.ContainsAny(am.SManagedResourceBaseManager.GetExportKeys()...) {
  150. q, err = am.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  151. if err != nil {
  152. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
  153. }
  154. }
  155. if keys.ContainsAny(am.SCloudregionResourceBaseManager.GetExportKeys()...) {
  156. q, err = am.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  157. if err != nil {
  158. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
  159. }
  160. }
  161. return q, nil
  162. }
  163. func (am *SAppManager) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (api.AppDetails, error) {
  164. return api.AppDetails{}, nil
  165. }
  166. func (a *SApp) GetAppEnvironments() ([]SAppEnvironment, error) {
  167. q := AppEnvironmentManager.Query().Equals("app_id", a.Id)
  168. ret := []SAppEnvironment{}
  169. err := db.FetchModelObjects(AppEnvironmentManager, q, &ret)
  170. if err != nil {
  171. return nil, errors.Wrap(err, "db.FetchModelObjects")
  172. }
  173. return ret, nil
  174. }
  175. func (am *SAppManager) GetApps(providerId string) ([]SApp, error) {
  176. q := AppManager.Query().Equals("manager_id", providerId)
  177. ret := []SApp{}
  178. err := db.FetchModelObjects(AppManager, q, &ret)
  179. if err != nil {
  180. return nil, errors.Wrap(err, "db.FetchModelObjects")
  181. }
  182. return ret, nil
  183. }
  184. func (self *SCloudregion) GetApps(managerId string) ([]SApp, error) {
  185. q := AppManager.Query().Equals("cloudregion_id", self.Id)
  186. if len(managerId) > 0 {
  187. q = q.Equals("manager_id", managerId)
  188. }
  189. ret := []SApp{}
  190. err := db.FetchModelObjects(AppManager, q, &ret)
  191. if err != nil {
  192. return nil, errors.Wrap(err, "db.FetchModelObjects")
  193. }
  194. return ret, nil
  195. }
  196. func (self *SCloudregion) SyncApps(
  197. ctx context.Context,
  198. userCred mcclient.TokenCredential,
  199. provider *SCloudprovider,
  200. exts []cloudprovider.ICloudApp,
  201. xor bool,
  202. ) compare.SyncResult {
  203. lockman.LockRawObject(ctx, AppManager.KeywordPlural(), fmt.Sprintf("%s-%s", provider.Id, self.Id))
  204. defer lockman.ReleaseRawObject(ctx, AppManager.KeywordPlural(), fmt.Sprintf("%s-%s", provider.Id, self.Id))
  205. result := compare.SyncResult{}
  206. apps, err := self.GetApps(provider.Id)
  207. if err != nil {
  208. result.Error(err)
  209. return result
  210. }
  211. removed := make([]SApp, 0)
  212. commondb := make([]SApp, 0)
  213. commonext := make([]cloudprovider.ICloudApp, 0)
  214. added := make([]cloudprovider.ICloudApp, 0)
  215. // compare
  216. err = compare.CompareSets(apps, exts, &removed, &commondb, &commonext, &added)
  217. if err != nil {
  218. result.Error(err)
  219. return result
  220. }
  221. // remove
  222. for i := 0; i < len(removed); i++ {
  223. err := removed[i].syncRemoveCloudApp(ctx, userCred)
  224. if err != nil {
  225. result.DeleteError(err)
  226. continue
  227. }
  228. result.Delete()
  229. }
  230. if !xor {
  231. // sync with cloud app
  232. for i := 0; i < len(commondb); i++ {
  233. err := commondb[i].SyncWithCloudApp(ctx, userCred, provider, commonext[i])
  234. if err != nil {
  235. result.UpdateError(err)
  236. continue
  237. }
  238. result.Update()
  239. }
  240. }
  241. // new one
  242. for i := 0; i < len(added); i++ {
  243. _, err := self.newFromCloudApp(ctx, userCred, provider, added[i])
  244. if err != nil {
  245. result.AddError(err)
  246. continue
  247. }
  248. result.Add()
  249. }
  250. return result
  251. }
  252. func (self *SCloudregion) newFromCloudApp(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudApp) (*SApp, error) {
  253. app := SApp{}
  254. app.SetModelManager(AppManager, &app)
  255. app.ExternalId = ext.GetGlobalId()
  256. app.CloudregionId = self.Id
  257. app.ManagerId = provider.Id
  258. app.IsEmulated = ext.IsEmulated()
  259. app.Status = ext.GetStatus()
  260. app.TechStack = ext.GetTechStack()
  261. app.Name = ext.GetName()
  262. app.Enabled = tristate.True
  263. app.OsType = string(ext.GetOsType())
  264. app.IpAddr = ext.GetIpAddress()
  265. app.Hostname = ext.GetHostname()
  266. app.ServerFarm = ext.GetServerFarm()
  267. app.PublicNetworkAccess = ext.GetPublicNetworkAccess()
  268. if netId := ext.GetNetworkId(); len(netId) > 0 {
  269. network, err := db.FetchByExternalIdAndManagerId(NetworkManager, netId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  270. wire := WireManager.Query().SubQuery()
  271. vpc := VpcManager.Query().SubQuery()
  272. return q.Join(wire, sqlchemy.Equals(wire.Field("id"), q.Field("wire_id"))).
  273. Join(vpc, sqlchemy.Equals(vpc.Field("id"), wire.Field("vpc_id"))).
  274. Filter(sqlchemy.Equals(vpc.Field("manager_id"), provider.Id))
  275. })
  276. if err != nil {
  277. log.Errorf("fetch network %s error: %v", netId, err)
  278. } else {
  279. app.NetworkId = network.GetId()
  280. }
  281. }
  282. err := AppManager.TableSpec().Insert(ctx, &app)
  283. if err != nil {
  284. return nil, errors.Wrap(err, "unable to insert app")
  285. }
  286. aes, err := ext.GetEnvironments()
  287. if err != nil {
  288. return &app, errors.Wrap(err, "unable to GetEnvironments")
  289. }
  290. result := app.SyncAppEnvironments(ctx, userCred, provider, aes)
  291. if result.IsError() {
  292. return &app, errors.Wrap(result.AllError(), "unable to SyncAppEnvironments")
  293. }
  294. SyncCloudProject(ctx, userCred, &app, provider.GetOwnerId(), ext, provider)
  295. syncVirtualResourceMetadata(ctx, userCred, &app, ext, false)
  296. db.OpsLog.LogEvent(&app, db.ACT_CREATE, app.GetShortDesc(ctx), userCred)
  297. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  298. Obj: &app,
  299. Action: notifyclient.ActionSyncCreate,
  300. })
  301. return &app, nil
  302. }
  303. func (am *SAppManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
  304. apps, err := am.GetApps(providerId)
  305. if err != nil {
  306. return errors.Wrapf(err, "unable to GetApps of provider id %s", providerId)
  307. }
  308. for i := range apps {
  309. err = apps[i].purge(ctx, userCred)
  310. if err != nil {
  311. return err
  312. }
  313. }
  314. return nil
  315. }
  316. func (a *SApp) GetChangeOwnerCandidateDomainIds() []string {
  317. return nil
  318. }
  319. func (a *SApp) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
  320. aes, err := a.GetAppEnvironments()
  321. if err != nil {
  322. return errors.Wrap(err, "unable to GetAppEnvironments")
  323. }
  324. for i := range aes {
  325. err = aes[i].Delete(ctx, userCred)
  326. if err != nil {
  327. return errors.Wrapf(err, "unable to Delete AppEnvironment %s", aes[i].Id)
  328. }
  329. }
  330. return a.Delete(ctx, userCred)
  331. }
  332. func (a *SApp) syncRemoveCloudApp(ctx context.Context, userCred mcclient.TokenCredential) error {
  333. err := a.purge(ctx, userCred)
  334. if err != nil {
  335. return err
  336. }
  337. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  338. Obj: a,
  339. Action: notifyclient.ActionSyncDelete,
  340. })
  341. return nil
  342. }
  343. func (a *SApp) SyncWithCloudApp(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudApp) error {
  344. diff, err := db.UpdateWithLock(ctx, a, func() error {
  345. a.ExternalId = ext.GetGlobalId()
  346. a.Status = ext.GetStatus()
  347. a.TechStack = ext.GetTechStack()
  348. a.OsType = string(ext.GetOsType())
  349. a.IpAddr = ext.GetIpAddress()
  350. a.Hostname = ext.GetHostname()
  351. a.ServerFarm = ext.GetServerFarm()
  352. a.PublicNetworkAccess = ext.GetPublicNetworkAccess()
  353. if netId := ext.GetNetworkId(); len(netId) > 0 && len(a.NetworkId) == 0 {
  354. network, err := db.FetchByExternalIdAndManagerId(NetworkManager, netId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  355. wire := WireManager.Query().SubQuery()
  356. vpc := VpcManager.Query().SubQuery()
  357. return q.Join(wire, sqlchemy.Equals(wire.Field("id"), q.Field("wire_id"))).
  358. Join(vpc, sqlchemy.Equals(vpc.Field("id"), wire.Field("vpc_id"))).
  359. Filter(sqlchemy.Equals(vpc.Field("manager_id"), provider.Id))
  360. })
  361. if err != nil {
  362. log.Errorf("fetch network %s error: %v", netId, err)
  363. } else {
  364. a.NetworkId = network.GetId()
  365. }
  366. }
  367. return nil
  368. })
  369. if err != nil {
  370. return errors.Wrap(err, "db.Update")
  371. }
  372. aes, err := ext.GetEnvironments()
  373. if err != nil {
  374. return errors.Wrapf(err, "unable to GetAppEnvironments for ICloudApp %s", ext.GetGlobalId())
  375. }
  376. result := a.SyncAppEnvironments(ctx, userCred, provider, aes)
  377. if result.IsError() {
  378. return result.AllError()
  379. }
  380. if len(diff) > 0 {
  381. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  382. Obj: a,
  383. Action: notifyclient.ActionSyncUpdate,
  384. })
  385. }
  386. if account, _ := provider.GetCloudaccount(); account != nil {
  387. syncVirtualResourceMetadata(ctx, userCred, a, ext, account.ReadOnly)
  388. }
  389. return nil
  390. }
  391. func (am *SAppManager) FetchCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, objs []interface{}, fields stringutils2.SSortedStrings, isList bool) []api.AppDetails {
  392. rows := make([]api.AppDetails, len(objs))
  393. virtRows := am.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  394. manRows := am.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  395. regRows := am.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  396. netRows := am.SNetworkResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  397. for i := range rows {
  398. rows[i].VirtualResourceDetails = virtRows[i]
  399. rows[i].ManagedResourceInfo = manRows[i]
  400. rows[i].CloudregionResourceInfo = regRows[i]
  401. rows[i].Network = netRows[i].Network
  402. rows[i].VpcId = netRows[i].VpcId
  403. rows[i].Vpc = netRows[i].Vpc
  404. }
  405. return rows
  406. }
  407. func (a *SApp) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  408. var openTask = true
  409. count, err := taskman.TaskManager.QueryTasksOfObject(a, time.Now().Add(-3*time.Minute), &openTask).CountWithError()
  410. if err != nil {
  411. return nil, err
  412. }
  413. if count > 0 {
  414. return nil, httperrors.NewBadRequestError("WebApp has %d task active, can't sync status", count)
  415. }
  416. return nil, StartResourceSyncStatusTask(ctx, userCred, a, "AppSyncstatusTask", "")
  417. }
  418. func (a *SApp) GetIRegion(ctx context.Context) (cloudprovider.ICloudRegion, error) {
  419. region, err := a.SCloudregionResourceBase.GetRegion()
  420. if err != nil {
  421. return nil, errors.Wrap(err, "GetRegion")
  422. }
  423. provider, err := a.GetDriver(ctx)
  424. if err != nil {
  425. return nil, errors.Wrap(err, "GetDriver")
  426. }
  427. return provider.GetIRegionById(region.GetExternalId())
  428. }
  429. func (a *SApp) GetIApp(ctx context.Context) (cloudprovider.ICloudApp, error) {
  430. if len(a.ExternalId) == 0 {
  431. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
  432. }
  433. iRegion, err := a.GetIRegion(ctx)
  434. if err != nil {
  435. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "GetIRegion")
  436. }
  437. return iRegion.GetICloudAppById(a.ExternalId)
  438. }
  439. func (self *SApp) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.MongoDBRemoteUpdateInput) (jsonutils.JSONObject, error) {
  440. err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "")
  441. if err != nil {
  442. return nil, errors.Wrap(err, "StartRemoteUpdateTask")
  443. }
  444. return nil, nil
  445. }
  446. func (self *SApp) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error {
  447. data := jsonutils.NewDict()
  448. data.Add(jsonutils.NewBool(replaceTags), "replace_tags")
  449. task, err := taskman.TaskManager.NewTask(ctx, "AppRemoteUpdateTask", self, userCred, data, parentTaskId, "", nil)
  450. if err != nil {
  451. return errors.Wrap(err, "NewTask")
  452. }
  453. self.SetStatus(ctx, userCred, apis.STATUS_UPDATE_TAGS, "StartRemoteUpdateTask")
  454. return task.ScheduleRun(nil)
  455. }
  456. func (self *SApp) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
  457. if len(self.ExternalId) == 0 || options.Options.KeepTagLocalization {
  458. return
  459. }
  460. if account := self.GetCloudaccount(); account != nil && account.ReadOnly {
  461. return
  462. }
  463. err := self.StartRemoteUpdateTask(ctx, userCred, true, "")
  464. if err != nil {
  465. log.Errorf("StartRemoteUpdateTask fail: %s", err)
  466. }
  467. }
  468. // 获取混合连接
  469. func (self *SApp) GetDetailsHybirdConnections(ctx context.Context, userCred mcclient.TokenCredential, input jsonutils.JSONObject) (*api.AppHybirdConnectionOutput, error) {
  470. iApp, err := self.GetIApp(ctx)
  471. if err != nil {
  472. return nil, err
  473. }
  474. ret := &api.AppHybirdConnectionOutput{
  475. Data: []api.AppHybirdConnection{},
  476. }
  477. connections, err := iApp.GetHybirdConnections()
  478. if err != nil {
  479. return nil, err
  480. }
  481. for _, conn := range connections {
  482. ret.Data = append(ret.Data, api.AppHybirdConnection{
  483. Id: conn.GetGlobalId(),
  484. Name: conn.GetName(),
  485. Hostname: conn.GetHostname(),
  486. Namespace: conn.GetNamespace(),
  487. Port: conn.GetPort(),
  488. })
  489. }
  490. return ret, nil
  491. }
  492. // 获取备份列表
  493. func (self *SApp) GetDetailsBackups(ctx context.Context, userCred mcclient.TokenCredential, input jsonutils.JSONObject) (*api.AppBackupOutput, error) {
  494. iApp, err := self.GetIApp(ctx)
  495. if err != nil {
  496. return nil, err
  497. }
  498. ret := &api.AppBackupOutput{
  499. Data: []api.AppBackup{},
  500. }
  501. backups, err := iApp.GetBackups()
  502. if err != nil {
  503. return nil, err
  504. }
  505. for _, backup := range backups {
  506. ret.Data = append(ret.Data, api.AppBackup{
  507. Id: backup.GetGlobalId(),
  508. Name: backup.GetName(),
  509. Type: backup.GetType(),
  510. })
  511. }
  512. opts := iApp.GetBackupConfig()
  513. jsonutils.Update(&ret.BackupConfig, opts)
  514. return ret, nil
  515. }
  516. // 获取证书列表
  517. func (self *SApp) GetDetailsCertificates(ctx context.Context, userCred mcclient.TokenCredential, input jsonutils.JSONObject) (*api.AppCertificateOutput, error) {
  518. iApp, err := self.GetIApp(ctx)
  519. if err != nil {
  520. return nil, err
  521. }
  522. ret := &api.AppCertificateOutput{
  523. Data: []api.AppCertificate{},
  524. }
  525. certs, err := iApp.GetCertificates()
  526. if err != nil {
  527. return nil, err
  528. }
  529. for _, cert := range certs {
  530. ret.Data = append(ret.Data, api.AppCertificate{
  531. Id: cert.GetGlobalId(),
  532. Name: cert.GetName(),
  533. SubjectName: cert.GetSubjectName(),
  534. Issuer: cert.GetIssuer(),
  535. IssueDate: cert.GetIssueDate(),
  536. Thumbprint: cert.GetThumbprint(),
  537. ExpireTime: cert.GetExpireTime(),
  538. })
  539. }
  540. return ret, nil
  541. }
  542. // 获取自定义域列表
  543. func (self *SApp) GetDetailsCustomDomains(ctx context.Context, userCred mcclient.TokenCredential, input jsonutils.JSONObject) (*api.AppDomainOutput, error) {
  544. iApp, err := self.GetIApp(ctx)
  545. if err != nil {
  546. return nil, err
  547. }
  548. ret := &api.AppDomainOutput{
  549. Data: []api.AppDomain{},
  550. }
  551. domains, err := iApp.GetDomains()
  552. if err != nil {
  553. return nil, err
  554. }
  555. for _, domain := range domains {
  556. ret.Data = append(ret.Data, api.AppDomain{
  557. Id: domain.GetGlobalId(),
  558. Name: domain.GetName(),
  559. Status: domain.GetStatus(),
  560. SslState: domain.GetSslState(),
  561. })
  562. }
  563. return ret, nil
  564. }