project_mappings.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 compute
  15. import (
  16. "reflect"
  17. "strings"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/pkg/gotypes"
  20. "yunion.io/x/pkg/utils"
  21. "yunion.io/x/onecloud/pkg/apis"
  22. "yunion.io/x/onecloud/pkg/httperrors"
  23. "yunion.io/x/onecloud/pkg/util/tagutils"
  24. )
  25. const (
  26. PROJECT_MAPPING_STATUS_AVAILABLE = "available"
  27. MAPPING_CONDITION_AND = "and"
  28. MAPPING_CONDITION_OR = "or"
  29. )
  30. type ProjectMappingRuleInfo struct {
  31. // 标签列表, 不可为空
  32. Tags tagutils.TTagSet `json:"tags"`
  33. // 条件表达式
  34. // enmu: and, or
  35. // default: and
  36. Condition string `json:"condition"`
  37. // 是否自动根据标签值创建项目, 仅标签列表中有且仅有一个没有value的key时支持
  38. AutoCreateProject bool `json:"auto_create_project"`
  39. // 符合条件时,资源放置的项目id, 此参数和auto_create_project互斥
  40. ProjectId string `json:"project_id"`
  41. // 只读信息
  42. // swagger:ignore
  43. Project string `json:"project"`
  44. // swagger:ignore
  45. DomainId string `json:"domain_id"`
  46. // 只读信息
  47. // swagger:ignore
  48. Domain string `json:"domain"`
  49. }
  50. func (rule ProjectMappingRuleInfo) IsWide() bool {
  51. for _, tag := range rule.Tags {
  52. if len(tag.Value) == 0 {
  53. return true
  54. }
  55. }
  56. return false
  57. }
  58. type MappingRules []ProjectMappingRuleInfo
  59. func (rules MappingRules) Rules() MappingRules {
  60. normal := []ProjectMappingRuleInfo{}
  61. wide := []ProjectMappingRuleInfo{}
  62. for _, rule := range rules {
  63. if rule.IsWide() {
  64. wide = append(wide, rule)
  65. } else {
  66. normal = append(normal, rule)
  67. }
  68. }
  69. return append(normal, wide...)
  70. }
  71. func (rule *ProjectMappingRuleInfo) Validate() error {
  72. if len(rule.Tags) == 0 {
  73. return httperrors.NewInputParameterError("missing tags")
  74. }
  75. if len(rule.Condition) == 0 {
  76. rule.Condition = MAPPING_CONDITION_AND
  77. }
  78. if !utils.IsInStringArray(rule.Condition, []string{MAPPING_CONDITION_AND, MAPPING_CONDITION_OR}) {
  79. return httperrors.NewInputParameterError("invalid condition")
  80. }
  81. emptyValueTags := 0
  82. for _, tag := range rule.Tags {
  83. if len(tag.Key) == 0 {
  84. return httperrors.NewInputParameterError("missing tag key for")
  85. }
  86. if len(tag.Value) == 0 {
  87. emptyValueTags++
  88. }
  89. }
  90. if emptyValueTags != 1 && rule.AutoCreateProject {
  91. return httperrors.NewInputParameterError("not support auto_create_project")
  92. }
  93. if !rule.AutoCreateProject && len(rule.ProjectId) == 0 && len(rule.Project) == 0 {
  94. return httperrors.NewInputParameterError("missing project_id")
  95. }
  96. return nil
  97. }
  98. // return domainId, projectId, newProj, isMatch
  99. func (self *ProjectMappingRuleInfo) IsMatchTags(_extTags map[string]string) (string, string, string, bool) {
  100. newProj := ""
  101. extTags := map[string]string{}
  102. for k, v := range _extTags {
  103. extTags[strings.ToUpper(k)] = v
  104. }
  105. switch self.Condition {
  106. case MAPPING_CONDITION_AND:
  107. for _, tag := range self.Tags {
  108. extTag, ok := extTags[strings.ToUpper(tag.Key)]
  109. if !ok || (len(tag.Value) > 0 && tag.Value != extTag) {
  110. return "", "", "", false
  111. }
  112. if self.AutoCreateProject && len(tag.Value) == 0 && len(extTag) > 0 {
  113. newProj = extTag
  114. }
  115. }
  116. if !self.AutoCreateProject && len(self.ProjectId) == 0 && len(self.Project) > 0 {
  117. newProj = self.Project
  118. }
  119. return self.DomainId, self.ProjectId, newProj, true
  120. case MAPPING_CONDITION_OR:
  121. for _, tag := range self.Tags {
  122. extTag, ok := extTags[strings.ToUpper(tag.Key)]
  123. if ok && (len(tag.Value) == 0 || tag.Value == extTag) {
  124. if self.AutoCreateProject && len(tag.Value) == 0 && len(extTag) > 0 {
  125. return "", "", extTag, true
  126. } else if !self.AutoCreateProject && len(self.ProjectId) == 0 && len(self.Project) > 0 {
  127. return self.DomainId, self.ProjectId, self.Project, true
  128. } else {
  129. return self.DomainId, self.ProjectId, "", true
  130. }
  131. }
  132. }
  133. }
  134. return "", "", "", false
  135. }
  136. func (rules MappingRules) Validate() error {
  137. for i := range rules {
  138. err := rules[i].Validate()
  139. if err != nil {
  140. return err
  141. }
  142. }
  143. return nil
  144. }
  145. type ProjectMappingRuleInfoDetails struct {
  146. ProjectMappingRuleInfo
  147. Project string `json:"project"`
  148. TenantId string `json:"tenant_id"`
  149. Tenant string `json:"tenant"`
  150. Domain string `json:"domain"`
  151. }
  152. type SProjectMappingAccount struct {
  153. Id string `json:"id"`
  154. Name string `json:"name"`
  155. }
  156. type ProjectMappingDetails struct {
  157. SProjectMapping
  158. apis.EnabledStatusInfrasResourceBaseDetails
  159. Rules []ProjectMappingRuleInfoDetails `json:"rules"`
  160. // 所绑定的云账号列表
  161. Accounts []SProjectMappingAccount `json:"accounts"`
  162. // 所绑定的云订阅列表
  163. Managers []SProjectMappingAccount `json:"managers"`
  164. }
  165. type ProjectMappingCreateInput struct {
  166. apis.EnabledStatusInfrasResourceBaseCreateInput
  167. // 根据标签key匹配的规则会默认排到列表最后
  168. Rules MappingRules
  169. }
  170. type ProjectMappingListInput struct {
  171. apis.EnabledStatusInfrasResourceBaseListInput
  172. }
  173. type ProjectMappingResourceInfo struct {
  174. ProjectMapping string `json:"project_mapping"`
  175. }
  176. type ProjectMappingUpdateInput struct {
  177. apis.EnabledStatusInfrasResourceBaseUpdateInput
  178. // 根据标签key匹配的规则会默认排到列表最后
  179. Rules MappingRules
  180. }
  181. type ProjectMappingFilterListInput struct {
  182. ProjectMappingId string `json:"project_mapping_id"`
  183. OrderByProjectMapping string `json:"order_by_project_mapping"`
  184. }
  185. func (self MappingRules) String() string {
  186. return jsonutils.Marshal(self).String()
  187. }
  188. func (self MappingRules) IsZero() bool {
  189. if len(self) == 0 {
  190. return true
  191. }
  192. return false
  193. }
  194. func init() {
  195. gotypes.RegisterSerializable(reflect.TypeOf(&MappingRules{}), func() gotypes.ISerializable {
  196. return &MappingRules{}
  197. })
  198. }