github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/catalogitem.go (about) 1 /* 2 * Copyright 2019 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. 3 */ 4 5 package govcd 6 7 import ( 8 "fmt" 9 "net/http" 10 "net/url" 11 12 "github.com/vmware/go-vcloud-director/v2/types/v56" 13 "github.com/vmware/go-vcloud-director/v2/util" 14 ) 15 16 type CatalogItem struct { 17 CatalogItem *types.CatalogItem 18 client *Client 19 } 20 21 func NewCatalogItem(cli *Client) *CatalogItem { 22 return &CatalogItem{ 23 CatalogItem: new(types.CatalogItem), 24 client: cli, 25 } 26 } 27 28 func (catalogItem *CatalogItem) GetVAppTemplate() (VAppTemplate, error) { 29 30 cat := NewVAppTemplate(catalogItem.client) 31 32 _, err := catalogItem.client.ExecuteRequest(catalogItem.CatalogItem.Entity.HREF, http.MethodGet, 33 "", "error retrieving vApp template: %s", nil, cat.VAppTemplate) 34 35 // The request was successful 36 return *cat, err 37 38 } 39 40 // Delete deletes the Catalog Item, returning an error if the vCD call fails. 41 // Link to API call: https://code.vmware.com/apis/220/vcloud#/doc/doc/operations/DELETE-CatalogItem.html 42 func (catalogItem *CatalogItem) Delete() error { 43 util.Logger.Printf("[TRACE] Deleting catalog item: %#v", catalogItem.CatalogItem) 44 catalogItemHREF := catalogItem.client.VCDHREF 45 catalogItemHREF.Path += "/catalogItem/" + catalogItem.CatalogItem.ID[23:] 46 47 util.Logger.Printf("[TRACE] Url for deleting catalog item: %#v and name: %s", catalogItemHREF, catalogItem.CatalogItem.Name) 48 49 return catalogItem.client.ExecuteRequestWithoutResponse(catalogItemHREF.String(), http.MethodDelete, 50 "", "error deleting Catalog item: %s", nil) 51 } 52 53 // queryCatalogItemList returns a list of Catalog Item for the given parent 54 func queryCatalogItemList(client *Client, parentField, parentValue string) ([]*types.QueryResultCatalogItemType, error) { 55 56 catalogItemType := types.QtCatalogItem 57 if client.IsSysAdmin { 58 catalogItemType = types.QtAdminCatalogItem 59 } 60 61 filterText := fmt.Sprintf("%s==%s", parentField, url.QueryEscape(parentValue)) 62 63 results, err := client.cumulativeQuery(catalogItemType, nil, map[string]string{ 64 "type": catalogItemType, 65 "filter": filterText, 66 }) 67 if err != nil { 68 return nil, fmt.Errorf("error querying catalog items %s", err) 69 } 70 71 if client.IsSysAdmin { 72 return results.Results.AdminCatalogItemRecord, nil 73 } else { 74 return results.Results.CatalogItemRecord, nil 75 } 76 } 77 78 // QueryCatalogItemList returns a list of Catalog Item for the given catalog 79 func (catalog *Catalog) QueryCatalogItemList() ([]*types.QueryResultCatalogItemType, error) { 80 return queryCatalogItemList(catalog.client, "catalog", catalog.Catalog.ID) 81 } 82 83 // QueryCatalogItemList returns a list of Catalog Item for the given VDC 84 func (vdc *Vdc) QueryCatalogItemList() ([]*types.QueryResultCatalogItemType, error) { 85 return queryCatalogItemList(vdc.client, "vdc", vdc.Vdc.ID) 86 } 87 88 // QueryCatalogItemList returns a list of Catalog Item for the given Admin VDC 89 func (vdc *AdminVdc) QueryCatalogItemList() ([]*types.QueryResultCatalogItemType, error) { 90 return queryCatalogItemList(vdc.client, "vdc", vdc.AdminVdc.ID) 91 } 92 93 // queryVappTemplateListWithParentField returns a list of vApp templates for the given parent 94 func queryVappTemplateListWithParentField(client *Client, parentField, parentValue string) ([]*types.QueryResultVappTemplateType, error) { 95 return queryVappTemplateListWithFilter(client, map[string]string{ 96 parentField: parentValue, 97 }) 98 } 99 100 // queryVappTemplateListWithFilter returns a list of vApp templates filtered by the given filter map. 101 // The filter map will build a filter like filterKey==filterValue;filterKey2==filterValue2;... 102 func queryVappTemplateListWithFilter(client *Client, filter map[string]string) ([]*types.QueryResultVappTemplateType, error) { 103 vappTemplateType := types.QtVappTemplate 104 if client.IsSysAdmin { 105 vappTemplateType = types.QtAdminVappTemplate 106 } 107 filterEncoded := "" 108 for k, v := range filter { 109 filterEncoded += fmt.Sprintf("%s==%s;", url.QueryEscape(k), url.QueryEscape(v)) 110 } 111 if len(filterEncoded) > 0 { 112 filterEncoded = filterEncoded[:len(filterEncoded)-1] // Removes the trailing ';' 113 } 114 results, err := client.cumulativeQuery(vappTemplateType, nil, map[string]string{ 115 "type": vappTemplateType, 116 "filter": filterEncoded, 117 }) 118 if err != nil { 119 return nil, fmt.Errorf("error querying vApp templates %s", err) 120 } 121 122 if client.IsSysAdmin { 123 return results.Results.AdminVappTemplateRecord, nil 124 } else { 125 return results.Results.VappTemplateRecord, nil 126 } 127 } 128 129 // QueryVappTemplateList returns a list of vApp templates for the given VDC 130 func (vdc *Vdc) QueryVappTemplateList() ([]*types.QueryResultVappTemplateType, error) { 131 return queryVappTemplateListWithParentField(vdc.client, "vdcName", vdc.Vdc.Name) 132 } 133 134 // QueryVappTemplateWithName returns one vApp template for the given VDC with the given name. 135 // Returns an error if it finds more than one. 136 func (vdc *Vdc) QueryVappTemplateWithName(vAppTemplateName string) (*types.QueryResultVappTemplateType, error) { 137 vAppTemplates, err := queryVappTemplateListWithFilter(vdc.client, map[string]string{ 138 "vdcName": vdc.Vdc.Name, 139 "name": vAppTemplateName, 140 }) 141 if err != nil { 142 return nil, err 143 } 144 if len(vAppTemplates) != 1 { 145 if len(vAppTemplates) == 0 { 146 return nil, ErrorEntityNotFound 147 } 148 return nil, fmt.Errorf("found %d vApp Templates with name %s in VDC %s", len(vAppTemplates), vAppTemplateName, vdc.Vdc.Name) 149 } 150 return vAppTemplates[0], nil 151 } 152 153 // QueryVappTemplateList returns a list of vApp templates for the given VDC 154 func (vdc *AdminVdc) QueryVappTemplateList() ([]*types.QueryResultVappTemplateType, error) { 155 return queryVappTemplateListWithParentField(vdc.client, "vdcName", vdc.AdminVdc.Name) 156 } 157 158 // QueryVappTemplateWithName returns one vApp template for the given VDC with the given name. 159 // Returns an error if it finds more than one. 160 func (vdc *AdminVdc) QueryVappTemplateWithName(vAppTemplateName string) (*types.QueryResultVappTemplateType, error) { 161 vAppTemplates, err := queryVappTemplateListWithFilter(vdc.client, map[string]string{ 162 "vdcName": vdc.AdminVdc.Name, 163 "name": vAppTemplateName, 164 }) 165 if err != nil { 166 return nil, err 167 } 168 if len(vAppTemplates) != 1 { 169 if len(vAppTemplates) == 0 { 170 return nil, ErrorEntityNotFound 171 } 172 return nil, fmt.Errorf("found %d vApp Templates with name %s in VDC %s", len(vAppTemplates), vAppTemplateName, vdc.AdminVdc.Name) 173 } 174 return vAppTemplates[0], nil 175 } 176 177 // QueryVappTemplateList returns a list of vApp templates for the given catalog 178 func (catalog *Catalog) QueryVappTemplateList() ([]*types.QueryResultVappTemplateType, error) { 179 return queryVappTemplateListWithParentField(catalog.client, "catalogName", catalog.Catalog.Name) 180 } 181 182 // QueryVappTemplateWithName returns one vApp template for the given Catalog with the given name. 183 // Returns an error if it finds more than one. 184 func (catalog *Catalog) QueryVappTemplateWithName(vAppTemplateName string) (*types.QueryResultVappTemplateType, error) { 185 return queryVappTemplateWithName(catalog.client, catalog.Catalog.Name, vAppTemplateName) 186 } 187 188 // QueryVappTemplateWithName returns one vApp template for the given Catalog with the given name. 189 // Returns an error if it finds more than one. 190 func (catalog *AdminCatalog) QueryVappTemplateWithName(vAppTemplateName string) (*types.QueryResultVappTemplateType, error) { 191 return queryVappTemplateWithName(catalog.client, catalog.AdminCatalog.Name, vAppTemplateName) 192 } 193 194 // queryVappTemplateWithName returns one vApp template for the given Catalog with the given name. 195 // Returns an error if it finds more than one. 196 func queryVappTemplateWithName(client *Client, catalogName, vAppTemplateName string) (*types.QueryResultVappTemplateType, error) { 197 vAppTemplates, err := queryVappTemplateListWithFilter(client, map[string]string{ 198 "catalogName": catalogName, 199 "name": vAppTemplateName, 200 }) 201 if err != nil { 202 return nil, err 203 } 204 if len(vAppTemplates) != 1 { 205 if len(vAppTemplates) == 0 { 206 return nil, ErrorEntityNotFound 207 } 208 return nil, fmt.Errorf("found %d vApp Templates with name %s in Catalog %s", len(vAppTemplates), vAppTemplateName, catalogName) 209 } 210 return vAppTemplates[0], nil 211 } 212 213 // queryCatalogItemFilteredList returns a list of Catalog Items with an optional filter 214 func queryCatalogItemFilteredList(client *Client, filter map[string]string) ([]*types.QueryResultCatalogItemType, error) { 215 catalogItemType := types.QtCatalogItem 216 if client.IsSysAdmin { 217 catalogItemType = types.QtAdminCatalogItem 218 } 219 220 filterText := "" 221 for k, v := range filter { 222 if filterText != "" { 223 filterText += ";" 224 } 225 filterText += fmt.Sprintf("%s==%s", k, url.QueryEscape(v)) 226 } 227 228 notEncodedParams := map[string]string{ 229 "type": catalogItemType, 230 } 231 if filterText != "" { 232 notEncodedParams["filter"] = filterText 233 } 234 results, err := client.cumulativeQuery(catalogItemType, nil, notEncodedParams) 235 if err != nil { 236 return nil, fmt.Errorf("error querying catalog items %s", err) 237 } 238 239 if client.IsSysAdmin { 240 return results.Results.AdminCatalogItemRecord, nil 241 } else { 242 return results.Results.CatalogItemRecord, nil 243 } 244 } 245 246 // QueryCatalogItemList returns a list of Catalog Item for the given admin catalog 247 func (catalog *AdminCatalog) QueryCatalogItemList() ([]*types.QueryResultCatalogItemType, error) { 248 return queryCatalogItemList(catalog.client, "catalog", catalog.AdminCatalog.ID) 249 } 250 251 // QueryCatalogItem returns a named Catalog Item for the given catalog 252 func (catalog *AdminCatalog) QueryCatalogItem(name string) (*types.QueryResultCatalogItemType, error) { 253 return queryCatalogItem(catalog.client, "catalog", catalog.AdminCatalog.ID, name) 254 } 255 256 // queryCatalogItem returns a named Catalog Item for the given parent 257 func queryCatalogItem(client *Client, parentField, parentValue, name string) (*types.QueryResultCatalogItemType, error) { 258 259 result, err := queryCatalogItemFilteredList(client, map[string]string{parentField: parentValue, "name": name}) 260 if err != nil { 261 return nil, err 262 } 263 if len(result) == 0 { 264 return nil, ErrorEntityNotFound 265 } 266 if len(result) > 1 { 267 return nil, fmt.Errorf("more than one item (%d) found with name %s", len(result), name) 268 } 269 return result[0], nil 270 } 271 272 // queryResultCatalogItemToCatalogItem converts a catalog item as retrieved from a query into a regular one 273 func queryResultCatalogItemToCatalogItem(client *Client, qr *types.QueryResultCatalogItemType) *CatalogItem { 274 var catalogItem = NewCatalogItem(client) 275 catalogItem.CatalogItem = &types.CatalogItem{ 276 HREF: qr.HREF, 277 Type: qr.Type, 278 ID: extractUuid(qr.HREF), 279 Name: qr.Name, 280 DateCreated: qr.CreationDate, 281 Entity: &types.Entity{ 282 HREF: qr.Entity, 283 Type: qr.EntityType, 284 Name: qr.EntityName, 285 }, 286 } 287 return catalogItem 288 } 289 290 // LaunchSync starts synchronisation of a subscribed Catalog item 291 func (item *CatalogItem) LaunchSync() (*Task, error) { 292 util.Logger.Printf("[TRACE] LaunchSync '%s' \n", item.CatalogItem.Name) 293 err := WaitResource(func() (*types.TasksInProgress, error) { 294 if item.CatalogItem.Tasks == nil { 295 return nil, nil 296 } 297 err := item.Refresh() 298 if err != nil { 299 return nil, err 300 } 301 return item.CatalogItem.Tasks, nil 302 }) 303 if err != nil { 304 return nil, err 305 } 306 return elementLaunchSync(item.client, item.CatalogItem.HREF, "catalog item") 307 } 308 309 // Refresh retrieves a fresh copy of the catalog Item 310 func (item *CatalogItem) Refresh() error { 311 _, err := item.client.ExecuteRequest(item.CatalogItem.HREF, http.MethodGet, 312 "", "error retrieving catalog item: %s", nil, item.CatalogItem) 313 if err != nil { 314 return err 315 } 316 return nil 317 }