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