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 }