github.com/vmware/govmomi@v0.51.0/vapi/vcenter/consumptiondomains/simulator/simulator.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package simulator 6 7 import ( 8 "net/http" 9 "net/url" 10 "strings" 11 12 "github.com/vmware/govmomi/simulator" 13 vapi "github.com/vmware/govmomi/vapi/simulator" 14 "github.com/vmware/govmomi/vapi/vcenter/consumptiondomains/zones" 15 ) 16 17 const ( 18 zonesPath = "/api/vcenter/consumption-domains/zones" 19 associationsPath = "/api/vcenter/consumption-domains/zones/cluster" 20 ) 21 22 func init() { 23 simulator.RegisterEndpoint(func(s *simulator.Service, r *simulator.Registry) { 24 New(s.Listen).Register(s, r) 25 }) 26 } 27 28 // ZoneData Helper type to store simulated entries 29 type ZoneData struct { 30 Name string 31 Id string 32 Description string 33 Associations []string 34 } 35 36 // Handler implements the Cluster Modules API simulator 37 type Handler struct { 38 URL *url.URL 39 data map[string]*ZoneData 40 } 41 42 // New creates a Handler instance 43 func New(u *url.URL) *Handler { 44 return &Handler{ 45 URL: u, 46 data: make(map[string]*ZoneData), 47 } 48 } 49 50 // Register Consumption Domains API paths with the vapi simulator's http.ServeMux 51 func (h *Handler) Register(s *simulator.Service, r *simulator.Registry) { 52 if r.IsVPX() { 53 s.HandleFunc(zonesPath, h.zones) 54 s.HandleFunc(zonesPath+"/", h.zones) 55 s.HandleFunc(associationsPath, h.associations) 56 s.HandleFunc(associationsPath+"/", h.associations) 57 } 58 } 59 60 func (h *Handler) zones(w http.ResponseWriter, r *http.Request) { 61 subpath := r.URL.Path[len(zonesPath):] 62 zoneId := strings.Replace(subpath, "/", "", -1) 63 64 switch r.Method { 65 case http.MethodGet: 66 if len(subpath) > 0 { 67 if d, ok := h.data[zoneId]; ok { 68 vapi.StatusOK(w, zones.ZoneInfo{Description: d.Description}) 69 return 70 } 71 vapi.ApiErrorNotFound(w) 72 } else { 73 items := make([]zones.ListItem, len(h.data)) 74 i := 0 75 for _, d := range h.data { 76 item := zones.ListItem{ 77 Zone: d.Name, 78 Info: zones.ZoneInfo{ 79 Description: d.Description, 80 }, 81 } 82 items[i] = item 83 i++ 84 } 85 86 result := zones.ListResult{Items: items} 87 vapi.StatusOK(w, result) 88 } 89 case http.MethodPost: 90 var spec zones.CreateSpec 91 if !vapi.Decode(r, w, &spec) { 92 vapi.ApiErrorGeneral(w) 93 return 94 } 95 96 newZone := ZoneData{ 97 Name: spec.Zone, 98 Description: spec.Description, 99 Id: spec.Zone, 100 Associations: make([]string, 0), 101 } 102 h.data[newZone.Id] = &newZone 103 104 vapi.StatusOK(w, newZone.Id) 105 case http.MethodDelete: 106 if _, ok := h.data[zoneId]; ok { 107 delete(h.data, zoneId) 108 vapi.StatusOK(w) 109 return 110 } 111 vapi.ApiErrorNotFound(w) 112 } 113 } 114 115 func (h *Handler) associations(w http.ResponseWriter, r *http.Request) { 116 subpath := r.URL.Path[len(associationsPath)+1:] 117 pathParts := strings.Split(subpath, "/") 118 119 if len(pathParts) != 2 || pathParts[1] != "associations" { 120 vapi.ApiErrorNotFound(w) 121 return 122 } 123 124 zoneId := pathParts[0] 125 126 switch r.Method { 127 case http.MethodGet: 128 if d, ok := h.data[zoneId]; ok { 129 vapi.StatusOK(w, d.Associations) 130 return 131 } 132 case http.MethodPost: 133 action := r.URL.Query().Get("action") 134 135 var clusterIds []string 136 if !vapi.Decode(r, w, &clusterIds) { 137 vapi.ApiErrorGeneral(w) 138 return 139 } 140 141 switch action { 142 case "add": 143 if d, ok := h.data[zoneId]; ok { 144 associations := append(d.Associations, clusterIds...) 145 d.Associations = associations 146 res := make(map[string]any) 147 res["success"] = true 148 vapi.StatusOK(w, res) 149 return 150 } 151 vapi.ApiErrorNotFound(w) 152 case "remove": 153 if d, ok := h.data[zoneId]; ok { 154 associations := make([]string, 0) 155 156 for _, a := range d.Associations { 157 found := false 158 for _, id := range clusterIds { 159 if a == id { 160 found = true 161 } 162 } 163 164 if !found { 165 associations = append(associations, a) 166 } 167 } 168 169 d.Associations = associations 170 171 vapi.StatusOK(w, nil) 172 return 173 } 174 vapi.ApiErrorNotFound(w) 175 default: 176 vapi.ApiErrorGeneral(w) 177 } 178 } 179 }