tags.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package logic
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "sort"
  6. "sync"
  7. "github.com/gravitl/netmaker/database"
  8. "github.com/gravitl/netmaker/models"
  9. )
  10. var tagMutex = &sync.RWMutex{}
  11. // GetTag - fetches tag info
  12. func GetTag(tagID models.TagID) (models.Tag, error) {
  13. data, err := database.FetchRecord(database.TAG_TABLE_NAME, tagID.String())
  14. if err != nil {
  15. return models.Tag{}, err
  16. }
  17. tag := models.Tag{}
  18. err = json.Unmarshal([]byte(data), &tag)
  19. if err != nil {
  20. return tag, err
  21. }
  22. return tag, nil
  23. }
  24. // InsertTag - creates new tag
  25. func InsertTag(tag models.Tag) error {
  26. _, err := database.FetchRecord(database.TAG_TABLE_NAME, tag.ID.String())
  27. if err == nil {
  28. return fmt.Errorf("tag `%s` exists already", tag.ID)
  29. }
  30. d, err := json.Marshal(tag)
  31. if err != nil {
  32. return err
  33. }
  34. return database.Insert(tag.ID.String(), string(d), database.TAG_TABLE_NAME)
  35. }
  36. // DeleteTag - delete tag, will also untag hosts
  37. func DeleteTag(tagID models.TagID) error {
  38. // cleanUp tags on hosts
  39. tag, err := GetTag(tagID)
  40. if err != nil {
  41. return err
  42. }
  43. nodes, err := GetNetworkNodes(tag.Network.String())
  44. if err != nil {
  45. return err
  46. }
  47. for _, nodeI := range nodes {
  48. nodeI := nodeI
  49. if _, ok := nodeI.Tags[tagID]; ok {
  50. delete(nodeI.Tags, tagID)
  51. UpsertNode(&nodeI)
  52. }
  53. }
  54. return database.DeleteRecord(database.TAG_TABLE_NAME, tagID.String())
  55. }
  56. // ListTagsWithHosts - lists all tags with tagged hosts
  57. func ListTagsWithNodes(netID models.NetworkID) ([]models.TagListResp, error) {
  58. tagMutex.RLock()
  59. defer tagMutex.RUnlock()
  60. tags, err := ListNetworkTags(netID)
  61. if err != nil {
  62. return []models.TagListResp{}, err
  63. }
  64. tagsNodeMap := GetTagMapWithNodes(netID)
  65. resp := []models.TagListResp{}
  66. for _, tagI := range tags {
  67. tagRespI := models.TagListResp{
  68. Tag: tagI,
  69. UsedByCnt: len(tagsNodeMap[tagI.ID]),
  70. TaggedNodes: tagsNodeMap[tagI.ID],
  71. }
  72. resp = append(resp, tagRespI)
  73. }
  74. return resp, nil
  75. }
  76. // ListTags - lists all tags from DB
  77. func ListTags() ([]models.Tag, error) {
  78. data, err := database.FetchRecords(database.TAG_TABLE_NAME)
  79. if err != nil && !database.IsEmptyRecord(err) {
  80. return []models.Tag{}, err
  81. }
  82. tags := []models.Tag{}
  83. for _, dataI := range data {
  84. tag := models.Tag{}
  85. err := json.Unmarshal([]byte(dataI), &tag)
  86. if err != nil {
  87. continue
  88. }
  89. tags = append(tags, tag)
  90. }
  91. return tags, nil
  92. }
  93. // ListTags - lists all tags from DB
  94. func ListNetworkTags(netID models.NetworkID) ([]models.Tag, error) {
  95. data, err := database.FetchRecords(database.TAG_TABLE_NAME)
  96. if err != nil && !database.IsEmptyRecord(err) {
  97. return []models.Tag{}, err
  98. }
  99. tags := []models.Tag{}
  100. for _, dataI := range data {
  101. tag := models.Tag{}
  102. err := json.Unmarshal([]byte(dataI), &tag)
  103. if err != nil {
  104. continue
  105. }
  106. if tag.Network == netID {
  107. tags = append(tags, tag)
  108. }
  109. }
  110. return tags, nil
  111. }
  112. // UpdateTag - updates and syncs hosts with tag update
  113. func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
  114. tagMutex.Lock()
  115. defer tagMutex.Unlock()
  116. tagNodesMap := GetNodesWithTag(req.ID)
  117. for _, nodeID := range req.TaggedNodes {
  118. node, err := GetNodeByID(nodeID)
  119. if err != nil {
  120. continue
  121. }
  122. if _, ok := tagNodesMap[node.ID.String()]; !ok {
  123. if node.Tags == nil {
  124. node.Tags = make(map[models.TagID]struct{})
  125. }
  126. if newID != "" {
  127. node.Tags[newID] = struct{}{}
  128. } else {
  129. node.Tags[req.ID] = struct{}{}
  130. }
  131. UpsertNode(&node)
  132. } else {
  133. if newID != "" {
  134. delete(node.Tags, req.ID)
  135. node.Tags[newID] = struct{}{}
  136. UpsertNode(&node)
  137. }
  138. delete(tagNodesMap, node.ID.String())
  139. }
  140. }
  141. for _, deletedTaggedNode := range tagNodesMap {
  142. deletedTaggedHost := deletedTaggedNode
  143. delete(deletedTaggedHost.Tags, req.ID)
  144. UpsertNode(&deletedTaggedHost)
  145. }
  146. go func(req models.UpdateTagReq) {
  147. if newID != "" {
  148. tagNodesMap = GetNodesWithTag(req.ID)
  149. for _, nodeI := range tagNodesMap {
  150. nodeI := nodeI
  151. delete(nodeI.Tags, req.ID)
  152. nodeI.Tags[newID] = struct{}{}
  153. UpsertNode(&nodeI)
  154. }
  155. }
  156. }(req)
  157. }
  158. // SortTagEntrys - Sorts slice of Tag entries by their id
  159. func SortTagEntrys(tags []models.TagListResp) {
  160. sort.Slice(tags, func(i, j int) bool {
  161. return tags[i].ID < tags[j].ID
  162. })
  163. }