@@ -458,6 +458,293 @@ func TestClusterScope_ReconcileRouteTable(t *testing.T) {
458458 }
459459}
460460
461+ func TestClusterScope_CreateRouteTable (t * testing.T ) {
462+ type args struct {
463+ routeTableType string
464+ spec infrastructurev1beta2.OCIClusterSpec
465+ setupMock func (t * testing.T , vcn * mock_vcn.MockClient )
466+ }
467+ tests := []struct {
468+ name string
469+ args args
470+ wantErr bool
471+ expectedErrorMessage string
472+ }{
473+ {
474+ name : "private without peering (NAT + Service routes only)" ,
475+ args : args {
476+ routeTableType : infrastructurev1beta2 .Private ,
477+ spec : infrastructurev1beta2.OCIClusterSpec {
478+ CompartmentId : "comp" ,
479+ NetworkSpec : infrastructurev1beta2.NetworkSpec {
480+ Vcn : infrastructurev1beta2.VCN {
481+ ID : common .String ("vcn1" ),
482+ NATGateway : infrastructurev1beta2.NATGateway {
483+ Id : common .String ("ngw" ),
484+ },
485+ ServiceGateway : infrastructurev1beta2.ServiceGateway {
486+ Id : common .String ("sgw" ),
487+ },
488+ },
489+ },
490+ },
491+ setupMock : func (t * testing.T , vcn * mock_vcn.MockClient ) {
492+ _ = core.CreateRouteTableRequest {
493+ CreateRouteTableDetails : core.CreateRouteTableDetails {
494+ VcnId : common .String ("vcn1" ),
495+ CompartmentId : common .String ("comp" ),
496+ DisplayName : common .String (PrivateRouteTableName ),
497+ FreeformTags : map [string ]string {},
498+ DefinedTags : map [string ]map [string ]interface {}{},
499+ RouteRules : []core.RouteRule {
500+ {
501+ DestinationType : core .RouteRuleDestinationTypeCidrBlock ,
502+ Destination : common .String ("0.0.0.0/0" ),
503+ NetworkEntityId : common .String ("ngw" ),
504+ Description : common .String ("traffic to the internet" ),
505+ },
506+ {
507+ DestinationType : core .RouteRuleDestinationTypeServiceCidrBlock ,
508+ Destination : common .String ("all-iad-services-in-oracle-services-network" ),
509+ NetworkEntityId : common .String ("sgw" ),
510+ Description : common .String ("traffic to OCI services" ),
511+ },
512+ },
513+ },
514+ }
515+ vcn .EXPECT ().
516+ CreateRouteTable (gomock .Any (), gomock .Any ()).
517+ DoAndReturn (func (_ context.Context , req core.CreateRouteTableRequest ) (core.CreateRouteTableResponse , error ) {
518+ // Validate core fields; ignore tags differences
519+ if req .CreateRouteTableDetails .VcnId == nil || * req .CreateRouteTableDetails .VcnId != "vcn1" {
520+ t .Errorf ("expected VcnId=vcn1, got %v" , req .CreateRouteTableDetails .VcnId )
521+ }
522+ if req .CreateRouteTableDetails .CompartmentId == nil || * req .CreateRouteTableDetails .CompartmentId != "comp" {
523+ t .Errorf ("expected CompartmentId=comp, got %v" , req .CreateRouteTableDetails .CompartmentId )
524+ }
525+ if req .CreateRouteTableDetails .DisplayName == nil || * req .CreateRouteTableDetails .DisplayName != PrivateRouteTableName {
526+ t .Errorf ("expected DisplayName=%s, got %v" , PrivateRouteTableName , req .CreateRouteTableDetails .DisplayName )
527+ }
528+ rr := req .CreateRouteTableDetails .RouteRules
529+ if len (rr ) != 2 {
530+ t .Fatalf ("expected 2 route rules, got %d" , len (rr ))
531+ }
532+ // NAT route
533+ if rr [0 ].Destination == nil || * rr [0 ].Destination != "0.0.0.0/0" {
534+ t .Errorf ("expected rule[0] dest 0.0.0.0/0, got %v" , rr [0 ].Destination )
535+ }
536+ if rr [0 ].NetworkEntityId == nil || * rr [0 ].NetworkEntityId != "ngw" {
537+ t .Errorf ("expected rule[0] NEI=ngw, got %v" , rr [0 ].NetworkEntityId )
538+ }
539+ // Service gateway route
540+ if rr [1 ].Destination == nil || * rr [1 ].Destination != "all-iad-services-in-oracle-services-network" {
541+ t .Errorf ("expected rule[1] dest all-iad-services-in-oracle-services-network, got %v" , rr [1 ].Destination )
542+ }
543+ if rr [1 ].NetworkEntityId == nil || * rr [1 ].NetworkEntityId != "sgw" {
544+ t .Errorf ("expected rule[1] NEI=sgw, got %v" , rr [1 ].NetworkEntityId )
545+ }
546+ return core.CreateRouteTableResponse {RouteTable : core.RouteTable {Id : common .String ("rt" )}}, nil
547+ })
548+ },
549+ },
550+ wantErr : false ,
551+ },
552+ {
553+ name : "private with peering (adds DRG peer routes)" ,
554+ args : args {
555+ routeTableType : infrastructurev1beta2 .Private ,
556+ spec : infrastructurev1beta2.OCIClusterSpec {
557+ CompartmentId : "comp" ,
558+ NetworkSpec : infrastructurev1beta2.NetworkSpec {
559+ VCNPeering : & infrastructurev1beta2.VCNPeering {
560+ DRG : & infrastructurev1beta2.DRG {ID : common .String ("drg-id" )},
561+ PeerRouteRules : []infrastructurev1beta2.PeerRouteRule {
562+ {VCNCIDRRange : "10.1.0.0/16" },
563+ },
564+ },
565+ Vcn : infrastructurev1beta2.VCN {
566+ ID : common .String ("vcn1" ),
567+ NATGateway : infrastructurev1beta2.NATGateway {
568+ Id : common .String ("ngw" ),
569+ },
570+ ServiceGateway : infrastructurev1beta2.ServiceGateway {
571+ Id : common .String ("sgw" ),
572+ },
573+ },
574+ },
575+ },
576+ setupMock : func (t * testing.T , vcn * mock_vcn.MockClient ) {
577+ _ = core.CreateRouteTableRequest {
578+ CreateRouteTableDetails : core.CreateRouteTableDetails {
579+ VcnId : common .String ("vcn1" ),
580+ CompartmentId : common .String ("comp" ),
581+ DisplayName : common .String (PrivateRouteTableName ),
582+ FreeformTags : map [string ]string {},
583+ DefinedTags : map [string ]map [string ]interface {}{},
584+ RouteRules : []core.RouteRule {
585+ {
586+ DestinationType : core .RouteRuleDestinationTypeCidrBlock ,
587+ Destination : common .String ("0.0.0.0/0" ),
588+ NetworkEntityId : common .String ("ngw" ),
589+ Description : common .String ("traffic to the internet" ),
590+ },
591+ {
592+ DestinationType : core .RouteRuleDestinationTypeServiceCidrBlock ,
593+ Destination : common .String ("all-iad-services-in-oracle-services-network" ),
594+ NetworkEntityId : common .String ("sgw" ),
595+ Description : common .String ("traffic to OCI services" ),
596+ },
597+ {
598+ DestinationType : core .RouteRuleDestinationTypeCidrBlock ,
599+ Destination : common .String ("10.1.0.0/16" ),
600+ NetworkEntityId : common .String ("drg-id" ),
601+ Description : common .String ("traffic to peer DRG" ),
602+ },
603+ },
604+ },
605+ }
606+ vcn .EXPECT ().
607+ CreateRouteTable (gomock .Any (), gomock .Any ()).
608+ DoAndReturn (func (_ context.Context , req core.CreateRouteTableRequest ) (core.CreateRouteTableResponse , error ) {
609+ // Validate core fields; ignore tags differences
610+ if req .CreateRouteTableDetails .VcnId == nil || * req .CreateRouteTableDetails .VcnId != "vcn1" {
611+ t .Errorf ("expected VcnId=vcn1, got %v" , req .CreateRouteTableDetails .VcnId )
612+ }
613+ if req .CreateRouteTableDetails .CompartmentId == nil || * req .CreateRouteTableDetails .CompartmentId != "comp" {
614+ t .Errorf ("expected CompartmentId=comp, got %v" , req .CreateRouteTableDetails .CompartmentId )
615+ }
616+ if req .CreateRouteTableDetails .DisplayName == nil || * req .CreateRouteTableDetails .DisplayName != PrivateRouteTableName {
617+ t .Errorf ("expected DisplayName=%s, got %v" , PrivateRouteTableName , req .CreateRouteTableDetails .DisplayName )
618+ }
619+ rr := req .CreateRouteTableDetails .RouteRules
620+ if len (rr ) != 3 {
621+ t .Fatalf ("expected 3 route rules, got %d" , len (rr ))
622+ }
623+ // NAT route
624+ if rr [0 ].Destination == nil || * rr [0 ].Destination != "0.0.0.0/0" {
625+ t .Errorf ("expected rule[0] dest 0.0.0.0/0, got %v" , rr [0 ].Destination )
626+ }
627+ if rr [0 ].NetworkEntityId == nil || * rr [0 ].NetworkEntityId != "ngw" {
628+ t .Errorf ("expected rule[0] NEI=ngw, got %v" , rr [0 ].NetworkEntityId )
629+ }
630+ // Service gateway route
631+ if rr [1 ].Destination == nil || * rr [1 ].Destination != "all-iad-services-in-oracle-services-network" {
632+ t .Errorf ("expected rule[1] dest all-iad-services-in-oracle-services-network, got %v" , rr [1 ].Destination )
633+ }
634+ if rr [1 ].NetworkEntityId == nil || * rr [1 ].NetworkEntityId != "sgw" {
635+ t .Errorf ("expected rule[1] NEI=sgw, got %v" , rr [1 ].NetworkEntityId )
636+ }
637+ // DRG peering route
638+ if rr [2 ].Destination == nil || * rr [2 ].Destination != "10.1.0.0/16" {
639+ t .Errorf ("expected rule[2] dest 10.1.0.0/16, got %v" , rr [2 ].Destination )
640+ }
641+ if rr [2 ].NetworkEntityId == nil || * rr [2 ].NetworkEntityId != "drg-id" {
642+ t .Errorf ("expected rule[2] NEI=drg-id, got %v" , rr [2 ].NetworkEntityId )
643+ }
644+ return core.CreateRouteTableResponse {RouteTable : core.RouteTable {Id : common .String ("rt" )}}, nil
645+ })
646+ },
647+ },
648+ wantErr : false ,
649+ },
650+ {
651+ name : "private with peering but DRG is nil" ,
652+ args : args {
653+ routeTableType : infrastructurev1beta2 .Private ,
654+ spec : infrastructurev1beta2.OCIClusterSpec {
655+ CompartmentId : "comp" ,
656+ NetworkSpec : infrastructurev1beta2.NetworkSpec {
657+ VCNPeering : & infrastructurev1beta2.VCNPeering {
658+ DRG : nil , // Intentionally set to nil
659+ PeerRouteRules : []infrastructurev1beta2.PeerRouteRule {{VCNCIDRRange : "10.1.0.0/16" }},
660+ RemotePeeringConnections : nil ,
661+ },
662+ Vcn : infrastructurev1beta2.VCN {
663+ ID : common .String ("vcn1" ),
664+ NATGateway : infrastructurev1beta2.NATGateway {
665+ Id : common .String ("ngw" ),
666+ },
667+ ServiceGateway : infrastructurev1beta2.ServiceGateway {
668+ Id : common .String ("sgw" ),
669+ },
670+ },
671+ },
672+ },
673+ setupMock : func (t * testing.T , vcn * mock_vcn.MockClient ) {
674+ // No CreateRouteTable call expected because we error out before
675+ vcn .EXPECT ().CreateRouteTable (gomock .Any (), gomock .Any ()).Times (0 )
676+ },
677+ },
678+ wantErr : true ,
679+ expectedErrorMessage : "Create Route Table: DRG has not been specified" ,
680+ },
681+ {
682+ name : "private with peering but DRG ID is nil" ,
683+ args : args {
684+ routeTableType : infrastructurev1beta2 .Private ,
685+ spec : infrastructurev1beta2.OCIClusterSpec {
686+ CompartmentId : "comp" ,
687+ NetworkSpec : infrastructurev1beta2.NetworkSpec {
688+ VCNPeering : & infrastructurev1beta2.VCNPeering {
689+ DRG : & infrastructurev1beta2.DRG {ID : nil },
690+ PeerRouteRules : []infrastructurev1beta2.PeerRouteRule {{VCNCIDRRange : "10.1.0.0/16" }},
691+ },
692+ Vcn : infrastructurev1beta2.VCN {
693+ ID : common .String ("vcn1" ),
694+ NATGateway : infrastructurev1beta2.NATGateway {
695+ Id : common .String ("ngw" ),
696+ },
697+ ServiceGateway : infrastructurev1beta2.ServiceGateway {
698+ Id : common .String ("sgw" ),
699+ },
700+ },
701+ },
702+ },
703+ setupMock : func (t * testing.T , vcn * mock_vcn.MockClient ) {
704+ // No CreateRouteTable call expected because we error out before
705+ vcn .EXPECT ().CreateRouteTable (gomock .Any (), gomock .Any ()).Times (0 )
706+ },
707+ },
708+ wantErr : true ,
709+ expectedErrorMessage : "Create Route Table: DRG ID has not been set" ,
710+ },
711+ }
712+
713+ for _ , tt := range tests {
714+ tt := tt
715+ t .Run (tt .name , func (t * testing.T ) {
716+ mockCtrl := gomock .NewController (t )
717+ defer mockCtrl .Finish ()
718+ vcnClient := mock_vcn .NewMockClient (mockCtrl )
719+ if tt .args .setupMock != nil {
720+ tt .args .setupMock (t , vcnClient )
721+ }
722+
723+ l := log .FromContext (context .Background ())
724+ ociClusterAccessor := OCISelfManagedCluster {
725+ OCICluster : & infrastructurev1beta2.OCICluster {
726+ ObjectMeta : metav1.ObjectMeta {UID : "cluster_uid" },
727+ Spec : tt .args .spec ,
728+ },
729+ }
730+ s := & ClusterScope {
731+ VCNClient : vcnClient ,
732+ OCIClusterAccessor : ociClusterAccessor ,
733+ Logger : & l ,
734+ RegionKey : "iad" ,
735+ }
736+
737+ _ , err := s .CreateRouteTable (context .Background (), tt .args .routeTableType )
738+ if (err != nil ) != tt .wantErr {
739+ t .Fatalf ("CreateRouteTable() error = %v, wantErr %v" , err , tt .wantErr )
740+ }
741+ if err != nil && tt .expectedErrorMessage != "" && err .Error () != tt .expectedErrorMessage {
742+ t .Fatalf ("CreateRouteTable() expected error = %q, got %q" , tt .expectedErrorMessage , err .Error ())
743+ }
744+ })
745+ }
746+ }
747+
461748func TestClusterScope_DeleteRouteTables (t * testing.T ) {
462749 mockCtrl := gomock .NewController (t )
463750 defer mockCtrl .Finish ()
0 commit comments