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