Skip to content

Commit

Permalink
Merge pull request #678 from KevFan/MGDAPI-5458
Browse files Browse the repository at this point in the history
MGDAPI-5458 - refactor: remove blocking gcp calls
  • Loading branch information
openshift-merge-robot committed Apr 13, 2023
2 parents 55f97ea + 924b4d9 commit a4fd41c
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 383 deletions.
22 changes: 13 additions & 9 deletions apis/integreatly/v1alpha1/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import (
)

var (
PhaseInProgress StatusPhase = "in progress"
PhaseDeleteInProgress StatusPhase = "deletion in progress"
PhaseComplete StatusPhase = "complete"
PhasePaused StatusPhase = "paused"
PhaseFailed StatusPhase = "failed"
StatusEmpty StatusMessage = ""
StatusUnsupportedType StatusMessage = "unsupported deployment type"
StatusDeploymentConfigNotFound StatusMessage = "deployment configuration not found"
StatusSkipCreate StatusMessage = "skipping create or update for maintenance"
PhaseInProgress StatusPhase = "in progress"
PhaseDeleteInProgress StatusPhase = "deletion in progress"
PhaseComplete StatusPhase = "complete"
PhasePaused StatusPhase = "paused"
PhaseFailed StatusPhase = "failed"
StatusEmpty StatusMessage = ""
StatusUnsupportedType StatusMessage = "unsupported deployment type"
StatusDeploymentConfigNotFound StatusMessage = "deployment configuration not found"
StatusSkipCreate StatusMessage = "skipping create or update for maintenance"
StatusNetworkCreateError StatusMessage = "failed to create network service"
StatusNetworkIPRangePendingCreation StatusMessage = "ip address range is pending creation"
StatusNetworkIPRangeNotExistOrPendingCreation StatusMessage = "ip address range does not exist or is pending creation"
StatusNetworkServiceConnectionPendingCreation StatusMessage = "service connection is pending creation"
)

type SecretRef struct {
Expand Down
108 changes: 23 additions & 85 deletions pkg/providers/gcp/cluster_network_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"cloud.google.com/go/compute/apiv1/computepb"
croType "github.com/integr8ly/cloud-resource-operator/apis/integreatly/v1alpha1/types"
"github.com/integr8ly/cloud-resource-operator/pkg/providers"
"github.com/integr8ly/cloud-resource-operator/pkg/providers/gcp/gcpiface"
"github.com/integr8ly/cloud-resource-operator/pkg/resources"
Expand All @@ -36,8 +37,8 @@ const (

//go:generate moq -out cluster_network_provider_moq.go . NetworkManager
type NetworkManager interface {
CreateNetworkIpRange(context.Context, *net.IPNet) (*computepb.Address, error)
CreateNetworkService(context.Context) (*servicenetworking.Connection, error)
CreateNetworkIpRange(context.Context, *net.IPNet) (*computepb.Address, croType.StatusMessage, error)
CreateNetworkService(context.Context) (*servicenetworking.Connection, croType.StatusMessage, error)
DeleteNetworkPeering(context.Context) error
DeleteNetworkService(context.Context) error
DeleteNetworkIpRange(context.Context) error
Expand Down Expand Up @@ -96,141 +97,78 @@ func NewNetworkManager(ctx context.Context, projectID string, opt option.ClientO
}, nil
}

func (n *NetworkProvider) CreateNetworkIpRange(ctx context.Context, cidrRange *net.IPNet) (*computepb.Address, error) {
func (n *NetworkProvider) CreateNetworkIpRange(ctx context.Context, cidrRange *net.IPNet) (*computepb.Address, croType.StatusMessage, error) {
// build ip address range name
ipRangeName, err := resources.BuildInfraName(ctx, n.Client, defaultIpRangePostfix, defaultGcpIdentifierLength)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to build ip address range infra name")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to build ip address range infra name")
}
address, err := n.getAddressRange(ctx, ipRangeName)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to retrieve ip address range")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to retrieve ip address range")
}
// if it does not exist, create it
if address == nil {
clusterVpc, err := getClusterVpc(ctx, n.Client, n.NetworkApi, n.ProjectID, n.Logger)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to get cluster vpc")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to get cluster vpc")
}
subnets, err := n.getClusterSubnets(ctx, clusterVpc)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to get cluster subnetworks")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to get cluster subnetworks")
}
err = validateCidrBlock(cidrRange, subnets)
if err != nil {
return nil, errorUtil.Wrap(err, "ip range validation failure")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "ip range validation failure")
}
err = n.createAddressRange(ctx, clusterVpc, ipRangeName, cidrRange)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to create ip address range")
}
if address, err = n.waitForAddress(ctx, ipRangeName); err != nil {
return nil, errorUtil.Wrap(err, "failed to retrieve ip address range")
}
}
return address, nil
}

