github.com/Axway/agent-sdk@v1.1.101/pkg/apic/apiserver/models/api/v1/resourcemeta.go (about) 1 package v1 2 3 import ( 4 "encoding/json" 5 "strings" 6 ) 7 8 const ( 9 ResourceDeleting = "DELETING" 10 Inactive = "inactive" 11 Active = "active" 12 ) 13 14 // Meta interface for API Server resource metadata 15 type Meta interface { 16 GetName() string 17 GetGroupVersionKind() GroupVersionKind 18 GetMetadata() Metadata 19 SetScopeName(string) 20 GetAttributes() map[string]string 21 SetAttributes(map[string]string) 22 GetTags() []string 23 SetTags([]string) 24 GetSubResource(key string) interface{} 25 SetSubResource(key string, resource interface{}) 26 GetReferenceByGVK(GroupVersionKind) Reference 27 } 28 29 // ResourceMeta metadata for a ResourceInstance 30 type ResourceMeta struct { 31 GroupVersionKind 32 Name string `json:"name,omitempty"` 33 Title string `json:"title,omitempty"` 34 // Metadata the metadata for the resource 35 Metadata Metadata `json:"metadata,omitempty"` 36 // Custom attributes for a resource. 37 Attributes map[string]string `json:"attributes"` 38 // List of tags. 39 Tags []string `json:"tags"` 40 // Finalizer on the API server resource 41 Finalizers []Finalizer `json:"finalizers"` 42 // SubResources contains all of the unique sub resources that may be added to a resource 43 SubResources map[string]interface{} `json:"-"` 44 } 45 46 // GetName gets the name of a resource 47 func (rm *ResourceMeta) GetName() string { 48 if rm == nil { 49 return "" 50 } 51 52 return rm.Name 53 } 54 55 // SetName sets the name of a resource 56 func (rm *ResourceMeta) SetName(name string) { 57 rm.Name = name 58 } 59 60 // SetScopeName sets the name of a resource 61 func (rm *ResourceMeta) SetScopeName(name string) { 62 rm.Metadata.Scope.Name = name 63 } 64 65 // GetMetadata gets the resource metadata 66 func (rm *ResourceMeta) GetMetadata() Metadata { 67 if rm == nil { 68 return Metadata{} 69 } 70 71 return rm.Metadata 72 } 73 74 // GetSelfLink gets the resource metadata selflink 75 func (rm *ResourceMeta) GetSelfLink() string { 76 if rm == nil { 77 return "" 78 } 79 80 // return the self lnk if we have it 81 if rm.GetMetadata().SelfLink != "" { 82 return rm.Metadata.SelfLink 83 } 84 85 if kindLink := rm.GetKindLink(); kindLink != "" { 86 return strings.Join([]string{kindLink, rm.Name}, "/") 87 } 88 return "" 89 } 90 91 // GetKindLink gets the link to resource kind 92 func (rm *ResourceMeta) GetKindLink() string { 93 if rm == nil { 94 return "" 95 } 96 97 // can't continue if group kind or version are blank 98 if rm.Group == "" || rm.Kind == "" || rm.APIVersion == "" { 99 return "" 100 } 101 102 // empty string to prepend with / 103 pathItems := []string{"", rm.Group, rm.APIVersion} 104 105 plural, _ := GetPluralFromKind(rm.Kind) 106 107 if rm.Metadata.Scope.Kind == "" { 108 scope, ok := GetScope(rm.GetGroupVersionKind().GroupKind) 109 if ok && scope != "" { 110 scopePlural, _ := GetPluralFromKind(scope) 111 pathItems = append(pathItems, []string{scopePlural, rm.Metadata.Scope.Name}...) 112 } 113 } else { 114 scopePlural, _ := GetPluralFromKind(rm.Metadata.Scope.Kind) 115 pathItems = append(pathItems, []string{scopePlural, rm.Metadata.Scope.Name}...) 116 } 117 118 pathItems = append(pathItems, plural) 119 120 return strings.Join(pathItems, "/") 121 } 122 123 // GetGroupVersionKind gets the group, version, and kind of the resource 124 func (rm *ResourceMeta) GetGroupVersionKind() GroupVersionKind { 125 if rm == nil { 126 return GroupVersionKind{} 127 } 128 129 return rm.GroupVersionKind 130 } 131 132 // GetAttributes gets the attributes of a resource 133 func (rm *ResourceMeta) GetAttributes() map[string]string { 134 if rm == nil { 135 return map[string]string{} 136 } 137 138 return rm.Attributes 139 } 140 141 // SetAttributes sets the attributes of a resource 142 func (rm *ResourceMeta) SetAttributes(attrs map[string]string) { 143 if rm == nil { 144 return 145 } 146 147 rm.Attributes = attrs 148 } 149 150 // GetTags gets the tags of the resource 151 func (rm *ResourceMeta) GetTags() []string { 152 if rm == nil { 153 return []string{} 154 } 155 156 return rm.Tags 157 } 158 159 // SetTags adds tags to the resource 160 func (rm *ResourceMeta) SetTags(tags []string) { 161 if rm == nil { 162 return 163 } 164 165 rm.Tags = tags 166 } 167 168 // GetSubResource get a sub resource by name 169 func (rm *ResourceMeta) GetSubResource(key string) interface{} { 170 if rm == nil || rm.SubResources == nil { 171 return nil 172 } 173 return rm.SubResources[key] 174 } 175 176 // SetSubResource saves a value to a sub resource by name and overrides the current value. 177 // To update a SubResource first call GetSubResource and modify it, then save it. 178 func (rm *ResourceMeta) SetSubResource(name string, value interface{}) { 179 if rm == nil { 180 return 181 } 182 183 if rm.SubResources == nil { 184 rm.SubResources = make(map[string]interface{}) 185 } 186 rm.SubResources[name] = value 187 } 188 189 // GetReferenceByGVK returns the first found reference that matches the GroupKind argument. 190 func (rm *ResourceMeta) GetReferenceByGVK(gvk GroupVersionKind) Reference { 191 for _, ref := range rm.Metadata.References { 192 if ref.Group == gvk.Group && ref.Kind == gvk.Kind { 193 return ref 194 } 195 } 196 return Reference{} 197 } 198 199 // MarshalJSON marshals the ResourceMeta to properly set the SubResources 200 func (rm *ResourceMeta) MarshalJSON() ([]byte, error) { 201 rawSubs := map[string]interface{}{} 202 subResources := rm.SubResources 203 204 for key, value := range subResources { 205 rawSubs[key] = value 206 } 207 208 // create an alias for *ResourceMeta to avoid a circular reference while marshalling. 209 type Alias ResourceMeta 210 v := &struct{ *Alias }{ 211 Alias: (*Alias)(rm), 212 } 213 214 metaBts, err := json.Marshal(v) 215 if err != nil { 216 return metaBts, err 217 } 218 219 rawMeta := map[string]interface{}{} 220 err = json.Unmarshal(metaBts, &rawMeta) 221 if err != nil { 222 return metaBts, nil 223 } 224 225 for k, v := range rawSubs { 226 if v != nil { 227 rawMeta[k] = v 228 } 229 } 230 231 return json.Marshal(rawMeta) 232 } 233 234 // UnmarshalJSON unmarshalls the ResourceMeta to properly set the SubResources 235 func (rm *ResourceMeta) UnmarshalJSON(data []byte) error { 236 type Alias ResourceMeta 237 // create an alias for *ResourceMeta to avoid a circular reference while unmarshalling. 238 v := &struct{ *Alias }{ 239 Alias: (*Alias)(rm), 240 } 241 242 // unmarshal data to the alias. The SubResources will not be unmarshalled since they are not defined. 243 err := json.Unmarshal(data, v) 244 if err != nil { 245 return err 246 } 247 248 bts, err := json.Marshal(v) 249 if err != nil { 250 return err 251 } 252 253 // all contains all the defined keys of ResourceMeta. The keys will be used to identify the values 254 // that do not belong in the SubResources map. 255 all := map[string]interface{}{} 256 err = json.Unmarshal(bts, &all) 257 if err != nil { 258 return err 259 } 260 261 // unmarshal data again to a map[string]interface{} to get all the values and the unique sub resources 262 rawSubs := map[string]interface{}{} 263 err = json.Unmarshal(data, &rawSubs) 264 if err != nil { 265 return err 266 } 267 268 // all contains all keys but the sub resources. rawSubs contains all keys, but should only contain the subresource keys. 269 // delete the keys from subs that are not sub resource keys 270 for k := range all { 271 delete(rawSubs, k) 272 } 273 delete(rawSubs, "owner") 274 delete(rawSubs, "spec") 275 276 if len(rawSubs) > 0 && rm.SubResources == nil { 277 rm.SubResources = make(map[string]interface{}) 278 } 279 280 for k, v := range rawSubs { 281 if v != nil { 282 rm.SubResources[k] = v 283 } 284 } 285 286 return nil 287 }