@@ -475,7 +475,134 @@ the request header.
475
475
476
476
When the tenant context is not needed (system administration calls), we just pass ` nil ` as ` additionalHeader ` .
477
477
478
+ ## Generic CRUD functions for OpenAPI entity implementation
478
479
480
+ Generic CRUD functions are used to minimize boilerplate for entity implementation in the SDK. They
481
+ might not always be the way to go when there are very specific operation needs as it is not worth
482
+ having a generic function for single use case. In such cases, low level API client function set,
483
+ that is located in ` openapi.go ` can help to perform such operations.
484
+
485
+ ### Terminology
486
+
487
+ #### inner vs outer types
488
+
489
+ For the context of generic CRUD function implementation (mainly in files
490
+ ` govcd/openapi_generic_outer_entities.go ` , ` govcd/openapi_generic_inner_entities.go ` ), such terms
491
+ are commonly used:
492
+
493
+ * ` inner ` type is the type that is responsible for marshaling/unmarshaling API
494
+ request payload and is usually inside ` types ` package. (e.g. ` types.IpSpace ` ,
495
+ ` types.NsxtAlbPoolMember ` , etc.)
496
+ * ` outer ` (type) - this is the type that wraps ` inner ` type and possibly any other entities that are
497
+ required to perform operations for a particular VCD entity. It will almost always include some
498
+ reference to client (` VCDClient ` or ` Client ` ), which is required to perform API operations. It may
499
+ contain additional fields.
500
+
501
+ Here are the entities mapped in the example below:
502
+
503
+ * ` DistributedFirewall ` is the ** ` outer ` ** type
504
+ * ` types.DistributedFirewallRules ` is the ** ` inner ` ** type (specified in
505
+ ` DistributedFirewall.DistributedFirewallRuleContainer ` field)
506
+ * ` client ` field contains the client that is required for perfoming API operations
507
+ * ` VdcGroup ` field contains additional data (VDC Group reference) that is required for
508
+ implementation of this particular entity
509
+
510
+ ``` go
511
+ type DistributedFirewall struct {
512
+ DistributedFirewallRuleContainer *types.DistributedFirewallRules
513
+ client *Client
514
+ VdcGroup *VdcGroup
515
+ }
516
+ ```
517
+
518
+ #### crudConfig
519
+
520
+ A special type ` govcd.crudConfig ` is used for passing configuration to both - ` inner ` and ` outer `
521
+ generic CRUD functions. It also has an internal ` validate() ` method, which is called upon execution
522
+ of any ` inner ` and ` outer ` CRUD functions.
523
+
524
+ See documentation of ` govcd.crudConfig ` for the options it provides.
525
+
526
+ ### Use cases
527
+
528
+ The main consideration when to use which functions depends on whether one is dealing with ` inner `
529
+ types or ` outer ` types. Both types can be used for quicker development.
530
+
531
+ Usually, ` outer ` type is used for a full featured entity (e.g. ` IpSpace ` , ` NsxtEdgeGateway ` ), while
532
+ ` inner ` suits cases where one needs to perform operations on an already existing or a read-only
533
+ entity.
534
+
535
+ ** Hint:** return value of your entity method will always hint whether it is ` inner ` or ` outer ` one:
536
+
537
+ ` inner ` type function signature example (returns ` *types.VdcNetworkProfile ` ):
538
+
539
+ ```
540
+ func (adminVdc *AdminVdc) UpdateVdcNetworkProfile(vdcNetworkProfileConfig *types.VdcNetworkProfile) (*types.VdcNetworkProfile, error) {
541
+ ```
542
+
543
+ ` outer ` type function signature example (returns ` *IpSpace ` ):
544
+
545
+ ```
546
+ func (vcdClient *VCDClient) CreateIpSpace(ipSpaceConfig *types.IpSpace) (*IpSpace, error) {
547
+ ```
548
+
549
+ #### inner CRUD functions
550
+
551
+ The entities that match below criteria are usually going to use ` inner ` crud functions:
552
+ * API property manipulation with separate API endpoints for an already existing entity (e.g. VDC
553
+ Network Profiles ` Vdc.UpdateVdcNetworkProfile ` )
554
+ * Read only entities (e.g. NSX-T Segment Profiles ` VCDClient.GetAllIpDiscoveryProfiles ` )
555
+
556
+ Inner types are more simple as they can be directly used without any additional overhead. There are
557
+ 7 functions that can be used:
558
+
559
+ * ` createInnerEntity `
560
+ * ` updateInnerEntity `
561
+ * ` updateInnerEntityWithHeaders `
562
+ * ` getInnerEntity `
563
+ * ` getInnerEntityWithHeaders `
564
+ * ` deleteEntityById `
565
+ * ` getAllInnerEntities `
566
+
567
+ Existing examples of the implementation are:
568
+
569
+ * ` Vdc.GetVdcNetworkProfile `
570
+ * ` Vdc.UpdateVdcNetworkProfile `
571
+ * ` Vdc.DeleteVdcNetworkProfile `
572
+ * ` VCDClient.GetAllIpDiscoveryProfiles `
573
+
574
+ #### outer CRUD functions
575
+
576
+ The entities, that implement complete management of a VCD entity will usually rely on ` outer ` CRUD
577
+ functions. Any ` outer ` type * must* implement ` wrap ` method (example signature provided below). It is
578
+ required to satisfy generic interface constraint (so that generic functions are able to wrap ` inner `
579
+ type into ` outer ` type)
580
+
581
+ ``` go
582
+ func (o OuterEntity ) wrap (inner *InnerEntity ) *OuterEntity {
583
+ o.OuterEntity = inner
584
+ return &o
585
+ }
586
+ ```
587
+ There are 5 functions for handling CRU(D).
588
+ * ` createOuterEntity `
589
+ * ` updateOuterEntity `
590
+ * ` getOuterEntity `
591
+ * ` getOuterEntityWithHeaders `
592
+ * ` getAllOuterEntities `
593
+
594
+ * Note* : ` D ` (deletion) in ` CRUD ` is a simple operation that does not additionally handle data and
595
+ ` deleteEntityById ` is sufficient.
596
+
597
+ Existing examples of the implementation are:
598
+ * ` IpSpace `
599
+ * ` IpSpaceUplink `
600
+ * ` DistributedFirewall `
601
+ * ` DistributedFirewallRule `
602
+ * ` NsxtSegmentProfileTemplate `
603
+ * ` DefinedEntityType `
604
+ * ` DefinedInterface `
605
+ * ` DefinedEntity `
479
606
480
607
## Testing
481
608
0 commit comments