github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/tenant_context.go (about)

     1  /*
     2   * Copyright 2021 VMware, Inc.  All rights reserved.  Licensed under the Apache v2 License.
     3   */
     4  package govcd
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/vmware/go-vcloud-director/v2/types/v56"
    11  )
    12  
    13  // TenantContext stores the information needed for an object to be used in the context of a given organization
    14  type TenantContext struct {
    15  	OrgId   string // The bare ID (without prefix) of an organization
    16  	OrgName string // The organization name
    17  }
    18  
    19  // organization is an abstraction of types Org and AdminOrg
    20  type organization interface {
    21  	orgId() string
    22  	orgName() string
    23  	tenantContext() (*TenantContext, error)
    24  	fullObject() interface{}
    25  }
    26  
    27  //lint:ignore U1000 for future usage
    28  type genericVdc interface {
    29  	vdcId() string
    30  	vdcName() string
    31  	vdcParent() interface{}
    32  }
    33  
    34  //lint:ignore U1000 for future usage
    35  type genericCatalog interface {
    36  	catalogId() string
    37  	catalogName() string
    38  	catalogParent() interface{}
    39  }
    40  
    41  // Implementation of organization interface for Org
    42  func (org *Org) orgId() string                          { return org.Org.ID }
    43  func (org *Org) orgName() string                        { return org.Org.Name }
    44  func (org *Org) tenantContext() (*TenantContext, error) { return org.getTenantContext() }
    45  func (org *Org) fullObject() interface{}                { return org }
    46  
    47  // Implementation of organization interface for AdminOrg
    48  func (adminOrg *AdminOrg) orgId() string                          { return adminOrg.AdminOrg.ID }
    49  func (adminOrg *AdminOrg) orgName() string                        { return adminOrg.AdminOrg.Name }
    50  func (adminOrg *AdminOrg) tenantContext() (*TenantContext, error) { return adminOrg.getTenantContext() }
    51  func (adminOrg *AdminOrg) fullObject() interface{}                { return adminOrg }
    52  
    53  // Implementation of genericVdc interface for Vdc
    54  func (vdc *Vdc) vdcId() string          { return vdc.Vdc.ID }
    55  func (vdc *Vdc) vdcName() string        { return vdc.Vdc.Name }
    56  func (vdc *Vdc) vdcParent() interface{} { return vdc.parent }
    57  
    58  // Implementation of genericVdc interface for AdminVdc
    59  func (adminVdc *AdminVdc) vdcId() string          { return adminVdc.AdminVdc.ID }
    60  func (adminVdc *AdminVdc) vdcName() string        { return adminVdc.AdminVdc.Name }
    61  func (adminVdc *AdminVdc) vdcParent() interface{} { return adminVdc.parent }
    62  
    63  // Implementation of genericCatalog interface for AdminCatalog
    64  func (adminCatalog *AdminCatalog) catalogId() string          { return adminCatalog.AdminCatalog.ID }
    65  func (adminCatalog *AdminCatalog) catalogName() string        { return adminCatalog.AdminCatalog.Name }
    66  func (adminCatalog *AdminCatalog) catalogParent() interface{} { return adminCatalog.parent }
    67  
    68  // Implementation of genericCatalog interface for AdminCatalog
    69  func (catalog *Catalog) catalogId() string          { return catalog.Catalog.ID }
    70  func (catalog *Catalog) catalogName() string        { return catalog.Catalog.Name }
    71  func (catalog *Catalog) catalogParent() interface{} { return catalog.parent }
    72  
    73  // getTenantContext returns the tenant context information for an Org
    74  // If the information was not stored, it gets created and stored for future use
    75  func (org *Org) getTenantContext() (*TenantContext, error) {
    76  	if org.TenantContext == nil {
    77  		id, err := getBareEntityUuid(org.Org.ID)
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  		org.TenantContext = &TenantContext{
    82  			OrgId:   id,
    83  			OrgName: org.Org.Name,
    84  		}
    85  	}
    86  	return org.TenantContext, nil
    87  }
    88  
    89  // getTenantContext returns the tenant context information for an AdminOrg
    90  // If the information was not stored, it gets created and stored for future use
    91  func (org *AdminOrg) getTenantContext() (*TenantContext, error) {
    92  	if org.TenantContext == nil {
    93  		id, err := getBareEntityUuid(org.AdminOrg.ID)
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  		org.TenantContext = &TenantContext{
    98  			OrgId:   id,
    99  			OrgName: org.AdminOrg.Name,
   100  		}
   101  	}
   102  	return org.TenantContext, nil
   103  }
   104  
   105  // getTenantContext retrieves the tenant context for an AdminVdc
   106  func (vdc *AdminVdc) getTenantContext() (*TenantContext, error) {
   107  	org := vdc.parent
   108  
   109  	if org == nil {
   110  		return nil, fmt.Errorf("VDC %s has no parent", vdc.AdminVdc.Name)
   111  	}
   112  	return org.tenantContext()
   113  }
   114  
   115  // getTenantContext retrieves the tenant context for a VDC
   116  func (vdc *Vdc) getTenantContext() (*TenantContext, error) {
   117  	org := vdc.parent
   118  
   119  	if org == nil {
   120  		return nil, fmt.Errorf("VDC %s has no parent", vdc.Vdc.Name)
   121  	}
   122  	return org.tenantContext()
   123  }
   124  
   125  // getTenantContext retrieves the tenant context for an AdminCatalog
   126  func (catalog *AdminCatalog) getTenantContext() (*TenantContext, error) {
   127  	org := catalog.parent
   128  
   129  	if org == nil {
   130  		return nil, fmt.Errorf("catalog %s has no parent", catalog.AdminCatalog.Name)
   131  	}
   132  	return org.tenantContext()
   133  }
   134  
   135  // getTenantContext retrieves the tenant context for a Catalog
   136  func (catalog *Catalog) getTenantContext() (*TenantContext, error) {
   137  	org := catalog.parent
   138  
   139  	if org == nil {
   140  		return nil, fmt.Errorf("catalog %s has no parent", catalog.Catalog.Name)
   141  	}
   142  	return org.tenantContext()
   143  }
   144  
   145  // getTenantContextHeader returns a map of strings containing the tenant context items
   146  // needed to be used in http.Request.Header
   147  func getTenantContextHeader(tenantContext *TenantContext) map[string]string {
   148  	if tenantContext == nil {
   149  		return nil
   150  	}
   151  	if tenantContext.OrgName == "" || strings.EqualFold(tenantContext.OrgName, "system") {
   152  		return nil
   153  	}
   154  	return map[string]string{
   155  		// All VCD 10.2.X versions do not like when URN is sent for Tenant context ID - they fail
   156  		// with 401 Unauthorized when such request is sent with URN formatted ID:
   157  		// * Fails with 401: urn:vcloud:org:6127c856-7315-46b8-b774-f2b8f1686c80
   158  		// * Works fine: 6127c856-7315-46b8-b774-f2b8f1686c80
   159  		types.HeaderTenantContext: extractUuid(tenantContext.OrgId),
   160  		types.HeaderAuthContext:   tenantContext.OrgName,
   161  	}
   162  }
   163  
   164  // getTenantContextFromHeader does the opposite of getTenantContextHeader:
   165  // given a header, returns a TenantContext
   166  func getTenantContextFromHeader(header map[string]string) *TenantContext {
   167  	if len(header) == 0 {
   168  		return nil
   169  	}
   170  	tenantContext, okTenant := header[types.HeaderTenantContext]
   171  	AuthContext, okAuth := header[types.HeaderAuthContext]
   172  	if okTenant && okAuth {
   173  		return &TenantContext{
   174  			OrgId:   tenantContext,
   175  			OrgName: AuthContext,
   176  		}
   177  	}
   178  	return nil
   179  }
   180  
   181  // getTenantContext retrieves the tenant context for a VdcGroup
   182  func (vdcGroup *VdcGroup) getTenantContext() (*TenantContext, error) {
   183  	org := vdcGroup.parent
   184  
   185  	if org == nil {
   186  		return nil, fmt.Errorf("VDC group %s has no parent", vdcGroup.VdcGroup.Name)
   187  	}
   188  	return org.tenantContext()
   189  }
   190  
   191  // getTenantContext retrieves the tenant context for a IpSpaceIpAllocation
   192  func (ipSpaceAllocation *IpSpaceIpAllocation) getTenantContext() (*TenantContext, error) {
   193  	org := ipSpaceAllocation.parent
   194  
   195  	if org == nil {
   196  		return nil, fmt.Errorf("IP Space IP Allocation %s has no parent", ipSpaceAllocation.IpSpaceIpAllocation.Description)
   197  	}
   198  	return org.tenantContext()
   199  }
   200  
   201  func (egw *NsxtEdgeGateway) getTenantContext() (*TenantContext, error) {
   202  	if egw != nil && egw.EdgeGateway.Org != nil {
   203  		if egw.EdgeGateway.Org.Name == "" || egw.EdgeGateway.Org.ID == "" {
   204  			return nil, fmt.Errorf("either parent NsxtEdgeGateway Org name or ID is empty and both must be set. Org name is [%s] and Org ID is [%s]", egw.EdgeGateway.Org.Name, egw.EdgeGateway.Org.ID)
   205  		}
   206  
   207  		return &TenantContext{OrgId: egw.EdgeGateway.Org.ID, OrgName: egw.EdgeGateway.Org.Name}, nil
   208  	}
   209  
   210  	return nil, fmt.Errorf("NsxtEdgeGateway is not fully initialized. Please initialize it before using this method")
   211  }