-
Notifications
You must be signed in to change notification settings - Fork 70
Allow to create multiple service networks #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e96dd9f
8760c56
8abcff4
f347046
a57d218
16fd5ca
0b88ab7
d7f67e3
247ce6e
a75eb40
a00f930
7022e5c
18cfa4f
2249f50
3f6f7dd
374ed34
2b3ed18
07e2a41
f70d9e5
730277c
ee42c90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
|
@@ -56,58 +61,94 @@ 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) | ||
| 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 | ||
|
|
||
| service_networkInput := vpclattice.CreateServiceNetworkInput{ | ||
| Name: &service_network.Spec.Name, | ||
| 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(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") | ||
| service_networkID = aws.StringValue(service_networkSummary.Id) | ||
| service_networkArn = aws.StringValue(service_networkSummary.Arn) | ||
| isServiceNetworkAssociatedWithVPC, _, _, err = m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) | ||
| 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) | ||
| if err != nil { | ||
| return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, err | ||
| } | ||
| } | ||
|
|
||
| if isServiceNetworkAssociatedWithVPC == false { | ||
| createServiceNetworkVpcAssociationInput := vpclattice.CreateServiceNetworkVpcAssociationInput{ | ||
| ServiceNetworkIdentifier: &service_networkID, | ||
| VpcIdentifier: &config.VpcID, | ||
| if service_network.Spec.AssociateToVPC == true { | ||
| if isServiceNetworkAssociatedWithVPC == false { | ||
liwenwu-amazon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // 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, | ||
| } | ||
| 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 | ||
| if err != nil { | ||
| 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) | ||
| 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) | ||
| } | ||
| } | ||
| } | ||
| 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 { | ||
| if isServiceNetworkAssociatedWithVPC == true { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I get the idea, that if service_network.Spec.AssociateToVPC=false, and ServiceNetwork is currently AssociatedWithVPC, we want to disassociate vpcAndServiceNetwork. I feel it is a bit wired that this is doing delete work while in create section.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case, the associationToVPC or disassociatefromVPC is kind of like an attribute of a service-network/gateway here. The K8S intend is to create gateway==servicenetwork, with attribute whether to associate/dis-associate to VPC |
||
| // current state: service network is associated to VPC | ||
| // desired state: not to associate this service network to VPC | ||
| 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) | ||
| } | ||
|
|
||
| // return retry and check later if disassociation workflow finishes | ||
| return latticemodel.ServiceNetworkStatus{ServiceNetworkARN: "", ServiceNetworkID: ""}, errors.New(LATTICE_RETRY) | ||
|
|
||
| } | ||
| 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 | ||
| } | ||
|
|
@@ -135,79 +176,103 @@ 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(2).Infof("Successfully deleted unknown service_network %v\n", service_network) | ||
| return nil | ||
| } | ||
|
|
||
| vpcLatticeSess := m.cloud.Lattice() | ||
| service_networkID := aws.StringValue(service_networkSummary.Id) | ||
| deleteNeedRetry := false | ||
| service_networkID := aws.StringValue(service_networkSummary.snSummary.Id) | ||
|
|
||
| _, service_networkAssociatedWithCurrentVPCId, service_networkVPCAssociations, err := m.isServiceNetworkAssociatedWithVPC(ctx, service_networkID) | ||
| _, service_networkAssociatedWithCurrentVPCId, assocResp, 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) | ||
| 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, | ||
| } | ||
| 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 for %v, err: %v \n", service_network, err) | ||
| } | ||
| // retry later to check if VPC disassociation workflow finishes | ||
| return errors.New(LATTICE_RETRY) | ||
|
|
||
| } | ||
|
|
||
| // 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 | ||
| vpcOwner, ok := snTags.Tags[latticemodel.K8SServiceNetworkOwnedByVPC] | ||
| if ok && *vpcOwner == config.VpcID { | ||
| needToDelete = true | ||
| } 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) | ||
| 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) | ||
| } | ||
| glog.V(2).Infof("DeleteServiceNetworkVPCAssociationResp: service_network %v , resp %v, err %v \n", service_network, resp, err) | ||
| } | ||
| } else { | ||
| // there are other Associations left for this service_network, could not delete | ||
| deleteNeedRetry = true | ||
| return nil | ||
| } | ||
|
|
||
| deleteInput := vpclattice.DeleteServiceNetworkInput{ | ||
| ServiceNetworkIdentifier: &service_networkID, | ||
| } | ||
| _, err = vpcLatticeSess.DeleteServiceNetworkWithContext(ctx, &deleteInput) | ||
| if err != nil { | ||
| if needToDelete { | ||
|
|
||
| if len(assocResp) != 0 { | ||
| glog.V(2).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, | ||
| } | ||
| 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) | ||
| } | ||
|
|
||
| glog.V(2).Infof("Successfully delete service_network %v\n", service_network) | ||
| return err | ||
| } | ||
|
|
||
| if deleteNeedRetry { | ||
| return errors.New(LATTICE_RETRY) | ||
| } else { | ||
| glog.V(6).Infof("Successfully delete service_network %v\n", service_network) | ||
| return err | ||
| glog.V(2).Infof("Deleting service_network (%v) Skipped, since it is owned by different VPC ", service_network) | ||
| return nil | ||
| } | ||
| } | ||
|
|
||
| // 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) | ||
| if err == nil { | ||
| 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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic seems wrong. Don't you want to change this every time the condition transitions? Right now, it only checks when it goes from unset -> set. Is it ever possible for this condition to be false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we reset it whenever there is a change and need controller to reconcile it