Skip to content

Commit

Permalink
Add support for internal load balancers (#734)
Browse files Browse the repository at this point in the history
* update godo

* Add support for internal load balancers
- Currently closed alpha and will document annotations when we open it up to beta
- When network=INTERNAL, the IP of the load balancer will be from the underlying VPC. This IP will only be accessible from within the VPC.
  • Loading branch information
bbassingthwaite authored Jun 5, 2024
1 parent 77587f7 commit 97918e1
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 5 deletions.
4 changes: 4 additions & 0 deletions cloud-controller-manager/do/lb_annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,8 @@ const (
// annDOType is the annotation used to specify the type of the load balancer. Either REGIONAL or REGIONAL_NETWORK (currently in closed alpha)
// are permitted. If no type is provided, then it will default REGIONAL.
annDOType = annDOLoadBalancerBase + "type"

// annDONetwork is the annotation used to specify the network type of the load balancer. Either EXTERNAL or INTERNAL (currently in closed alpha)
// are permitted. If no network is provided, then it will default EXTERNAL.
annDONetwork = annDOLoadBalancerBase + "network"
)
16 changes: 16 additions & 0 deletions cloud-controller-manager/do/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,10 @@ func buildLoadBalancerRequest(ctx context.Context, service *v1.Service, godoClie
if err != nil {
return nil, err
}
lbNetwork, err := getNetwork(service)
if err != nil {
return nil, err
}
var forwardingRules []godo.ForwardingRule
if lbType == godo.LoadBalancerTypeRegionalNetwork {
forwardingRules, err = buildRegionalNetworkForwardingRule(service)
Expand Down Expand Up @@ -625,6 +629,7 @@ func buildLoadBalancerRequest(ctx context.Context, service *v1.Service, godoClie
HTTPIdleTimeoutSeconds: httpIdleTimeoutSeconds,
Firewall: fw,
Type: lbType,
Network: lbNetwork,
}, nil
}

Expand Down Expand Up @@ -1388,6 +1393,17 @@ func getType(service *v1.Service) (string, error) {
return name, nil
}

func getNetwork(service *v1.Service) (string, error) {
network := service.Annotations[annDONetwork]
if network == "" {
return godo.LoadBalancerNetworkTypeExternal, nil
}
if !(network == godo.LoadBalancerNetworkTypeExternal || network == godo.LoadBalancerNetworkTypeInternal) {
return "", fmt.Errorf("only LB networks supported are (%s, %s)", godo.LoadBalancerNetworkTypeExternal, godo.LoadBalancerNetworkTypeInternal)
}
return network, nil
}

func findDups(lists ...[]int) []string {
occurrences := map[int]int{}

Expand Down
90 changes: 90 additions & 0 deletions cloud-controller-manager/do/loadbalancers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3680,6 +3680,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -3757,6 +3758,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -3846,6 +3848,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -3979,6 +3982,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4056,6 +4060,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4134,6 +4139,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4212,6 +4218,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4350,6 +4357,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
CookieTtlSeconds: 300,
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4432,6 +4440,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
CookieTtlSeconds: 300,
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4524,6 +4533,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(false),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -4617,6 +4627,7 @@ func Test_buildLoadBalancerRequest(t *testing.T) {
Type: "none",
},
DisableLetsEncryptDNSRecords: godo.PtrTo(true),
Network: godo.LoadBalancerNetworkTypeExternal,
},
nil,
},
Expand Down Expand Up @@ -6155,6 +6166,85 @@ func Test_getType(t *testing.T) {
}
}

func Test_getNetwork(t *testing.T) {
var (
external = godo.LoadBalancerNetworkTypeExternal
internal = godo.LoadBalancerNetworkTypeInternal
)
testcases := []struct {
name string
service *v1.Service
wantErr bool
expected *string
}{
{
name: "no value defaults to EXTERNAL",
service: &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
UID: "abc123",
Annotations: map[string]string{},
},
},
wantErr: false,
expected: &external,
}, {
name: "annotation set to EXTERNAL",
service: &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
UID: "abc123",
Annotations: map[string]string{
annDONetwork: godo.LoadBalancerNetworkTypeExternal,
},
},
},
wantErr: false,
expected: &external,
},
{
name: "annotation set to INTERNAL",
service: &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
UID: "abc123",
Annotations: map[string]string{
annDONetwork: godo.LoadBalancerNetworkTypeInternal,
},
},
},
wantErr: false,
expected: &internal,
},
{
name: "illegal value",
service: &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
UID: "abc123",
Annotations: map[string]string{
annDONetwork: "abcd",
},
},
},
wantErr: true,
},
}

for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
lbType, err := getNetwork(test.service)
if test.wantErr != (err != nil) {
t.Errorf("got error %q, want error: %t", err, test.wantErr)
}

if test.expected != nil && lbType != *test.expected {
t.Fatalf("got lb network %v, want %v", lbType, *test.expected)
}
})
}
}

func Test_buildFirewall(t *testing.T) {
testcases := []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ toolchain go1.22.2

require (
github.com/davecgh/go-spew v1.1.1
github.com/digitalocean/godo v1.116.0
github.com/digitalocean/godo v1.116.1-0.20240604202737-333fbb54616a
github.com/go-logr/logr v1.4.2
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/digitalocean/godo v1.116.0 h1:SuF/Imd1/dE/nYrUFVkJ2itesQNnJQE1a/vmtHknxeE=
github.com/digitalocean/godo v1.116.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo=
github.com/digitalocean/godo v1.116.1-0.20240604202737-333fbb54616a h1:4px/JtHLirGz3uNMO2dZ2Nuk/XFFpjU7aJ3TI0z/W/Q=
github.com/digitalocean/godo v1.116.1-0.20240604202737-333fbb54616a/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
Expand Down
19 changes: 19 additions & 0 deletions vendor/github.com/digitalocean/godo/apps.gen.go

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

48 changes: 48 additions & 0 deletions vendor/github.com/digitalocean/godo/apps_accessors.go

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

9 changes: 8 additions & 1 deletion vendor/github.com/digitalocean/godo/load_balancers.go

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

Loading

0 comments on commit 97918e1

Please sign in to comment.