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  }