func (n *NetworkProvider) waitForAddress(ctx context.Context, ipRangeName string) (*computepb.Address, error) {
addressChan := make(chan *computepb.Address, 1)
errorChan := make(chan error, 1)
defer close(addressChan)
defer close(errorChan)
go func() {
for {
address, err := n.getAddressRange(ctx, ipRangeName)
if err != nil {
errorChan <- err
break
}
if address != nil {
addressChan <- address
break
}
time.Sleep(time.Second * 3)
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to create ip address range")
}

}()
select {
case address := <-addressChan:
n.Logger.Infof("created ip address range %s: %s/%d", address.GetName(), address.GetAddress(), address.GetPrefixLength())
return address, nil
case err := <-errorChan:
return nil, err
case <-time.After(defaultTimeout):
return nil, fmt.Errorf("waitForAddress() timed out")
return nil, croType.StatusNetworkIPRangePendingCreation, nil
}
n.Logger.Infof("created ip address range %s: %s/%d", address.GetName(), address.GetAddress(), address.GetPrefixLength())
return address, "", nil
}

// CreateNetworkService Creates the network service connection and will return the service if it has been created successfully
// This automatically creates a peering connection to the clusterVpc named after the service connection
func (n *NetworkProvider) CreateNetworkService(ctx context.Context) (*servicenetworking.Connection, error) {
func (n *NetworkProvider) CreateNetworkService(ctx context.Context) (*servicenetworking.Connection, croType.StatusMessage, error) {
clusterVpc, err := getClusterVpc(ctx, n.Client, n.NetworkApi, n.ProjectID, n.Logger)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to get cluster vpc")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to get cluster vpc")
}
service, err := n.getServiceConnection(clusterVpc)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to retrieve service connection")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to retrieve service connection")
}
// if it does not exist, create it
if service == nil {
// build ip address range name
ipRange, err := resources.BuildInfraName(ctx, n.Client, defaultIpRangePostfix, defaultGcpIdentifierLength)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to build ip address range infra name")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to build ip address range infra name")
}
address, err := n.getAddressRange(ctx, ipRange)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to retrieve ip address range")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to retrieve ip address range")
}
// if the ip range is present, and is ready for use
// possible states for address are RESERVING, RESERVED, IN_USE
if address == nil || address.GetStatus() == computepb.Address_RESERVING.String() {
return nil, errors.New("ip address range does not exist or is pending creation")
return nil, croType.StatusNetworkIPRangeNotExistOrPendingCreation, nil
}
if address != nil && address.GetStatus() == computepb.Address_RESERVED.String() {
err = n.createServiceConnection(clusterVpc, ipRange)
if err != nil {
return nil, errorUtil.Wrap(err, "failed to create service connection")
return nil, croType.StatusNetworkCreateError, errorUtil.Wrap(err, "failed to create service connection")
}
if service, err = n.waitForConnection(clusterVpc); err != nil {
return nil, errorUtil.Wrap(err, "failed to retrieve service connection")
}
}
}
return service, nil
}

func (n *NetworkProvider) waitForConnection(clusterVpc *computepb.Network) (*servicenetworking.Connection, error) {
connectionChan := make(chan *servicenetworking.Connection, 1)
errorChan := make(chan error, 1)
defer close(connectionChan)
defer close(errorChan)
go func() {
for {
connection, err := n.getServiceConnection(clusterVpc)
if err != nil {
errorChan <- err
break
}
if connection != nil {
connectionChan <- connection
break
}
time.Sleep(time.Second * 3)
return nil, croType.StatusNetworkServiceConnectionPendingCreation, nil
}

}()
select {
case connection := <-connectionChan:
n.Logger.Infof("created network service connection %s", connection.Service)
return connection, nil
case err := <-errorChan:
return nil, err
case <-time.After(defaultTimeout):
return nil, fmt.Errorf("waitForConnection() timed out")
}
n.Logger.Infof("created network service connection %s", service)
return service, "", nil
}

// DeleteNetworkPeering Removes the peering connection from the cluster vpc
Expand Down
13 changes: 7 additions & 6 deletions pkg/providers/gcp/cluster_network_provider_moq.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a4fd41c

Please sign in to comment.