From e96dd9fc3d2e48a8a8615e74b60b1e37e4541eba Mon Sep 17 00:00:00 2001 From: liwen wu Date: Tue, 28 Feb 2023 07:56:03 +0000 Subject: [PATCH 01/21] Define field in service network model to indicate whether needs to associate to VPC --- pkg/gateway/model_build_servicenetwork.go | 15 +++++++++++++-- pkg/model/lattice/servicenetwork.go | 7 ++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pkg/gateway/model_build_servicenetwork.go b/pkg/gateway/model_build_servicenetwork.go index 1ed5b027..dd7eb092 100644 --- a/pkg/gateway/model_build_servicenetwork.go +++ b/pkg/gateway/model_build_servicenetwork.go @@ -61,8 +61,19 @@ func (t *serviceNetworkModelBuildTask) buildModel(ctx context.Context) error { func (t *serviceNetworkModelBuildTask) buildServiceNetwork(ctx context.Context) error { spec := latticemodel.ServiceNetworkSpec{ - Name: t.gateway.Name, - Account: config.AccountID, + Name: t.gateway.Name, + Account: config.AccountID, + AssociateToVPC: false, + } + + if len(t.gateway.ObjectMeta.Annotations) > 0 { + if value, exist := t.gateway.Annotations["application-networking.k8s.aws/lattice-vpc-association"]; exist { + if value == "true" { + spec.AssociateToVPC = true + } + + } + } if !t.gateway.DeletionTimestamp.IsZero() { diff --git a/pkg/model/lattice/servicenetwork.go b/pkg/model/lattice/servicenetwork.go index b13c973e..37488428 100644 --- a/pkg/model/lattice/servicenetwork.go +++ b/pkg/model/lattice/servicenetwork.go @@ -16,9 +16,10 @@ type ServiceNetwork struct { type ServiceNetworkSpec struct { // The name of the ServiceNetwork - Name string `json:"name"` - Account string `json:"account"` - IsDeleted bool + Name string `json:"name"` + Account string `json:"account"` + AssociateToVPC bool + IsDeleted bool } type ServiceNetworkStatus struct { From 8760c56799f0be7329f4e0f8f519893f38830837 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Tue, 28 Feb 2023 15:58:44 +0000 Subject: [PATCH 02/21] Update service network create call to not to associate if the spec says not to associate --- pkg/deploy/lattice/service_network_manager.go | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index accf9d0f..c716f7ef 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -81,33 +81,37 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo } } - if isServiceNetworkAssociatedWithVPC == false { - createServiceNetworkVpcAssociationInput := vpclattice.CreateServiceNetworkVpcAssociationInput{ - ServiceNetworkIdentifier: &service_networkID, - VpcIdentifier: &config.VpcID, - } - glog.V(2).Infof("Create service_network/vpc association >>>> req[%v]\n", createServiceNetworkVpcAssociationInput) - resp, err := vpcLatticeSess.CreateServiceNetworkVpcAssociationWithContext(ctx, &createServiceNetworkVpcAssociationInput) - glog.V(2).Infof("Create service_network and vpc association here >>>> resp[%v] err [%v]\n", resp, err) - // Associate service_network with vpc - if err != nil { - glog.V(6).Infoln("ServiceNetwork is created successfully, but failed to associate service_network and vpc, err: ", err) - return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err - } else { - service_networkVPCAssociationStatus := aws.StringValue(resp.Status) - switch service_networkVPCAssociationStatus { - case vpclattice.ServiceNetworkVpcAssociationStatusCreateInProgress: - return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) - case vpclattice.ServiceNetworkVpcAssociationStatusActive: - return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: service_networkArn, ServiceNetworkID: service_networkID}, nil - case vpclattice.ServiceNetworkVpcAssociationStatusCreateFailed: - return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) - case vpclattice.ServiceNetworkVpcAssociationStatusDeleteFailed: - return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) - case vpclattice.ServiceNetworkVpcAssociationStatusDeleteInProgress: - return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) + if service_network.Spec.AssociateToVPC == true { + if isServiceNetworkAssociatedWithVPC == false { + createServiceNetworkVpcAssociationInput := vpclattice.CreateServiceNetworkVpcAssociationInput{ + ServiceNetworkIdentifier: &service_networkID, + VpcIdentifier: &config.VpcID, + } + glog.V(2).Infof("Create service_network/vpc association >>>> req[%v]\n", createServiceNetworkVpcAssociationInput) + resp, err := vpcLatticeSess.CreateServiceNetworkVpcAssociationWithContext(ctx, &createServiceNetworkVpcAssociationInput) + glog.V(2).Infof("Create service_network and vpc association here >>>> resp[%v] err [%v]\n", resp, err) + // Associate service_network with vpc + if err != nil { + glog.V(6).Infoln("ServiceNetwork is created successfully, but failed to associate service_network and vpc, err: ", err) + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err + } else { + service_networkVPCAssociationStatus := aws.StringValue(resp.Status) + switch service_networkVPCAssociationStatus { + case vpclattice.ServiceNetworkVpcAssociationStatusCreateInProgress: + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) + case vpclattice.ServiceNetworkVpcAssociationStatusActive: + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: service_networkArn, ServiceNetworkID: service_networkID}, nil + case vpclattice.ServiceNetworkVpcAssociationStatusCreateFailed: + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) + case vpclattice.ServiceNetworkVpcAssociationStatusDeleteFailed: + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) + case vpclattice.ServiceNetworkVpcAssociationStatusDeleteInProgress: + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) + } } } + } else { + glog.V(2).Infof("liwwu: Create service_network and NO vpc association here") } return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: service_networkArn, ServiceNetworkID: service_networkID}, nil } From 8abcff4364d3b1ef5a2b044d694de05bb6420f6e Mon Sep 17 00:00:00 2001 From: liwen wu Date: Tue, 28 Feb 2023 16:25:08 +0000 Subject: [PATCH 03/21] Add resource tag to indicate which VPC's controller create this service network --- pkg/deploy/lattice/service_network_manager.go | 6 ++++++ pkg/model/lattice/servicenetwork.go | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index c716f7ef..ae3b8973 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -59,9 +59,14 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo vpcLatticeSess := m.cloud.Lattice() if service_networkSummary == nil { glog.V(2).Infof("ServiceNetwork Create API here, service_network[%v] vpciID[%s]\n", service_network, config.VpcID) + // Add tag to show this is the VPC create this servicenetwork + // This means, the servicenetwork can only be deleted by the controller running in this VPC + service_networkInput := vpclattice.CreateServiceNetworkInput{ Name: &service_network.Spec.Name, + Tags: make(map[string]*string), } + service_networkInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID resp, err := vpcLatticeSess.CreateServiceNetworkWithContext(ctx, &service_networkInput) if err != nil { glog.V(6).Infoln("Failed to create service_network, err: ", err) @@ -71,6 +76,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo service_networkArn = aws.StringValue(resp.Arn) isServiceNetworkAssociatedWithVPC = false glog.V(2).Infof(" ServiceNetwork Create API resp [%v]\n", resp) + } else { glog.V(6).Infoln("service_network exists, further check association") service_networkID = aws.StringValue(service_networkSummary.Id) diff --git a/pkg/model/lattice/servicenetwork.go b/pkg/model/lattice/servicenetwork.go index 37488428..63b1c543 100644 --- a/pkg/model/lattice/servicenetwork.go +++ b/pkg/model/lattice/servicenetwork.go @@ -4,6 +4,10 @@ import ( "github.com/aws/aws-application-networking-k8s/pkg/model/core" ) +const ( + K8SServiceNetworkOwnedByVPC = "K8SServiceNetworkOwnedByVPC" +) + type ServiceNetwork struct { core.ResourceMeta `json:"-"` From f3470465cb8d37189a3e27f1b5010d570196234c Mon Sep 17 00:00:00 2001 From: liwen wu Date: Tue, 28 Feb 2023 23:32:54 +0000 Subject: [PATCH 04/21] Fixed unit test failure for service network creation --- .../lattice/service_network_manager_test.go | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index 600fcfba..f06ed587 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -15,7 +15,7 @@ import ( ) // ServiceNetwork does not exist before,happy case. -func Test_CreateServiceNetwork_MeshNotExist(t *testing.T) { +func Test_CreateServiceNetwork_MeshNotExist_NoAssociation(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ Name: "test", @@ -32,17 +32,12 @@ func Test_CreateServiceNetwork_MeshNotExist(t *testing.T) { Name: &name, } listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{} - status := vpclattice.ServiceNetworkVpcAssociationStatusActive - createServiceNetworkVPCAssociationOutput := &vpclattice.CreateServiceNetworkVpcAssociationOutput{ - Status: &status, - } + createServiceNetworkInput := &vpclattice.CreateServiceNetworkInput{ Name: &name, + Tags: make(map[string]*string), } - createServiceNetworkVpcAssociationInput := &vpclattice.CreateServiceNetworkVpcAssociationInput{ - ServiceNetworkIdentifier: &id, - VpcIdentifier: &config.VpcID, - } + createServiceNetworkInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID c := gomock.NewController(t) defer c.Finish() @@ -51,7 +46,6 @@ func Test_CreateServiceNetwork_MeshNotExist(t *testing.T) { mockVpcLatticeSess := mocks.NewMockLattice(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().CreateServiceNetworkWithContext(ctx, createServiceNetworkInput).Return(meshCreateOutput, nil) - mockVpcLatticeSess.EXPECT().CreateServiceNetworkVpcAssociationWithContext(ctx, createServiceNetworkVpcAssociationInput).Return(createServiceNetworkVPCAssociationOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) @@ -243,6 +237,7 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat } // ServiceNetwork already exists, association is ServiceNetworkVpcAssociationStatusCreateFailed. +/* TODO for association func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStatusCreateFailed(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ @@ -297,8 +292,10 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat assert.Equal(t, resp.ServiceNetworkARN, meshArn) assert.Equal(t, resp.ServiceNetworkID, meshId) } +*/ // ServiceNetwork already exists, associated with other VPC +/* TODO for association test func Test_CreateServiceNetwork_MeshAlreadyExist_MeshAssociatedWithOtherVPC(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ @@ -354,8 +351,10 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_MeshAssociatedWithOtherVPC(t *te assert.Equal(t, resp.ServiceNetworkARN, meshArn) assert.Equal(t, resp.ServiceNetworkID, meshId) } +*/ // ServiceNetwork does not exists, association is ServiceNetworkVpcAssociationStatusFailed. +/* TODO test for association func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusFailed(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ @@ -404,8 +403,10 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusFa assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } +*/ // ServiceNetwork does not exists, association is ServiceNetworkVpcAssociationStatusCreateInProgress. +/* TODO for assocition func Test_CreateServiceNetwork_MeshNOTExist_ServiceNetworkVpcAssociationStatusCreateInProgress(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ @@ -453,8 +454,10 @@ func Test_CreateServiceNetwork_MeshNOTExist_ServiceNetworkVpcAssociationStatusCr assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } +*/ // ServiceNetwork does not exists, association is ServiceNetworkVpcAssociationStatusDeleteInProgress. +/* TODO for association func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusDeleteInProgress(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ @@ -502,8 +505,10 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusDe assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } +*/ // ServiceNetwork does not exists, association returns Error. +/* TODO for association func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationReturnsError(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ @@ -548,6 +553,7 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationReturnsE assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } +*/ // Mesh does not exist and failed to create. func Test_CreateMesh_MeshNotExist_MeshCreateFailed(t *testing.T) { @@ -569,8 +575,11 @@ func Test_CreateMesh_MeshNotExist_MeshCreateFailed(t *testing.T) { listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{} meshCreateInput := &vpclattice.CreateServiceNetworkInput{ Name: &name, + Tags: make(map[string]*string), } + meshCreateInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + c := gomock.NewController(t) defer c.Finish() ctx := context.TODO() From a57d2187f2d4053a7eb9c95fd0f7ed524f9160d1 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Wed, 1 Mar 2023 01:55:32 +0000 Subject: [PATCH 05/21] Add logic to retrieve tags on service network lattice object --- pkg/deploy/lattice/service_network_manager.go | 30 +++++++++++++++---- .../lattice/service_network_manager_test.go | 7 +++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index ae3b8973..09703c9f 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -19,6 +19,11 @@ type ServiceNetworkManager interface { Delete(ctx context.Context, service_network string) error } +type serviceNetworkOutput struct { + snSummary *vpclattice.ServiceNetworkSummary + snTags *vpclattice.ListTagsForResourceOutput +} + func NewDefaultServiceNetworkManager(cloud lattice_aws.Cloud) *defaultServiceNetworkManager { return &defaultServiceNetworkManager{ cloud: cloud, @@ -79,8 +84,8 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo } else { glog.V(6).Infoln("service_network exists, further check association") - service_networkID = aws.StringValue(service_networkSummary.Id) - service_networkArn = aws.StringValue(service_networkSummary.Arn) + service_networkID = aws.StringValue(service_networkSummary.snSummary.Id) + service_networkArn = aws.StringValue(service_networkSummary.snSummary.Arn) isServiceNetworkAssociatedWithVPC, _, _, err = m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) if err != nil { return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err @@ -158,7 +163,7 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo } vpcLatticeSess := m.cloud.Lattice() - service_networkID := aws.StringValue(service_networkSummary.Id) + service_networkID := aws.StringValue(service_networkSummary.snSummary.Id) deleteNeedRetry := false _, service_networkAssociatedWithCurrentVPCId, service_networkVPCAssociations, err := m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) @@ -209,7 +214,7 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo } // Find service_network by name return service_network,err if service_network exists, otherwise return nil, nil. -func (m *defaultServiceNetworkManager) findServiceNetworkByName(ctx context.Context, targetServiceNetwork string) (*vpclattice.ServiceNetworkSummary, error) { +func (m *defaultServiceNetworkManager) findServiceNetworkByName(ctx context.Context, targetServiceNetwork string) (*serviceNetworkOutput, error) { vpcLatticeSess := m.cloud.Lattice() service_networkListInput := vpclattice.ListServiceNetworksInput{} resp, err := vpcLatticeSess.ListServiceNetworksAsList(ctx, &service_networkListInput) @@ -217,7 +222,22 @@ func (m *defaultServiceNetworkManager) findServiceNetworkByName(ctx context.Cont for _, r := range resp { if aws.StringValue(r.Name) == targetServiceNetwork { glog.V(6).Infoln("Found ServiceNetwork named ", targetServiceNetwork) - return r, err + + tagsInput := vpclattice.ListTagsForResourceInput{ + ResourceArn: r.Arn, + } + tagsOutput, err := vpcLatticeSess.ListTagsForResourceWithContext(ctx, &tagsInput) + + if err != nil { + tagsOutput = nil + } + + snOutput := serviceNetworkOutput{ + snSummary: r, + snTags: tagsOutput, + } + + return &snOutput, err } } return nil, err diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index f06ed587..618de8da 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -130,6 +130,7 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) @@ -179,6 +180,7 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) @@ -226,6 +228,7 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) @@ -638,6 +641,7 @@ func Test_DeleteMesh_MeshExistsNoAssociation(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInout).Return(deleteMeshOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() @@ -671,6 +675,7 @@ func Test_DeleteMesh_MeshExists_AssociationsWithOtherVPCExists(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) @@ -718,6 +723,7 @@ func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockVpcLatticeSess.EXPECT().DeleteServiceNetworkVpcAssociationWithContext(ctx, deleteServiceNetworkVpcAssociationInput).Return(deleteServiceNetworkVpcAssociationOutput, nil) mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInput).Return(deleteMeshOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() @@ -762,6 +768,7 @@ func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) From 16fd5caf15c57a520d909a967f20e0459bb8a202 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Wed, 1 Mar 2023 02:33:23 +0000 Subject: [PATCH 06/21] Only delete service network if it is created by this VPC --- pkg/deploy/lattice/service_network_manager.go | 34 +++++++++++++------ .../lattice/service_network_manager_test.go | 14 ++++++-- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index 09703c9f..5565a22e 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -197,19 +197,33 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo return nil } - deleteInput := vpclattice.DeleteServiceNetworkInput{ - ServiceNetworkIdentifier: &service_networkID, - } - _, err = vpcLatticeSess.DeleteServiceNetworkWithContext(ctx, &deleteInput) - if err != nil { - return err + // check if this VPC that creates the service network + needToDelete := false + if service_networkSummary.snTags != nil && service_networkSummary.snTags.Tags != nil { + snTags := service_networkSummary.snTags + vpcOwner, ok := snTags.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] + if ok && *vpcOwner == config.VpcID { + needToDelete = true + } } - if deleteNeedRetry { - return errors.New(LATTICE_RETRY) + if needToDelete { + deleteInput := vpclattice.DeleteServiceNetworkInput{ + ServiceNetworkIdentifier: &service_networkID, + } + _, err = vpcLatticeSess.DeleteServiceNetworkWithContext(ctx, &deleteInput) + if err != nil { + return err + } + + if deleteNeedRetry { + return errors.New(LATTICE_RETRY) + } else { + glog.V(6).Infof("Successfully delete service_network %v\n", service_network) + return err + } } else { - glog.V(6).Infof("Successfully delete service_network %v\n", service_network) - return err + return nil } } diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index 618de8da..9b48ddfb 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -641,7 +641,12 @@ func Test_DeleteMesh_MeshExistsNoAssociation(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) - mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) + + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInout).Return(deleteMeshOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() @@ -723,7 +728,12 @@ func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) - mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) + + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) mockVpcLatticeSess.EXPECT().DeleteServiceNetworkVpcAssociationWithContext(ctx, deleteServiceNetworkVpcAssociationInput).Return(deleteServiceNetworkVpcAssociationOutput, nil) mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInput).Return(deleteMeshOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() From 0b88ab7d48689444e45bde9e58b92e55191875d9 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Wed, 1 Mar 2023 02:50:29 +0000 Subject: [PATCH 07/21] Update to have better log msgs --- pkg/deploy/lattice/service_network_manager.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index 5565a22e..d92d90cf 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -122,7 +122,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo } } } else { - glog.V(2).Infof("liwwu: Create service_network and NO vpc association here") + glog.V(2).Infof("Create service_network(%v) without vpc association", service_network.Spec.Name) } return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: service_networkArn, ServiceNetworkID: service_networkID}, nil } @@ -219,10 +219,11 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo if deleteNeedRetry { return errors.New(LATTICE_RETRY) } else { - glog.V(6).Infof("Successfully delete service_network %v\n", service_network) + glog.V(2).Infof("Successfully delete service_network %v\n", service_network) return err } } else { + glog.V(2).Infof("Deleting service_network (%v) Skipped, since it is owned by different VPC ", service_network) return nil } } From d7f67e3c400fae8833e5033160dab47c3abc55f3 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Wed, 1 Mar 2023 20:10:33 +0000 Subject: [PATCH 08/21] Move this close to where we update httproute status --- controllers/httproute_controller.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/controllers/httproute_controller.go b/controllers/httproute_controller.go index 838ad58a..1f3dec24 100644 --- a/controllers/httproute_controller.go +++ b/controllers/httproute_controller.go @@ -270,12 +270,6 @@ func (r *HTTPRouteReconciler) updateHTTPRouteStatus(ctx context.Context, dns str glog.V(6).Infof("updateHTTPRouteStatus: httproute %v, dns %v\n", httproute, dns) httprouteOld := httproute.DeepCopy() - if len(httproute.Status.RouteStatus.Parents) == 0 { - httproute.Status.RouteStatus.Parents = make([]v1alpha2.RouteParentStatus, 1) - httproute.Status.RouteStatus.Parents[0].Conditions = make([]metav1.Condition, 1) - httproute.Status.RouteStatus.Parents[0].Conditions[0].LastTransitionTime = eventhandlers.ZeroTransitionTime - } - if len(httproute.ObjectMeta.Annotations) == 0 { httproute.ObjectMeta.Annotations = make(map[string]string) } @@ -288,7 +282,13 @@ func (r *HTTPRouteReconciler) updateHTTPRouteStatus(ctx context.Context, dns str } httprouteOld = httproute.DeepCopy() + if len(httproute.Status.RouteStatus.Parents) == 0 { + httproute.Status.RouteStatus.Parents = make([]v1alpha2.RouteParentStatus, 1) + httproute.Status.RouteStatus.Parents[0].Conditions = make([]metav1.Condition, 1) + httproute.Status.RouteStatus.Parents[0].Conditions[0].LastTransitionTime = eventhandlers.ZeroTransitionTime + } + fmt.Printf("liwwu >>>>httproute :%v \n", httproute) httproute.Status.RouteStatus.Parents[0].ControllerName = config.LatticeGatewayControllerName httproute.Status.RouteStatus.Parents[0].Conditions[0].Type = "httproute" From 247ce6eb3b34650f26e28c0d5bd27f4422cc2a02 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Wed, 1 Mar 2023 22:46:53 +0000 Subject: [PATCH 09/21] Add logic to associate or disassociate based on annotation value --- pkg/deploy/lattice/service_network_manager.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index d92d90cf..44b8603b 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -61,6 +61,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo var service_networkID string var service_networkArn string var isServiceNetworkAssociatedWithVPC bool + var service_networkAssociatedWithCurrentVPCId *string vpcLatticeSess := m.cloud.Lattice() if service_networkSummary == nil { glog.V(2).Infof("ServiceNetwork Create API here, service_network[%v] vpciID[%s]\n", service_network, config.VpcID) @@ -86,7 +87,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo glog.V(6).Infoln("service_network exists, further check association") service_networkID = aws.StringValue(service_networkSummary.snSummary.Id) service_networkArn = aws.StringValue(service_networkSummary.snSummary.Arn) - isServiceNetworkAssociatedWithVPC, _, _, err = m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) + isServiceNetworkAssociatedWithVPC, service_networkAssociatedWithCurrentVPCId, _, err = m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) if err != nil { return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err } @@ -122,6 +123,22 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo } } } else { + if isServiceNetworkAssociatedWithVPC == true { + glog.V(2).Infof("Disassociate service_network(%v) from vpc association", service_network.Spec.Name) + + deleteServiceNetworkVpcAssociationInput := vpclattice.DeleteServiceNetworkVpcAssociationInput{ + ServiceNetworkVpcAssociationIdentifier: service_networkAssociatedWithCurrentVPCId, + } + + resp, err := vpcLatticeSess.DeleteServiceNetworkVpcAssociationWithContext(ctx, &deleteServiceNetworkVpcAssociationInput) + if err != nil { + glog.V(2).Infof("Failed to delete association for %v err=%v , resp = %v\n", service_network.Spec.Name, err, resp) + } + + // return retry and check later if disassociation workflow finishes + return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) + + } glog.V(2).Infof("Create service_network(%v) without vpc association", service_network.Spec.Name) } return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: service_networkArn, ServiceNetworkID: service_networkID}, nil From a75eb401a75529a79af3844f1135774387bdbc61 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Wed, 1 Mar 2023 22:47:22 +0000 Subject: [PATCH 10/21] Fixed unit test to align with latest business logic --- .../lattice/service_network_manager_test.go | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index 9b48ddfb..bf4e18a3 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -196,8 +196,9 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStatusActive(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -240,12 +241,13 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat } // ServiceNetwork already exists, association is ServiceNetworkVpcAssociationStatusCreateFailed. -/* TODO for association + func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStatusCreateFailed(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -285,6 +287,11 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) mockVpcLatticeSess.EXPECT().CreateServiceNetworkVpcAssociationWithContext(ctx, createServiceNetworkVpcAssociationInput).Return(createServiceNetworkVPCAssociationOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() @@ -295,15 +302,14 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat assert.Equal(t, resp.ServiceNetworkARN, meshArn) assert.Equal(t, resp.ServiceNetworkID, meshId) } -*/ // ServiceNetwork already exists, associated with other VPC -/* TODO for association test func Test_CreateServiceNetwork_MeshAlreadyExist_MeshAssociatedWithOtherVPC(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -344,6 +350,11 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_MeshAssociatedWithOtherVPC(t *te mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) mockVpcLatticeSess.EXPECT().CreateServiceNetworkVpcAssociationWithContext(ctx, createServiceNetworkVpcAssociationInput).Return(createServiceNetworkVPCAssociationOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() @@ -354,15 +365,14 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_MeshAssociatedWithOtherVPC(t *te assert.Equal(t, resp.ServiceNetworkARN, meshArn) assert.Equal(t, resp.ServiceNetworkID, meshId) } -*/ // ServiceNetwork does not exists, association is ServiceNetworkVpcAssociationStatusFailed. -/* TODO test for association func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusFailed(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -382,7 +392,10 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusFa } meshCreateInput := &vpclattice.CreateServiceNetworkInput{ Name: &name, + Tags: make(map[string]*string), } + meshCreateInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + createServiceNetworkVpcAssociationInput := &vpclattice.CreateServiceNetworkVpcAssociationInput{ ServiceNetworkIdentifier: &meshId, VpcIdentifier: &config.VpcID, @@ -406,15 +419,14 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusFa assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } -*/ // ServiceNetwork does not exists, association is ServiceNetworkVpcAssociationStatusCreateInProgress. -/* TODO for assocition func Test_CreateServiceNetwork_MeshNOTExist_ServiceNetworkVpcAssociationStatusCreateInProgress(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -433,7 +445,9 @@ func Test_CreateServiceNetwork_MeshNOTExist_ServiceNetworkVpcAssociationStatusCr } meshCreateInput := &vpclattice.CreateServiceNetworkInput{ Name: &name, + Tags: make(map[string]*string), } + meshCreateInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID createServiceNetworkVpcAssociationInput := &vpclattice.CreateServiceNetworkVpcAssociationInput{ ServiceNetworkIdentifier: &meshId, VpcIdentifier: &config.VpcID, @@ -457,15 +471,14 @@ func Test_CreateServiceNetwork_MeshNOTExist_ServiceNetworkVpcAssociationStatusCr assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } -*/ // ServiceNetwork does not exists, association is ServiceNetworkVpcAssociationStatusDeleteInProgress. -/* TODO for association func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusDeleteInProgress(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -484,7 +497,9 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusDe } meshCreateInput := &vpclattice.CreateServiceNetworkInput{ Name: &name, + Tags: make(map[string]*string), } + meshCreateInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID createServiceNetworkVpcAssociationInput := &vpclattice.CreateServiceNetworkVpcAssociationInput{ ServiceNetworkIdentifier: &meshId, VpcIdentifier: &config.VpcID, @@ -508,15 +523,14 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationStatusDe assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } -*/ // ServiceNetwork does not exists, association returns Error. -/* TODO for association func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationReturnsError(t *testing.T) { CreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -532,7 +546,9 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationReturnsE } meshCreateInput := &vpclattice.CreateServiceNetworkInput{ Name: &name, + Tags: make(map[string]*string), } + meshCreateInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID createServiceNetworkVpcAssociationInput := &vpclattice.CreateServiceNetworkVpcAssociationInput{ ServiceNetworkIdentifier: &meshId, VpcIdentifier: &config.VpcID, @@ -556,7 +572,6 @@ func Test_CreateServiceNetwork_MeshNotExist_ServiceNetworkVpcAssociationReturnsE assert.Equal(t, resp.ServiceNetworkARN, "") assert.Equal(t, resp.ServiceNetworkID, "") } -*/ // Mesh does not exist and failed to create. func Test_CreateMesh_MeshNotExist_MeshCreateFailed(t *testing.T) { From a00f930f993829faa76ba8b4384e21a4130c0009 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 02:10:32 +0000 Subject: [PATCH 11/21] Update unit test --- .../lattice/service_network_manager_test.go | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index bf4e18a3..273bcf74 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -18,8 +18,9 @@ import ( func Test_CreateServiceNetwork_MeshNotExist_NoAssociation(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: false, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -97,8 +98,9 @@ func Test_CreateServiceNetwork_ListFailed(t *testing.T) { func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStatusCreateInProgress(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ - Name: "test", - Account: "123456789", + Name: "test", + Account: "123456789", + AssociateToVPC: true, }, Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, } @@ -353,7 +355,8 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_MeshAssociatedWithOtherVPC(t *te snTagsOuput := &vpclattice.ListTagsForResourceOutput{ Tags: make(map[string]*string), } - snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + dummy_vpc := "dummy-vpc-id" + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &dummy_vpc mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) mockVpcLatticeSess.EXPECT().CreateServiceNetworkVpcAssociationWithContext(ctx, createServiceNetworkVpcAssociationInput).Return(createServiceNetworkVPCAssociationOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() @@ -633,6 +636,7 @@ func Test_DeleteMesh_MeshNotExist(t *testing.T) { assert.Nil(t, err) } +// delte a service network, which has no association and also was created by this VPC func Test_DeleteMesh_MeshExistsNoAssociation(t *testing.T) { arn := "123456789" id := "123456789" @@ -695,7 +699,11 @@ func Test_DeleteMesh_MeshExists_AssociationsWithOtherVPCExists(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) - mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) From 7022e5c7d9fb42692aaffe97e13d8130c1f406eb Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 03:05:56 +0000 Subject: [PATCH 12/21] Refact delete logic and unit test(s) --- pkg/deploy/lattice/service_network_manager.go | 54 ++++++-------- .../lattice/service_network_manager_test.go | 71 +++++++++++-------- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index 44b8603b..0c0538e7 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -181,37 +181,27 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo vpcLatticeSess := m.cloud.Lattice() service_networkID := aws.StringValue(service_networkSummary.snSummary.Id) - deleteNeedRetry := false - _, service_networkAssociatedWithCurrentVPCId, service_networkVPCAssociations, err := m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) + _, service_networkAssociatedWithCurrentVPCId, _, err := m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) if err != nil { return err } - totalAssociation := len(service_networkVPCAssociations) - if totalAssociation == 0 { - deleteNeedRetry = false - } else if service_networkAssociatedWithCurrentVPCId != nil { - if err == errors.New(LATTICE_RETRY) { - // The current association is in progress - deleteNeedRetry = true - return errors.New(LATTICE_RETRY) - } else { - // Happy case, this is the last association - deleteNeedRetry = true - deleteServiceNetworkVpcAssociationInput := vpclattice.DeleteServiceNetworkVpcAssociationInput{ - ServiceNetworkVpcAssociationIdentifier: service_networkAssociatedWithCurrentVPCId, - } - glog.V(2).Infof("DeleteServiceNetworkVpcAssociationInput >>>> %v\n", deleteServiceNetworkVpcAssociationInput) - resp, err := vpcLatticeSess.DeleteServiceNetworkVpcAssociationWithContext(ctx, &deleteServiceNetworkVpcAssociationInput) - if err != nil { - glog.V(6).Infof("Failed to delete association %v \n", err) - } - glog.V(2).Infof("DeleteServiceNetworkVPCAssociationResp: service_network %v , resp %v, err %v \n", service_network, resp, err) + if service_networkAssociatedWithCurrentVPCId != nil { + // current VPC is associated with this service network + + // Happy case, disassociate the VPC from service network + deleteServiceNetworkVpcAssociationInput := vpclattice.DeleteServiceNetworkVpcAssociationInput{ + ServiceNetworkVpcAssociationIdentifier: service_networkAssociatedWithCurrentVPCId, } - } else { - // there are other Associations left for this service_network, could not delete - deleteNeedRetry = true - return nil + glog.V(2).Infof("DeleteServiceNetworkVpcAssociationInput >>>> %v\n", deleteServiceNetworkVpcAssociationInput) + resp, err := vpcLatticeSess.DeleteServiceNetworkVpcAssociationWithContext(ctx, &deleteServiceNetworkVpcAssociationInput) + if err != nil { + glog.V(2).Infof("Failed to delete association %v \n", err) + } + glog.V(2).Infof("DeleteServiceNetworkVPCAssociationResp: service_network %v , resp %v, err %v \n", service_network, resp, err) + // retry later to check if VPC disassociation workflow finishes + return errors.New(LATTICE_RETRY) + } // check if this VPC that creates the service network @@ -225,20 +215,18 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo } if needToDelete { + deleteInput := vpclattice.DeleteServiceNetworkInput{ ServiceNetworkIdentifier: &service_networkID, } _, err = vpcLatticeSess.DeleteServiceNetworkWithContext(ctx, &deleteInput) if err != nil { - return err - } - - if deleteNeedRetry { return errors.New(LATTICE_RETRY) - } else { - glog.V(2).Infof("Successfully delete service_network %v\n", service_network) - return err } + + glog.V(2).Infof("Successfully delete service_network %v\n", service_network) + return err + } else { glog.V(2).Infof("Deleting service_network (%v) Skipped, since it is owned by different VPC ", service_network) return nil diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index 273bcf74..28e841d3 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -675,22 +675,38 @@ func Test_DeleteMesh_MeshExistsNoAssociation(t *testing.T) { assert.Nil(t, err) } -func Test_DeleteMesh_MeshExists_AssociationsWithOtherVPCExists(t *testing.T) { +// Deleting a service netwrok, when +// * the service network is associated with current VPC +// * and it is this VPC creates this service network +func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { arn := "123456789" id := "123456789" name := "test" - vpcId := "123456789" - item := vpclattice.ServiceNetworkSummary{ + itemMesh := vpclattice.ServiceNetworkSummary{ Arn: &arn, Id: &id, Name: &name, } - listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{&item} + listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{&itemMesh} - ServiceNetworkVpcAssociationSummaryItem := vpclattice.ServiceNetworkVpcAssociationSummary{ - VpcId: &vpcId, + associationArn := "123456789" + associationID := "123456789" + associationStatus := vpclattice.ServiceNetworkVpcAssociationStatusActive + associationVPCId := config.VpcID + itemAssociation := vpclattice.ServiceNetworkVpcAssociationSummary{ + Arn: &associationArn, + Id: &associationID, + ServiceNetworkArn: &arn, + ServiceNetworkId: &id, + ServiceNetworkName: &name, + Status: &associationStatus, + VpcId: &associationVPCId, } - statusServiceNetworkVPCOutput := []*vpclattice.ServiceNetworkVpcAssociationSummary{&ServiceNetworkVpcAssociationSummaryItem} + statusServiceNetworkVPCOutput := []*vpclattice.ServiceNetworkVpcAssociationSummary{&itemAssociation} + + deleteInProgressStatus := vpclattice.ServiceNetworkVpcAssociationStatusDeleteInProgress + deleteServiceNetworkVpcAssociationOutput := &vpclattice.DeleteServiceNetworkVpcAssociationOutput{Status: &deleteInProgressStatus} + deleteServiceNetworkVpcAssociationInput := &vpclattice.DeleteServiceNetworkVpcAssociationInput{ServiceNetworkVpcAssociationIdentifier: &associationID} c := gomock.NewController(t) defer c.Finish() @@ -699,20 +715,23 @@ func Test_DeleteMesh_MeshExists_AssociationsWithOtherVPCExists(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ Tags: make(map[string]*string), } snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) + mockVpcLatticeSess.EXPECT().DeleteServiceNetworkVpcAssociationWithContext(ctx, deleteServiceNetworkVpcAssociationInput).Return(deleteServiceNetworkVpcAssociationOutput, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) err := meshManager.Delete(ctx, "test") - assert.Nil(t, err) + assert.NotNil(t, err) + assert.Equal(t, err, errors.New(LATTICE_RETRY)) } -func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { +func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC_NotCreatedByVPC(t *testing.T) { arn := "123456789" id := "123456789" name := "test" @@ -726,7 +745,7 @@ func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { associationArn := "123456789" associationID := "123456789" associationStatus := vpclattice.ServiceNetworkVpcAssociationStatusActive - associationVPCId := config.VpcID + associationVPCId := "123456789" itemAssociation := vpclattice.ServiceNetworkVpcAssociationSummary{ Arn: &associationArn, Id: &associationID, @@ -738,12 +757,6 @@ func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { } statusServiceNetworkVPCOutput := []*vpclattice.ServiceNetworkVpcAssociationSummary{&itemAssociation} - deleteInProgressStatus := vpclattice.ServiceNetworkVpcAssociationStatusDeleteInProgress - deleteServiceNetworkVpcAssociationOutput := &vpclattice.DeleteServiceNetworkVpcAssociationOutput{Status: &deleteInProgressStatus} - deleteMeshOutput := &vpclattice.DeleteServiceNetworkOutput{} - deleteServiceNetworkVpcAssociationInput := &vpclattice.DeleteServiceNetworkVpcAssociationInput{ServiceNetworkVpcAssociationIdentifier: &associationID} - deleteMeshInput := &vpclattice.DeleteServiceNetworkInput{ServiceNetworkIdentifier: &id} - c := gomock.NewController(t) defer c.Finish() ctx := context.TODO() @@ -751,24 +764,16 @@ func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) - - snTagsOuput := &vpclattice.ListTagsForResourceOutput{ - Tags: make(map[string]*string), - } - snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID - mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) - mockVpcLatticeSess.EXPECT().DeleteServiceNetworkVpcAssociationWithContext(ctx, deleteServiceNetworkVpcAssociationInput).Return(deleteServiceNetworkVpcAssociationOutput, nil) - mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInput).Return(deleteMeshOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) err := meshManager.Delete(ctx, "test") - assert.NotNil(t, err) - assert.Equal(t, err, errors.New(LATTICE_RETRY)) + assert.Nil(t, err) } -func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC(t *testing.T) { +func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC_CreatedByVPC(t *testing.T) { arn := "123456789" id := "123456789" name := "test" @@ -801,13 +806,21 @@ func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC(t *testing.T) { mockCloud := mocks_aws.NewMockCloud(c) mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) - mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) + snTagsOutput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOutput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOutput, nil) + deleteMeshOutput := &vpclattice.DeleteServiceNetworkOutput{} + deleteMeshInout := &vpclattice.DeleteServiceNetworkInput{ServiceNetworkIdentifier: &id} + mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInout).Return(deleteMeshOutput, errors.New("404")) mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) err := meshManager.Delete(ctx, "test") - assert.Nil(t, err) + assert.NotNil(t, err) + assert.Equal(t, err, errors.New(LATTICE_RETRY)) } func Test_ListMesh_MeshExists(t *testing.T) { From 18cfa4f38da499179d46cb34e38d2ff0dd0bb195 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 03:10:46 +0000 Subject: [PATCH 13/21] minor refactor delete routine --- pkg/deploy/lattice/service_network_manager.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index 0c0538e7..b3692da1 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -167,15 +167,8 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo return err } - var ifServiceNetworkExist bool if service_networkSummary == nil { - ifServiceNetworkExist = false - } else { - ifServiceNetworkExist = true - } - - if ifServiceNetworkExist == false { - glog.V(6).Infof("ServiceNetworkManager-Delete, successfully deleting unknown service_network %v\n", service_network) + glog.V(6).Infof("Successfully deleted unknown service_network %v\n", service_network) return nil } @@ -204,7 +197,7 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo } - // check if this VPC that creates the service network + // check if this VPC that created the service network needToDelete := false if service_networkSummary.snTags != nil && service_networkSummary.snTags.Tags != nil { snTags := service_networkSummary.snTags From 2249f50772d5dd5bd8671f6e341f81a594c23489 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 16:12:46 +0000 Subject: [PATCH 14/21] Update debug msgs in create routine --- pkg/deploy/lattice/service_network_manager.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index b3692da1..08a88b06 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -64,7 +64,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo var service_networkAssociatedWithCurrentVPCId *string vpcLatticeSess := m.cloud.Lattice() if service_networkSummary == nil { - glog.V(2).Infof("ServiceNetwork Create API here, service_network[%v] vpciID[%s]\n", service_network, config.VpcID) + glog.V(2).Infof("Create ServiceNetwork, service_network[%v] and tag it with vpciID[%s]\n", service_network, config.VpcID) // Add tag to show this is the VPC create this servicenetwork // This means, the servicenetwork can only be deleted by the controller running in this VPC @@ -75,16 +75,16 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo service_networkInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID resp, err := vpcLatticeSess.CreateServiceNetworkWithContext(ctx, &service_networkInput) if err != nil { - glog.V(6).Infoln("Failed to create service_network, err: ", err) + glog.V(2).Infof("Failed to create service_network[%v], err: %v", service_network, err) return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err } service_networkID = aws.StringValue(resp.Id) service_networkArn = aws.StringValue(resp.Arn) isServiceNetworkAssociatedWithVPC = false - glog.V(2).Infof(" ServiceNetwork Create API resp [%v]\n", resp) + glog.V(6).Infof(" ServiceNetwork Create API resp [%v]\n", resp) } else { - glog.V(6).Infoln("service_network exists, further check association") + glog.V(6).Infof("service_network[%v] exists, further check association", service_network) service_networkID = aws.StringValue(service_networkSummary.snSummary.Id) service_networkArn = aws.StringValue(service_networkSummary.snSummary.Arn) isServiceNetworkAssociatedWithVPC, service_networkAssociatedWithCurrentVPCId, _, err = m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) @@ -95,6 +95,8 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo if service_network.Spec.AssociateToVPC == true { if isServiceNetworkAssociatedWithVPC == false { + // current state: service network is associated to VPC + // desired state: associate this service network to VPC createServiceNetworkVpcAssociationInput := vpclattice.CreateServiceNetworkVpcAssociationInput{ ServiceNetworkIdentifier: &service_networkID, VpcIdentifier: &config.VpcID, @@ -104,7 +106,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo glog.V(2).Infof("Create service_network and vpc association here >>>> resp[%v] err [%v]\n", resp, err) // Associate service_network with vpc if err != nil { - glog.V(6).Infoln("ServiceNetwork is created successfully, but failed to associate service_network and vpc, err: ", err) + glog.V(2).Infof("Failed to associate service_network[%v] and vpc, err: %v", service_network, err) return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err } else { service_networkVPCAssociationStatus := aws.StringValue(resp.Status) @@ -124,6 +126,8 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo } } else { if isServiceNetworkAssociatedWithVPC == true { + // current state: service network is associated to VPC + // desired state: not to associate this service network to VPC glog.V(2).Infof("Disassociate service_network(%v) from vpc association", service_network.Spec.Name) deleteServiceNetworkVpcAssociationInput := vpclattice.DeleteServiceNetworkVpcAssociationInput{ From 3f6f7ddf63b046c5f6906be3648033ac21d81a22 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 16:32:47 +0000 Subject: [PATCH 15/21] Update debug msg and also avoid call delete API if there are VPC associations --- pkg/deploy/lattice/service_network_manager.go | 30 +++++++++++++------ .../lattice/service_network_manager_test.go | 4 +-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index 08a88b06..4eaa9536 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -73,7 +73,10 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo Tags: make(map[string]*string), } service_networkInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + + glog.V(2).Infof("Create service_network >>>> req[%v]", service_networkInput) resp, err := vpcLatticeSess.CreateServiceNetworkWithContext(ctx, &service_networkInput) + glog.V(2).Infof("Create service_network >>>> resp[%v], err : %v", resp, err) if err != nil { glog.V(2).Infof("Failed to create service_network[%v], err: %v", service_network, err) return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err @@ -101,7 +104,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo ServiceNetworkIdentifier: &service_networkID, VpcIdentifier: &config.VpcID, } - glog.V(2).Infof("Create service_network/vpc association >>>> req[%v]\n", createServiceNetworkVpcAssociationInput) + glog.V(2).Infof("Create service_network/vpc association >>>> req[%v]", createServiceNetworkVpcAssociationInput) resp, err := vpcLatticeSess.CreateServiceNetworkVpcAssociationWithContext(ctx, &createServiceNetworkVpcAssociationInput) glog.V(2).Infof("Create service_network and vpc association here >>>> resp[%v] err [%v]\n", resp, err) // Associate service_network with vpc @@ -128,13 +131,15 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo if isServiceNetworkAssociatedWithVPC == true { // current state: service network is associated to VPC // desired state: not to associate this service network to VPC - glog.V(2).Infof("Disassociate service_network(%v) from vpc association", service_network.Spec.Name) + glog.V(6).Infof("Disassociate service_network(%v) from vpc association", service_network.Spec.Name) deleteServiceNetworkVpcAssociationInput := vpclattice.DeleteServiceNetworkVpcAssociationInput{ ServiceNetworkVpcAssociationIdentifier: service_networkAssociatedWithCurrentVPCId, } + glog.V(2).Infof("Delete service_network association >>>> req[%v]", deleteServiceNetworkVpcAssociationInput) resp, err := vpcLatticeSess.DeleteServiceNetworkVpcAssociationWithContext(ctx, &deleteServiceNetworkVpcAssociationInput) + glog.V(2).Infof("Delete service_network association >>>> resp[%v],err [%v]", resp, err) if err != nil { glog.V(2).Infof("Failed to delete association for %v err=%v , resp = %v\n", service_network.Spec.Name, err, resp) } @@ -143,7 +148,7 @@ func (m *defaultServiceNetworkManager) Create(ctx context.Context, service_netwo return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) } - glog.V(2).Infof("Create service_network(%v) without vpc association", service_network.Spec.Name) + glog.V(2).Infof("Created service_network(%v) without vpc association", service_network.Spec.Name) } return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: service_networkArn, ServiceNetworkID: service_networkID}, nil } @@ -172,14 +177,14 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo } if service_networkSummary == nil { - glog.V(6).Infof("Successfully deleted unknown service_network %v\n", service_network) + glog.V(2).Infof("Successfully deleted unknown service_network %v\n", service_network) return nil } vpcLatticeSess := m.cloud.Lattice() service_networkID := aws.StringValue(service_networkSummary.snSummary.Id) - _, service_networkAssociatedWithCurrentVPCId, _, err := m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) + _, service_networkAssociatedWithCurrentVPCId, assocResp, err := m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) if err != nil { return err } @@ -192,16 +197,16 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo } glog.V(2).Infof("DeleteServiceNetworkVpcAssociationInput >>>> %v\n", deleteServiceNetworkVpcAssociationInput) resp, err := vpcLatticeSess.DeleteServiceNetworkVpcAssociationWithContext(ctx, &deleteServiceNetworkVpcAssociationInput) + glog.V(2).Infof("DeleteServiceNetworkVPCAssociationResp: service_network %v , resp %v, err %v \n", service_network, resp, err) if err != nil { - glog.V(2).Infof("Failed to delete association %v \n", err) + glog.V(2).Infof("Failed to delete association for %v, err: %v \n", service_network, err) } - glog.V(2).Infof("DeleteServiceNetworkVPCAssociationResp: service_network %v , resp %v, err %v \n", service_network, resp, err) // retry later to check if VPC disassociation workflow finishes return errors.New(LATTICE_RETRY) } - // check if this VPC that created the service network + // check if this VPC is the one created the service network needToDelete := false if service_networkSummary.snTags != nil && service_networkSummary.snTags.Tags != nil { snTags := service_networkSummary.snTags @@ -213,10 +218,17 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo if needToDelete { + if len(assocResp) != 0 { + glog.V(6).Infof("Retry deleting %v later, due to service network still has VPCs associated", service_network) + return errors.New(LATTICE_RETRY) + } + deleteInput := vpclattice.DeleteServiceNetworkInput{ ServiceNetworkIdentifier: &service_networkID, } - _, err = vpcLatticeSess.DeleteServiceNetworkWithContext(ctx, &deleteInput) + glog.V(2).Infof("DeleteServiceNetworkWithContext: service_network %v", service_network) + resp, err := vpcLatticeSess.DeleteServiceNetworkWithContext(ctx, &deleteInput) + glog.V(2).Infof("DeleteServiceNetworkWithContext: service_network %v , resp %v, err %v \n", service_network, resp, err) if err != nil { return errors.New(LATTICE_RETRY) } diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index 28e841d3..5a343433 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -811,9 +811,7 @@ func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC_CreatedByVPC(t *testing.T) } snTagsOutput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOutput, nil) - deleteMeshOutput := &vpclattice.DeleteServiceNetworkOutput{} - deleteMeshInout := &vpclattice.DeleteServiceNetworkInput{ServiceNetworkIdentifier: &id} - mockVpcLatticeSess.EXPECT().DeleteServiceNetworkWithContext(ctx, deleteMeshInout).Return(deleteMeshOutput, errors.New("404")) + mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() meshManager := NewDefaultServiceNetworkManager(mockCloud) From 374ed34bde1eca4ce8eeeab9bee00ff61004c4c0 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 18:12:40 +0000 Subject: [PATCH 16/21] Add some more unit test(s) --- .../lattice/service_network_manager_test.go | 153 +++++++++++++++++- .../model_build_service_network_test.go | 47 ++++-- pkg/gateway/model_build_servicenetwork.go | 5 +- 3 files changed, 193 insertions(+), 12 deletions(-) diff --git a/pkg/deploy/lattice/service_network_manager_test.go b/pkg/deploy/lattice/service_network_manager_test.go index 5a343433..e016535f 100644 --- a/pkg/deploy/lattice/service_network_manager_test.go +++ b/pkg/deploy/lattice/service_network_manager_test.go @@ -15,7 +15,7 @@ import ( ) // ServiceNetwork does not exist before,happy case. -func Test_CreateServiceNetwork_MeshNotExist_NoAssociation(t *testing.T) { +func Test_CreateServiceNetwork_MeshNotExist_NoNeedToAssociate(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ Spec: latticemodel.ServiceNetworkSpec{ Name: "test", @@ -57,6 +57,58 @@ func Test_CreateServiceNetwork_MeshNotExist_NoAssociation(t *testing.T) { assert.Equal(t, resp.ServiceNetworkID, id) } +func Test_CreateServiceNetwork_MeshNotExist_NeedToAssociate(t *testing.T) { + meshCreateInput := latticemodel.ServiceNetwork{ + Spec: latticemodel.ServiceNetworkSpec{ + Name: "test", + Account: "123456789", + AssociateToVPC: true, + }, + Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, + } + arn := "12345678912345678912" + id := "12345678912345678912" + name := "test" + meshCreateOutput := &vpclattice.CreateServiceNetworkOutput{ + Arn: &arn, + Id: &id, + Name: &name, + } + listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{} + + createServiceNetworkInput := &vpclattice.CreateServiceNetworkInput{ + Name: &name, + Tags: make(map[string]*string), + } + createServiceNetworkInput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + + c := gomock.NewController(t) + defer c.Finish() + ctx := context.TODO() + mockCloud := mocks_aws.NewMockCloud(c) + mockVpcLatticeSess := mocks.NewMockLattice(c) + mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) + mockVpcLatticeSess.EXPECT().CreateServiceNetworkWithContext(ctx, createServiceNetworkInput).Return(meshCreateOutput, nil) + meshId := "12345678912345678912" + createServiceNetworkVpcAssociationInput := &vpclattice.CreateServiceNetworkVpcAssociationInput{ + ServiceNetworkIdentifier: &meshId, + VpcIdentifier: &config.VpcID, + } + associationStatus := vpclattice.ServiceNetworkVpcAssociationStatusUpdateInProgress + createServiceNetworkVPCAssociationOutput := &vpclattice.CreateServiceNetworkVpcAssociationOutput{ + Status: &associationStatus, + } + mockVpcLatticeSess.EXPECT().CreateServiceNetworkVpcAssociationWithContext(ctx, createServiceNetworkVpcAssociationInput).Return(createServiceNetworkVPCAssociationOutput, nil) + mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() + + meshManager := NewDefaultServiceNetworkManager(mockCloud) + resp, err := meshManager.Create(ctx, &meshCreateInput) + + assert.Nil(t, err) + assert.Equal(t, resp.ServiceNetworkARN, arn) + assert.Equal(t, resp.ServiceNetworkID, id) +} + // List and find mesh does not work. func Test_CreateServiceNetwork_ListFailed(t *testing.T) { meshCreateInput := latticemodel.ServiceNetwork{ @@ -242,6 +294,57 @@ func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStat assert.Equal(t, resp.ServiceNetworkID, meshId) } +func Test_CreateServiceNetwork_MeshAlreadyExist_AssociateToNotAssociate(t *testing.T) { + meshCreateInput := latticemodel.ServiceNetwork{ + Spec: latticemodel.ServiceNetworkSpec{ + Name: "test", + Account: "123456789", + AssociateToVPC: false, + }, + Status: &latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, + } + meshId := "12345678912345678912" + meshArn := "12345678912345678912" + name := "test" + item := vpclattice.ServiceNetworkSummary{ + Arn: &meshArn, + Id: &meshId, + Name: &name, + } + listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{&item} + + status := vpclattice.ServiceNetworkVpcAssociationStatusActive + items := vpclattice.ServiceNetworkVpcAssociationSummary{ + ServiceNetworkArn: &meshArn, + ServiceNetworkId: &meshId, + ServiceNetworkName: &meshId, + Status: &status, + VpcId: &config.VpcID, + } + statusServiceNetworkVPCOutput := []*vpclattice.ServiceNetworkVpcAssociationSummary{&items} + + c := gomock.NewController(t) + defer c.Finish() + ctx := context.TODO() + mockVpcLatticeSess := mocks.NewMockLattice(c) + mockCloud := mocks_aws.NewMockCloud(c) + mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) + mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(nil, nil) + deleteInProgressStatus := vpclattice.ServiceNetworkVpcAssociationStatusDeleteInProgress + deleteServiceNetworkVpcAssociationOutput := &vpclattice.DeleteServiceNetworkVpcAssociationOutput{Status: &deleteInProgressStatus} + + mockVpcLatticeSess.EXPECT().DeleteServiceNetworkVpcAssociationWithContext(ctx, gomock.Any()).Return(deleteServiceNetworkVpcAssociationOutput, nil) + + mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() + + meshManager := NewDefaultServiceNetworkManager(mockCloud) + _, err := meshManager.Create(ctx, &meshCreateInput) + + assert.Equal(t, err, errors.New(LATTICE_RETRY)) + +} + // ServiceNetwork already exists, association is ServiceNetworkVpcAssociationStatusCreateFailed. func Test_CreateServiceNetwork_MeshAlreadyExist_ServiceNetworkVpcAssociationStatusCreateFailed(t *testing.T) { @@ -731,6 +834,54 @@ func Test_DeleteMesh_MeshExistsAssociatedWithVPC_Deleting(t *testing.T) { assert.Equal(t, err, errors.New(LATTICE_RETRY)) } +func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC(t *testing.T) { + arn := "123456789" + id := "123456789" + name := "test" + itemMesh := vpclattice.ServiceNetworkSummary{ + Arn: &arn, + Id: &id, + Name: &name, + } + listServiceNetworkOutput := []*vpclattice.ServiceNetworkSummary{&itemMesh} + + associationArn := "123456789" + associationID := "123456789" + associationStatus := vpclattice.ServiceNetworkVpcAssociationStatusActive + associationVPCId := "other-vpc-id" + itemAssociation := vpclattice.ServiceNetworkVpcAssociationSummary{ + Arn: &associationArn, + Id: &associationID, + ServiceNetworkArn: &arn, + ServiceNetworkId: &id, + ServiceNetworkName: &name, + Status: &associationStatus, + VpcId: &associationVPCId, + } + statusServiceNetworkVPCOutput := []*vpclattice.ServiceNetworkVpcAssociationSummary{&itemAssociation} + + c := gomock.NewController(t) + defer c.Finish() + ctx := context.TODO() + mockVpcLatticeSess := mocks.NewMockLattice(c) + mockCloud := mocks_aws.NewMockCloud(c) + mockVpcLatticeSess.EXPECT().ListServiceNetworksAsList(ctx, gomock.Any()).Return(listServiceNetworkOutput, nil) + mockVpcLatticeSess.EXPECT().ListServiceNetworkVpcAssociationsAsList(ctx, gomock.Any()).Return(statusServiceNetworkVPCOutput, nil) + + snTagsOuput := &vpclattice.ListTagsForResourceOutput{ + Tags: make(map[string]*string), + } + snTagsOuput.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] = &config.VpcID + mockVpcLatticeSess.EXPECT().ListTagsForResourceWithContext(ctx, gomock.Any()).Return(snTagsOuput, nil) + mockCloud.EXPECT().Lattice().Return(mockVpcLatticeSess).AnyTimes() + + meshManager := NewDefaultServiceNetworkManager(mockCloud) + err := meshManager.Delete(ctx, "test") + + assert.NotNil(t, err) + assert.Equal(t, err, errors.New(LATTICE_RETRY)) +} + func Test_DeleteMesh_MeshExistsAssociatedWithOtherVPC_NotCreatedByVPC(t *testing.T) { arn := "123456789" id := "123456789" diff --git a/pkg/gateway/model_build_service_network_test.go b/pkg/gateway/model_build_service_network_test.go index 899ea6f7..41b19853 100644 --- a/pkg/gateway/model_build_service_network_test.go +++ b/pkg/gateway/model_build_service_network_test.go @@ -13,22 +13,50 @@ import ( func Test_MeshModelBuild(t *testing.T) { now := metav1.Now() tests := []struct { - name string - gw *v1alpha2.Gateway - wantErr error - wantName string - wantIsDeleted bool + name string + gw *v1alpha2.Gateway + wantErr error + wantName string + wantIsDeleted bool + associateToVPC bool }{ { - name: "Adding Mesh", + name: "Adding Mesh, no annotation on VPC association", gw: &v1alpha2.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "mesh1", }, }, - wantErr: nil, - wantName: "mesh1", - wantIsDeleted: false, + wantErr: nil, + wantName: "mesh1", + wantIsDeleted: false, + associateToVPC: false, + }, + { + name: "Adding Mesh, and need VPC association", + gw: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mesh1", + Annotations: map[string]string{LatticeVPCAssociationAnnotation: "true"}, + }, + }, + wantErr: nil, + wantName: "mesh1", + wantIsDeleted: false, + associateToVPC: true, + }, + { + name: "Adding Mesh, and need VPC association", + gw: &v1alpha2.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mesh1", + Annotations: map[string]string{LatticeVPCAssociationAnnotation: "false"}, + }, + }, + wantErr: nil, + wantName: "mesh1", + wantIsDeleted: false, + associateToVPC: false, }, { name: "Deleting Mesh", @@ -56,6 +84,7 @@ func Test_MeshModelBuild(t *testing.T) { } else { assert.Equal(t, tt.wantName, got.Spec.Name) assert.Equal(t, tt.wantIsDeleted, got.Spec.IsDeleted) + assert.Equal(t, tt.associateToVPC, got.Spec.AssociateToVPC) } }) diff --git a/pkg/gateway/model_build_servicenetwork.go b/pkg/gateway/model_build_servicenetwork.go index dd7eb092..f883ca3b 100644 --- a/pkg/gateway/model_build_servicenetwork.go +++ b/pkg/gateway/model_build_servicenetwork.go @@ -13,7 +13,8 @@ import ( ) const ( - ResourceIDServiceNetwork = "ServiceNetwork" + ResourceIDServiceNetwork = "ServiceNetwork" + LatticeVPCAssociationAnnotation = "application-networking.k8s.aws/lattice-vpc-association" ) // ModelBuilder builds the model stack for the mesh resource. @@ -67,7 +68,7 @@ func (t *serviceNetworkModelBuildTask) buildServiceNetwork(ctx context.Context) } if len(t.gateway.ObjectMeta.Annotations) > 0 { - if value, exist := t.gateway.Annotations["application-networking.k8s.aws/lattice-vpc-association"]; exist { + if value, exist := t.gateway.Annotations[LatticeVPCAssociationAnnotation]; exist { if value == "true" { spec.AssociateToVPC = true } From 2b3ed1861204fdf6d3697c70173d5f7f14f9034a Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 19:40:50 +0000 Subject: [PATCH 17/21] Re-enable servicenetowrk reconcile deleting staled SDK SNs --- pkg/deploy/lattice/service_network_synthesizer.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pkg/deploy/lattice/service_network_synthesizer.go b/pkg/deploy/lattice/service_network_synthesizer.go index 2b32294d..ba903d5e 100644 --- a/pkg/deploy/lattice/service_network_synthesizer.go +++ b/pkg/deploy/lattice/service_network_synthesizer.go @@ -39,21 +39,16 @@ func (s *serviceNetworkSynthesizer) Synthesize(ctx context.Context) error { ret = LATTICE_RETRY } - /* TODO - * support following when we have tagging enabled, so that K8S will NOT accidently delete - * other serviceNetworkes - - if err := s.synthesizeSDKServiceNetworks(ctx); err != nil { ret = LATTICE_RETRY } - */ //TODO // https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/pkg/deploy/elbv2/load_balancer_synthesizer.go#L46 if ret != "" { return errors.New(ret) } else { + glog.V(6).Infof("Finish synthesizing ServiceNetworks/Gateways ... \n") return nil } @@ -109,7 +104,7 @@ func (s *serviceNetworkSynthesizer) synthesizeSDKServiceNetworks(ctx context.Con var ret = "" sdkServiceNetworks, err := s.serviceNetworkManager.List(ctx) if err != nil { - glog.V(6).Infof("Synthesize failed on List lattice serviceNetworkes %v\n", err) + glog.V(2).Infof("Synthesize failed on List lattice serviceNetworkes %v\n", err) return err } glog.V(6).Infof("SDK List: %v \n", sdkServiceNetworks) @@ -136,16 +131,18 @@ func (s *serviceNetworkSynthesizer) synthesizeSDKServiceNetworks(ctx context.Con if toBeDeleted { - glog.V(6).Infof("Synthesizing Gateway: Delete stale sdkServiceNetwork %v\n", sdkServiceNetwork) + glog.V(2).Infof("Synthesizing Gateway: Delete stale sdkServiceNetwork %v\n", sdkServiceNetwork) err := s.serviceNetworkManager.Delete(ctx, sdkServiceNetwork) if err != nil { + glog.V(6).Infof("Need to retry synthesizing err %v", err) ret = LATTICE_RETRY } } } if ret != "" { + glog.V(2).Infof("Need to retry synthesizing, reg = %v", ret) return errors.New(ret) } else { return nil From 07e2a410394162ed0b53d0030f9bfb6b7275439b Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 19:41:39 +0000 Subject: [PATCH 18/21] Update not to update timestamp in every reconcile loop which cause controller in loops --- controllers/gateway_controller.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/gateway_controller.go b/controllers/gateway_controller.go index 91cab32a..bf327cec 100644 --- a/controllers/gateway_controller.go +++ b/controllers/gateway_controller.go @@ -249,7 +249,9 @@ func (r *GatewayReconciler) updateGatewayStatus(ctx context.Context, serviceNetw //if gw.Status.Conditions[0].LastTransitionTime == eventhandlers.ZeroTransitionTime { glog.V(6).Infof("updateGatewayStatus: updating last transition time \n") - gw.Status.Conditions[0].LastTransitionTime = metav1.NewTime(time.Now()) + if gw.Status.Conditions[0].LastTransitionTime == eventhandlers.ZeroTransitionTime { + gw.Status.Conditions[0].LastTransitionTime = metav1.NewTime(time.Now()) + } //} gw.Status.Conditions[0].Status = "True" gw.Status.Conditions[0].Message = fmt.Sprintf("aws-gateway-arn: %s", serviceNetworkStatus.ARN) From f70d9e58bdff63bac91f73c65ac023e490bbf526 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 21:15:34 +0000 Subject: [PATCH 19/21] Update debug msgs --- pkg/deploy/lattice/service_network_manager.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/deploy/lattice/service_network_manager.go b/pkg/deploy/lattice/service_network_manager.go index 4eaa9536..2eb56f99 100644 --- a/pkg/deploy/lattice/service_network_manager.go +++ b/pkg/deploy/lattice/service_network_manager.go @@ -213,13 +213,19 @@ func (m *defaultServiceNetworkManager) Delete(ctx context.Context, service_netwo vpcOwner, ok := snTags.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] if ok && *vpcOwner == config.VpcID { needToDelete = true + } else { + if ok { + glog.V(2).Infof("Skip deleting, the service network[%v] is created by VPC %v", service_network, *vpcOwner) + } else { + glog.V(2).Infof("Skip deleting, the service network[%v] is not created by K8S, since there is no tag", service_network) + } } } if needToDelete { if len(assocResp) != 0 { - glog.V(6).Infof("Retry deleting %v later, due to service network still has VPCs associated", service_network) + glog.V(2).Infof("Retry deleting %v later, due to service network still has VPCs associated", service_network) return errors.New(LATTICE_RETRY) } From 730277ce1e276a92cdfa238ad5ab10257387b6b8 Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 21:21:45 +0000 Subject: [PATCH 20/21] Update gateway example object to specify they needs to associated to current VPC --- examples/my-hotel-gateway-multi-listeners.yaml | 2 ++ examples/my-hotel-gateway-tls.yaml | 2 ++ examples/my-hotel-gateway.yaml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/examples/my-hotel-gateway-multi-listeners.yaml b/examples/my-hotel-gateway-multi-listeners.yaml index 86f4f51c..acb68947 100644 --- a/examples/my-hotel-gateway-multi-listeners.yaml +++ b/examples/my-hotel-gateway-multi-listeners.yaml @@ -2,6 +2,8 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: name: my-hotel + annotations: + application-networking.k8s.aws/lattice-vpc-association: "true" spec: gatewayClassName: amazon-vpc-lattice listeners: diff --git a/examples/my-hotel-gateway-tls.yaml b/examples/my-hotel-gateway-tls.yaml index 48861296..15dd29d8 100644 --- a/examples/my-hotel-gateway-tls.yaml +++ b/examples/my-hotel-gateway-tls.yaml @@ -2,6 +2,8 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: name: my-hotel + annotations: + application-networking.k8s.aws/lattice-vpc-association: "true" spec: gatewayClassName: amazon-vpc-lattice listeners: diff --git a/examples/my-hotel-gateway.yaml b/examples/my-hotel-gateway.yaml index ded0f2cc..04b99622 100644 --- a/examples/my-hotel-gateway.yaml +++ b/examples/my-hotel-gateway.yaml @@ -2,6 +2,8 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: name: my-hotel + annotations: + application-networking.k8s.aws/lattice-vpc-association: "true" spec: gatewayClassName: amazon-vpc-lattice listeners: From ee42c90ab7933693017607d31cdce5ad660594fd Mon Sep 17 00:00:00 2001 From: liwen wu Date: Thu, 2 Mar 2023 21:32:57 +0000 Subject: [PATCH 21/21] Update document on new annotation --- docs/configure.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/configure.md b/docs/configure.md index 94a55d8e..7727d9dc 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -18,6 +18,19 @@ This example creates a single cluster in a single VPC, then configures two route ```bash kubectl apply -f examples/my-hotel-gateway.yaml ``` + ***Note*** + + By default, the gateway(lattice service network) is not associated with cluster's VPC. To associate a gateway(lattice service network) to VPC, gateway object must have following annotation. + + + apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: Gateway + metadata: + name: my-hotel + annotations: + application-networking.k8s.aws/lattice-vpc-association: "true" + + 1. Verify that `my-hotel` gateway is created (this could take about five minutes): ```bash kubectl get gateway