github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/defined_interface.go (about) 1 /* 2 * Copyright 2023 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. 3 */ 4 5 package govcd 6 7 import ( 8 "fmt" 9 "net/url" 10 "strings" 11 12 "github.com/vmware/go-vcloud-director/v2/types/v56" 13 ) 14 15 const ( 16 labelDefinedInterface = "Defined Interface" 17 labelDefinedInterfaceBehavior = "Defined Interface Behavior" 18 ) 19 20 // DefinedInterface is a type for handling Defined Interfaces, from the Runtime Defined Entities framework, in VCD. 21 // This is often referred as Runtime Defined Entity Interface or RDE Interface in documentation. 22 type DefinedInterface struct { 23 DefinedInterface *types.DefinedInterface 24 client *Client 25 } 26 27 // wrap is a hidden helper that facilitates the usage of a generic CRUD function 28 // 29 //lint:ignore U1000 this method is used in generic functions, but annoys staticcheck 30 func (d DefinedInterface) wrap(inner *types.DefinedInterface) *DefinedInterface { 31 d.DefinedInterface = inner 32 return &d 33 } 34 35 // CreateDefinedInterface creates a Defined Interface. 36 // Only System administrator can create Defined Interfaces. 37 func (vcdClient *VCDClient) CreateDefinedInterface(definedInterface *types.DefinedInterface) (*DefinedInterface, error) { 38 c := crudConfig{ 39 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaces, 40 entityLabel: labelDefinedInterface, 41 } 42 outerType := DefinedInterface{client: &vcdClient.Client} 43 return createOuterEntity(&vcdClient.Client, outerType, c, definedInterface) 44 } 45 46 // GetAllDefinedInterfaces retrieves all Defined Interfaces. Query parameters can be supplied to perform additional filtering. 47 func (vcdClient *VCDClient) GetAllDefinedInterfaces(queryParameters url.Values) ([]*DefinedInterface, error) { 48 c := crudConfig{ 49 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaces, 50 entityLabel: labelDefinedInterface, 51 queryParameters: queryParameters, 52 } 53 54 outerType := DefinedInterface{client: &vcdClient.Client} 55 return getAllOuterEntities(&vcdClient.Client, outerType, c) 56 } 57 58 // GetDefinedInterface retrieves a single Defined Interface defined by its unique combination of vendor, nss and version. 59 func (vcdClient *VCDClient) GetDefinedInterface(vendor, nss, version string) (*DefinedInterface, error) { 60 queryParameters := url.Values{} 61 queryParameters.Add("filter", fmt.Sprintf("vendor==%s;nss==%s;version==%s", vendor, nss, version)) 62 interfaces, err := vcdClient.GetAllDefinedInterfaces(queryParameters) 63 if err != nil { 64 return nil, err 65 } 66 67 if len(interfaces) == 0 { 68 return nil, fmt.Errorf("%s could not find the Defined Interface with vendor %s, nss %s and version %s", ErrorEntityNotFound, vendor, nss, version) 69 } 70 71 if len(interfaces) > 1 { 72 return nil, fmt.Errorf("found more than 1 Defined Interface with vendor %s, nss %s and version %s", vendor, nss, version) 73 } 74 75 return interfaces[0], nil 76 } 77 78 // GetDefinedInterfaceById gets a Defined Interface identified by its unique URN. 79 func (vcdClient *VCDClient) GetDefinedInterfaceById(id string) (*DefinedInterface, error) { 80 c := crudConfig{ 81 entityLabel: labelDefinedInterface, 82 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaces, 83 endpointParams: []string{id}, 84 } 85 86 outerType := DefinedInterface{client: &vcdClient.Client} 87 return getOuterEntity(&vcdClient.Client, outerType, c) 88 } 89 90 // Update updates the receiver Defined Interface with the values given by the input. 91 // Only System administrator can update Defined Interfaces. 92 func (di *DefinedInterface) Update(definedInterface types.DefinedInterface) error { 93 if di.DefinedInterface.ID == "" { 94 return fmt.Errorf("ID of the receiver Defined Interface is empty") 95 } 96 97 if definedInterface.ID != "" && definedInterface.ID != di.DefinedInterface.ID { 98 return fmt.Errorf("ID of the receiver Defined Interface and the input ID don't match") 99 } 100 101 // We override these as they need to be always sent on updates 102 definedInterface.Version = di.DefinedInterface.Version 103 definedInterface.Nss = di.DefinedInterface.Nss 104 definedInterface.Vendor = di.DefinedInterface.Vendor 105 106 c := crudConfig{ 107 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaces, 108 endpointParams: []string{di.DefinedInterface.ID}, 109 entityLabel: labelDefinedInterface, 110 } 111 resultDefinedInterface, err := updateInnerEntity(di.client, c, &definedInterface) 112 if err != nil { 113 return err 114 } 115 // Only if there was no error in request we overwrite pointer receiver as otherwise it would 116 // wipe out existing data 117 di.DefinedInterface = resultDefinedInterface 118 return err 119 } 120 121 // Delete deletes the receiver Defined Interface. 122 // Only System administrator can delete Defined Interfaces. 123 func (di *DefinedInterface) Delete() error { 124 if di.DefinedInterface.ID == "" { 125 return fmt.Errorf("ID of the receiver Defined Interface is empty") 126 } 127 128 c := crudConfig{ 129 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaces, 130 endpointParams: []string{di.DefinedInterface.ID}, 131 entityLabel: labelDefinedInterface, 132 } 133 134 err := deleteEntityById(di.client, c) 135 if err != nil { 136 return err 137 } 138 139 di.DefinedInterface = &types.DefinedInterface{} 140 return nil 141 } 142 143 // AddBehavior adds a new Behavior to the receiver DefinedInterface. 144 // Only allowed if the Interface is not in use. 145 func (di *DefinedInterface) AddBehavior(behavior types.Behavior) (*types.Behavior, error) { 146 if di.DefinedInterface.ID == "" { 147 return nil, fmt.Errorf("ID of the receiver Defined Interface is empty") 148 } 149 150 c := crudConfig{ 151 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaceBehaviors, 152 endpointParams: []string{di.DefinedInterface.ID}, 153 entityLabel: labelDefinedInterfaceBehavior, 154 } 155 return createInnerEntity(di.client, c, &behavior) 156 } 157 158 // GetAllBehaviors retrieves all the Behaviors of the receiver Defined Interface. 159 func (di *DefinedInterface) GetAllBehaviors(queryParameters url.Values) ([]*types.Behavior, error) { 160 if di.DefinedInterface.ID == "" { 161 return nil, fmt.Errorf("ID of the receiver Defined Interface is empty") 162 } 163 return getAllBehaviors(di.client, di.DefinedInterface.ID, types.OpenApiEndpointRdeInterfaceBehaviors, queryParameters) 164 } 165 166 // getAllBehaviors gets all the Behaviors from the object referenced by the input Object ID with the given OpenAPI endpoint. 167 func getAllBehaviors(client *Client, objectId, openApiEndpoint string, queryParameters url.Values) ([]*types.Behavior, error) { 168 c := crudConfig{ 169 endpoint: types.OpenApiPathVersion1_0_0 + openApiEndpoint, 170 entityLabel: labelDefinedInterfaceBehavior, 171 endpointParams: []string{objectId}, 172 queryParameters: queryParameters, 173 } 174 return getAllInnerEntities[types.Behavior](client, c) 175 } 176 177 // GetBehaviorById retrieves a unique Behavior that belongs to the receiver Defined Interface and is determined by the 178 // input ID. 179 func (di *DefinedInterface) GetBehaviorById(id string) (*types.Behavior, error) { 180 c := crudConfig{ 181 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaceBehaviors, 182 endpointParams: []string{di.DefinedInterface.ID, id}, 183 entityLabel: labelDefinedInterfaceBehavior, 184 } 185 return getInnerEntity[types.Behavior](di.client, c) 186 } 187 188 // GetBehaviorByName retrieves a unique Behavior that belongs to the receiver Defined Interface and is named after 189 // the input. 190 func (di *DefinedInterface) GetBehaviorByName(name string) (*types.Behavior, error) { 191 behaviors, err := di.GetAllBehaviors(nil) 192 if err != nil { 193 return nil, fmt.Errorf("could not get the Behaviors of the Defined Interface with ID '%s': %s", di.DefinedInterface.ID, err) 194 } 195 label := fmt.Sprintf("Defined Interface Behavior with name '%s' in Defined Interface with ID '%s': %s", name, di.DefinedInterface.ID, ErrorEntityNotFound) 196 return localFilterOneOrError(label, behaviors, "Name", name) 197 } 198 199 // UpdateBehavior updates a Behavior specified by the input. 200 func (di *DefinedInterface) UpdateBehavior(behavior types.Behavior) (*types.Behavior, error) { 201 if di.DefinedInterface.ID == "" { 202 return nil, fmt.Errorf("ID of the receiver Defined Interface is empty") 203 } 204 if behavior.ID == "" { 205 return nil, fmt.Errorf("ID of the Behavior to update is empty") 206 } 207 208 c := crudConfig{ 209 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaceBehaviors, 210 endpointParams: []string{di.DefinedInterface.ID, behavior.ID}, 211 entityLabel: labelDefinedInterfaceBehavior, 212 } 213 return updateInnerEntity(di.client, c, &behavior) 214 } 215 216 // DeleteBehavior removes a Behavior specified by its ID from the receiver Defined Interface. 217 func (di *DefinedInterface) DeleteBehavior(behaviorId string) error { 218 if di.DefinedInterface.ID == "" { 219 return fmt.Errorf("ID of the receiver Defined Interface is empty") 220 } 221 222 c := crudConfig{ 223 endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeInterfaceBehaviors, 224 endpointParams: []string{di.DefinedInterface.ID, behaviorId}, 225 entityLabel: labelDefinedInterfaceBehavior, 226 } 227 return deleteEntityById(di.client, c) 228 } 229 230 // amendRdeApiError fixes a wrong type of error returned by VCD API <= v36.0 on GET operations 231 // when the defined interface does not exist. 232 func amendRdeApiError(client *Client, err error) error { 233 if client.APIClientVersionIs("<= 36.0") && err != nil && strings.Contains(err.Error(), "does not exist") { 234 return fmt.Errorf("%s: %s", ErrorEntityNotFound.Error(), err) 235 } 236 return err 237 }