Skip to content

Commit f257382

Browse files
committed
Add support for Shared VPC Networking
This is an update to the stale PR #991 ** Added support for Host Project for a shared VPC in the Network struct. ** Network Resources will now use the host project name if exists, otherwise the normal project. ** Update the cluster getter interface to include the NetworkProject and Indicator for a shared VPC. ** Update reconcilers for girewall rules, subnets and network. ** Update the services to use the host project for resources when a shared vpc is used.
1 parent 47f0958 commit f257382

14 files changed

+111
-7
lines changed

api/v1beta1/types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ type NetworkSpec struct {
112112
// Allow for configuration of load balancer backend (useful for changing apiserver port)
113113
// +optional
114114
LoadBalancerBackendPort *int32 `json:"loadBalancerBackendPort,omitempty"`
115+
116+
// HostProject is the name of the project hosting the shared VPC network resources.
117+
// +optional
118+
HostProject *string `json:"hostProject,omitempty"`
115119
}
116120

117121
// LoadBalancerSpec contains configuration for one or more LoadBalancers.

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/interfaces.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type ReconcilerWithResult interface {
4646
// Client is an interface which can get cloud client.
4747
type Client interface {
4848
Cloud() Cloud
49+
NetworkCloud() Cloud
4950
}
5051

5152
// ClusterGetter is an interface which can get cluster information.
@@ -56,6 +57,8 @@ type ClusterGetter interface {
5657
Name() string
5758
Namespace() string
5859
NetworkName() string
60+
NetworkProject() string
61+
IsSharedVpc() bool
5962
Network() *infrav1.Network
6063
AdditionalLabels() infrav1.Labels
6164
FailureDomains() clusterv1.FailureDomains

cloud/scope/cluster.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,27 @@ func (s *ClusterScope) Cloud() cloud.Cloud {
9090
return newCloud(s.Project(), s.GCPServices)
9191
}
9292

93+
// NetworkCloud returns initialized cloud.
94+
func (s *ClusterScope) NetworkCloud() cloud.Cloud {
95+
return newCloud(s.NetworkProject(), s.GCPServices)
96+
}
97+
9398
// Project returns the current project name.
9499
func (s *ClusterScope) Project() string {
95100
return s.GCPCluster.Spec.Project
96101
}
97102

103+
// NetworkProject returns the project name where network resources should exist.
104+
// The network project defaults to the Project when one is not supplied.
105+
func (s *ClusterScope) NetworkProject() string {
106+
return ptr.Deref(s.GCPCluster.Spec.Network.HostProject, s.Project())
107+
}
108+
109+
// IsSharedVpc returns true If sharedVPC used else , returns false.
110+
func (s *ClusterScope) IsSharedVpc() bool {
111+
return s.NetworkProject() != s.Project()
112+
}
113+
98114
// Region returns the cluster region.
99115
func (s *ClusterScope) Region() string {
100116
return s.GCPCluster.Spec.Region
@@ -117,7 +133,7 @@ func (s *ClusterScope) NetworkName() string {
117133

118134
// NetworkLink returns the partial URL for the network.
119135
func (s *ClusterScope) NetworkLink() string {
120-
return fmt.Sprintf("projects/%s/global/networks/%s", s.Project(), s.NetworkName())
136+
return fmt.Sprintf("projects/%s/global/networks/%s", s.NetworkProject(), s.NetworkName())
121137
}
122138

123139
// Network returns the cluster network object.

cloud/scope/machine.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ func (m *MachineScope) Cloud() cloud.Cloud {
9494
return m.ClusterGetter.Cloud()
9595
}
9696

97+
// NetworkCloud returns initialized network cloud.
98+
func (m *MachineScope) NetworkCloud() cloud.Cloud {
99+
return m.ClusterGetter.NetworkCloud()
100+
}
101+
97102
// Zone returns the FailureDomain for the GCPMachine.
98103
func (m *MachineScope) Zone() string {
99104
if m.Machine.Spec.FailureDomain == nil {
@@ -319,7 +324,7 @@ func (m *MachineScope) InstanceAdditionalDiskSpec() []*compute.AttachedDisk {
319324
// InstanceNetworkInterfaceSpec returns compute network interface spec.
320325
func (m *MachineScope) InstanceNetworkInterfaceSpec() *compute.NetworkInterface {
321326
networkInterface := &compute.NetworkInterface{
322-
Network: path.Join("projects", m.ClusterGetter.Project(), "global", "networks", m.ClusterGetter.NetworkName()),
327+
Network: path.Join("projects", m.ClusterGetter.NetworkProject(), "global", "networks", m.ClusterGetter.NetworkName()),
323328
}
324329

325330
if m.GCPMachine.Spec.PublicIP != nil && *m.GCPMachine.Spec.PublicIP {
@@ -332,7 +337,7 @@ func (m *MachineScope) InstanceNetworkInterfaceSpec() *compute.NetworkInterface
332337
}
333338

334339
if m.GCPMachine.Spec.Subnet != nil {
335-
networkInterface.Subnetwork = path.Join("regions", m.ClusterGetter.Region(), "subnetworks", *m.GCPMachine.Spec.Subnet)
340+
networkInterface.Subnetwork = path.Join("projects", m.ClusterGetter.NetworkProject(), "regions", m.ClusterGetter.Region(), "subnetworks", *m.GCPMachine.Spec.Subnet)
336341
}
337342

338343
return networkInterface

cloud/scope/managedcluster.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ func (s *ManagedClusterScope) Cloud() cloud.Cloud {
9393
return newCloud(s.Project(), s.GCPServices)
9494
}
9595

96+
// NetworkCloud returns initialized cloud.
97+
func (s *ManagedClusterScope) NetworkCloud() cloud.Cloud {
98+
return newCloud(s.NetworkProject(), s.GCPServices)
99+
}
100+
96101
// Project returns the current project name.
97102
func (s *ManagedClusterScope) Project() string {
98103
return s.GCPManagedCluster.Spec.Project
@@ -118,9 +123,20 @@ func (s *ManagedClusterScope) NetworkName() string {
118123
return ptr.Deref(s.GCPManagedCluster.Spec.Network.Name, "default")
119124
}
120125

126+
// NetworkProject returns the project name where network resources should exist.
127+
// The network project defaults to the Project when one is not supplied.
128+
func (s *ManagedClusterScope) NetworkProject() string {
129+
return ptr.Deref(s.GCPManagedCluster.Spec.Network.HostProject, s.Project())
130+
}
131+
132+
// IsSharedVpc returns true If sharedVPC used else , returns false.
133+
func (s *ManagedClusterScope) IsSharedVpc() bool {
134+
return s.NetworkProject() != s.Project()
135+
}
136+
121137
// NetworkLink returns the partial URL for the network.
122138
func (s *ManagedClusterScope) NetworkLink() string {
123-
return fmt.Sprintf("projects/%s/global/networks/%s", s.Project(), s.NetworkName())
139+
return fmt.Sprintf("projects/%s/global/networks/%s", s.NetworkProject(), s.NetworkName())
124140
}
125141

126142
// Network returns the cluster network object.

cloud/services/compute/firewalls/reconcile.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import (
2828
// Reconcile reconcile cluster firewall compoenents.
2929
func (s *Service) Reconcile(ctx context.Context) error {
3030
log := log.FromContext(ctx)
31+
if s.scope.IsSharedVpc() {
32+
log.V(2).Info("Shared VPC enabled. Ignore Reconciling firewall resources")
33+
return nil
34+
}
3135
log.Info("Reconciling firewall resources")
3236
for _, spec := range s.scope.FirewallRulesSpec() {
3337
log.V(2).Info("Looking firewall", "name", spec.Name)
@@ -50,6 +54,10 @@ func (s *Service) Reconcile(ctx context.Context) error {
5054
// Delete delete cluster firewall compoenents.
5155
func (s *Service) Delete(ctx context.Context) error {
5256
log := log.FromContext(ctx)
57+
if s.scope.IsSharedVpc() {
58+
log.V(2).Info("Shared VPC enabled. Ignore Deleting firewall resources")
59+
return nil
60+
}
5361
log.Info("Deleting firewall resources")
5462
for _, spec := range s.scope.FirewallRulesSpec() {
5563
log.V(2).Info("Deleting firewall", "name", spec.Name)

cloud/services/compute/networks/reconcile.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ func (s *Service) Reconcile(ctx context.Context) error {
5454
// Delete delete cluster network components.
5555
func (s *Service) Delete(ctx context.Context) error {
5656
log := log.FromContext(ctx)
57+
if s.scope.IsSharedVpc() {
58+
log.V(2).Info("Shared VPC enabled. Ignore Deleting network resources")
59+
s.scope.Network().Router = nil
60+
s.scope.Network().SelfLink = nil
61+
return nil
62+
}
5763
log.Info("Deleting network resources")
5864
networkKey := meta.GlobalKey(s.scope.NetworkName())
5965
log.V(2).Info("Looking for network before deleting", "name", networkKey)
@@ -104,6 +110,11 @@ func (s *Service) createOrGetNetwork(ctx context.Context) (*compute.Network, err
104110
return nil, err
105111
}
106112

113+
if s.scope.IsSharedVpc() {
114+
log.Error(err, "Shared VPC is enabled, but could not find existing network", "name", s.scope.NetworkName())
115+
return nil, err
116+
}
117+
107118
log.V(2).Info("Creating a network", "name", s.scope.NetworkName())
108119
if err := s.networks.Insert(ctx, networkKey, s.scope.NetworkSpec()); err != nil {
109120
log.Error(err, "Error creating a network", "name", s.scope.NetworkName())
@@ -132,6 +143,11 @@ func (s *Service) createOrGetRouter(ctx context.Context, network *compute.Networ
132143
return nil, err
133144
}
134145

146+
if s.scope.IsSharedVpc() {
147+
log.Error(err, "Shared VPC is enabled, but could not find existing router", "name", routerKey)
148+
return nil, err
149+
}
150+
135151
spec.Network = network.SelfLink
136152
spec.Description = infrav1.ClusterTagKey(s.scope.Name())
137153
log.V(2).Info("Creating a cloudnat router", "name", spec.Name)

cloud/services/compute/networks/service.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ var _ cloud.Reconciler = &Service{}
5656

5757
// New returns Service from given scope.
5858
func New(scope Scope) *Service {
59+
scopeCloud := scope.Cloud()
60+
if scope.IsSharedVpc() {
61+
scopeCloud = scope.NetworkCloud()
62+
}
63+
5964
return &Service{
6065
scope: scope,
61-
networks: scope.Cloud().Networks(),
62-
routers: scope.Cloud().Routers(),
66+
networks: scopeCloud.Networks(),
67+
routers: scopeCloud.Routers(),
6368
}
6469
}

cloud/services/compute/subnets/reconcile.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ func (s *Service) Reconcile(ctx context.Context) error {
4444
// Delete deletes cluster subnetwork components.
4545
func (s *Service) Delete(ctx context.Context) error {
4646
logger := log.FromContext(ctx)
47+
if s.scope.IsSharedVpc() {
48+
logger.V(2).Info("Shared VPC enabled. Skip deleting subnet resources")
49+
return nil
50+
}
4751
for _, subnetSpec := range s.scope.SubnetSpecs() {
4852
subnetKey := meta.RegionalKey(subnetSpec.Name, s.getSubnetRegion(subnetSpec))
4953
logger.V(2).Info("Looking for subnet before deleting it", "name", subnetSpec.Name)
@@ -89,6 +93,11 @@ func (s *Service) createOrGetSubnets(ctx context.Context) ([]*compute.Subnetwork
8993
return subnets, err
9094
}
9195

96+
if s.scope.IsSharedVpc() {
97+
logger.Error(err, "Shared VPC is enabled, but could not find existing subnetwork", "name", subnetSpec.Name)
98+
return nil, err
99+
}
100+
92101
// Subnet was not found, let's create it
93102
logger.V(2).Info("Creating a subnet", "name", subnetSpec.Name)
94103
if err := s.subnets.Insert(ctx, subnetKey, subnetSpec); err != nil {

0 commit comments

Comments
 (0)