Skip to content

Commit

Permalink
support byovpc and clean up list filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
eljohnson92 committed Mar 7, 2024
1 parent 4c79ecb commit b16ad05
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 56 deletions.
13 changes: 9 additions & 4 deletions .github/workflows/build_test_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version-file: 'go.mod'
check-latest: true

- name: Build
run: make build
Expand Down Expand Up @@ -79,7 +80,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version-file: 'go.mod'
check-latest: true

- name: Docker cache
uses: ScribeMD/[email protected]
Expand Down Expand Up @@ -134,7 +136,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version-file: 'go.mod'
check-latest: true

- name: Docker cache
uses: ScribeMD/[email protected]
Expand All @@ -156,6 +159,7 @@ jobs:
with:
name: logs
path: .logs/*
overwrite: true

chainsaw-test:
needs: [go-build-test, docker-build]
Expand Down Expand Up @@ -193,7 +197,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version-file: 'go.mod'
check-latest: true

- name: Docker cache
uses: ScribeMD/[email protected]
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version-file: 'go.mod'
check-latest: true

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/linodecluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ type NetworkSpec struct {
LoadBalancerPort int `json:"loadBalancerPort,omitempty"`
// NodeBalancerID is the id of api server NodeBalancer.
// +optional
NodeBalancerID int `json:"nodeBalancerID,omitempty"`
NodeBalancerID *int `json:"nodeBalancerID,omitempty"`
// NodeBalancerConfigID is the config ID of api server NodeBalancer.
// +optional
NodeBalancerConfigID *int `json:"nodeBalancerConfigID,omitempty"`
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

21 changes: 9 additions & 12 deletions cloud/services/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package services

import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
Expand All @@ -21,20 +20,18 @@ const (

// CreateNodeBalancer creates a new NodeBalancer if one doesn't exist
func CreateNodeBalancer(ctx context.Context, clusterScope *scope.ClusterScope, logger logr.Logger) (*linodego.NodeBalancer, error) {
var linodeNBs []linodego.NodeBalancer
var linodeNB *linodego.NodeBalancer

NBLabel := fmt.Sprintf("%s-api-server", clusterScope.LinodeCluster.Name)
clusterUID := string(clusterScope.LinodeCluster.UID)
tags := []string{string(clusterScope.LinodeCluster.UID)}
filter := map[string]string{
"label": NBLabel,
listFilter := util.Filter{
ID: clusterScope.LinodeCluster.Spec.Network.NodeBalancerID,
Label: NBLabel,
Tags: tags,
}

rawFilter, err := json.Marshal(filter)
linodeNBs, err := clusterScope.LinodeClient.ListNodeBalancers(ctx, linodego.NewListOptions(1, listFilter.String()))
if err != nil {
return nil, err
}
if linodeNBs, err = clusterScope.LinodeClient.ListNodeBalancers(ctx, linodego.NewListOptions(1, string(rawFilter))); err != nil {
logger.Info("Failed to list NodeBalancers", "error", err.Error())

return nil, err
Expand Down Expand Up @@ -97,7 +94,7 @@ func CreateNodeBalancerConfig(

if linodeNBConfig, err = clusterScope.LinodeClient.CreateNodeBalancerConfig(
ctx,
clusterScope.LinodeCluster.Spec.Network.NodeBalancerID,
*clusterScope.LinodeCluster.Spec.Network.NodeBalancerID,
createConfig,
); err != nil {
logger.Info("Failed to create Linode NodeBalancer config", "error", err.Error())
Expand Down Expand Up @@ -145,7 +142,7 @@ func AddNodeToNB(
}
_, err = machineScope.LinodeClient.CreateNodeBalancerNode(
ctx,
machineScope.LinodeCluster.Spec.Network.NodeBalancerID,
*machineScope.LinodeCluster.Spec.Network.NodeBalancerID,
*machineScope.LinodeCluster.Spec.Network.NodeBalancerConfigID,
linodego.NodeBalancerNodeCreateOptions{
Label: machineScope.Cluster.Name,
Expand Down Expand Up @@ -185,7 +182,7 @@ func DeleteNodeFromNB(

err := machineScope.LinodeClient.DeleteNodeBalancerNode(
ctx,
machineScope.LinodeCluster.Spec.Network.NodeBalancerID,
*machineScope.LinodeCluster.Spec.Network.NodeBalancerID,
*machineScope.LinodeCluster.Spec.Network.NodeBalancerConfigID,
*machineScope.LinodeMachine.Spec.InstanceID,
)
Expand Down
8 changes: 7 additions & 1 deletion cloud/services/object_storage_buckets.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ import (
)

func EnsureObjectStorageBucket(ctx context.Context, bScope *scope.ObjectStorageBucketScope) (*linodego.ObjectStorageBucket, error) {
// Buckets do not have IDs so hardcode it to 0
listFilter := util.Filter{
ID: nil,
Label: *bScope.Bucket.Spec.Label,
Tags: nil,
}
buckets, err := bScope.LinodeClient.ListObjectStorageBucketsInCluster(
ctx,
linodego.NewListOptions(1, util.CreateLinodeAPIFilter(*bScope.Bucket.Spec.Label, nil)),
linodego.NewListOptions(1, listFilter.String()),
bScope.Bucket.Spec.Cluster,
)
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions controller/linodecluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (r *LinodeClusterReconciler) reconcileCreate(ctx context.Context, logger lo
return err
}

clusterScope.LinodeCluster.Spec.Network.NodeBalancerID = linodeNB.ID
clusterScope.LinodeCluster.Spec.Network.NodeBalancerID = &linodeNB.ID

linodeNBConfig, err := services.CreateNodeBalancerConfig(ctx, clusterScope, logger)
if err != nil {
Expand All @@ -191,14 +191,14 @@ func (r *LinodeClusterReconciler) reconcileCreate(ctx context.Context, logger lo

func (r *LinodeClusterReconciler) reconcileDelete(ctx context.Context, logger logr.Logger, clusterScope *scope.ClusterScope) error {
logger.Info("deleting cluster")
if clusterScope.LinodeCluster.Spec.Network.NodeBalancerID == 0 {
if clusterScope.LinodeCluster.Spec.Network.NodeBalancerID == nil {
logger.Info("NodeBalancer ID is missing, nothing to do")
controllerutil.RemoveFinalizer(clusterScope.LinodeCluster, infrav1alpha1.GroupVersion.String())

return nil
}

if err := clusterScope.LinodeClient.DeleteNodeBalancer(ctx, clusterScope.LinodeCluster.Spec.Network.NodeBalancerID); err != nil {
if err := clusterScope.LinodeClient.DeleteNodeBalancer(ctx, *clusterScope.LinodeCluster.Spec.Network.NodeBalancerID); err != nil {
logger.Info("Failed to delete Linode NodeBalancer", "error", err.Error())

// Not found is not an error
Expand All @@ -212,7 +212,7 @@ func (r *LinodeClusterReconciler) reconcileDelete(ctx context.Context, logger lo

conditions.MarkFalse(clusterScope.LinodeCluster, clusterv1.ReadyCondition, clusterv1.DeletedReason, clusterv1.ConditionSeverityInfo, "Load balancer deleted")

clusterScope.LinodeCluster.Spec.Network.NodeBalancerID = 0
clusterScope.LinodeCluster.Spec.Network.NodeBalancerID = nil
clusterScope.LinodeCluster.Spec.Network.NodeBalancerConfigID = nil
controllerutil.RemoveFinalizer(clusterScope.LinodeCluster, infrav1alpha1.GroupVersion.String())

Expand Down
7 changes: 6 additions & 1 deletion controller/linodemachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,12 @@ func (r *LinodeMachineReconciler) reconcileCreate(

tags := []string{machineScope.LinodeCluster.Name}

linodeInstances, err := machineScope.LinodeClient.ListInstances(ctx, linodego.NewListOptions(1, util.CreateLinodeAPIFilter(machineScope.LinodeMachine.Name, tags)))
listFilter := util.Filter{
ID: machineScope.LinodeMachine.Spec.InstanceID,
Label: machineScope.LinodeMachine.Name,
Tags: tags,
}
linodeInstances, err := machineScope.LinodeClient.ListInstances(ctx, linodego.NewListOptions(1, listFilter.String()))
if err != nil {
logger.Error(err, "Failed to list Linode machine instances")

Expand Down
10 changes: 4 additions & 6 deletions controller/linodevpc_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ type LinodeVPCReconciler struct {
ReconcileTimeout time.Duration
}

//+kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=linodevpcs,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=linodevpcs/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=linodevpcs/finalizers,verbs=update
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=linodevpcs,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=linodevpcs/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=linodevpcs/finalizers,verbs=update

//+kubebuilder:rbac:groups="",resources=events,verbs=create;update;patch
// +kubebuilder:rbac:groups="",resources=events,verbs=create;update;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the VPC closer to the desired state.
Expand Down Expand Up @@ -221,8 +221,6 @@ func (r *LinodeVPCReconciler) reconcileDelete(ctx context.Context, logger logr.L
logger.Error(err, "Failed to fetch VPC")

return res, err
} else if vpc == nil {
return res, errors.New("failed to fetch VPC")
}

if vpc != nil {
Expand Down
9 changes: 7 additions & 2 deletions controller/linodevpc_controller_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,23 @@ func (r *LinodeVPCReconciler) reconcileVPC(ctx context.Context, vpcScope *scope.

return err
}

if createConfig.Label == "" {
createConfig.Label = vpcScope.LinodeVPC.Name
}

if vpcs, err := vpcScope.LinodeClient.ListVPCs(ctx, linodego.NewListOptions(1, util.CreateLinodeAPIFilter(createConfig.Label, nil))); err != nil {
listFilter := util.Filter{
ID: vpcScope.LinodeVPC.Spec.VPCID,
Label: createConfig.Label,
Tags: nil,
}
if vpcs, err := vpcScope.LinodeClient.ListVPCs(ctx, linodego.NewListOptions(1, listFilter.String())); err != nil {
logger.Error(err, "Failed to list VPCs")

return err
} else if len(vpcs) != 0 {
// Labels are unique
vpcScope.LinodeVPC.Spec.VPCID = &vpcs[0].ID
vpcScope.LinodeVPC.Spec.Label = vpcs[0].Label

return nil
}
Expand Down
45 changes: 45 additions & 0 deletions util/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package util

import (
"encoding/json"
"strconv"
"strings"
)

// Filter holds the fields used for filtering results from the Linode API.
//
// The fields within Filter are prioritized so that only the most-specific
// field is present when Filter is marshaled to JSON.
type Filter struct {
ID *int // Filter on the resource's ID (most specific).
Label string // Filter on the resource's label.
Tags []string // Filter resources by their tags (least specific).
}

// MarshalJSON returns a JSON-encoded representation of a [Filter].
// The resulting encoded value will have exactly 1 (one) field present.
// See [Filter] for details on the value precedence.
func (f Filter) MarshalJSON() ([]byte, error) {
filter := make(map[string]string, 1)
switch {
case f.ID != nil:
filter["id"] = strconv.Itoa(*f.ID)
case f.Label != "":
filter["label"] = f.Label
case len(f.Tags) != 0:
filter["tags"] = strings.Join(f.Tags, ",")
}

return json.Marshal(filter)
}

// String returns the string representation of the encoded value from
// [Filter.MarshalJSON].
func (f Filter) String() string {
p, err := f.MarshalJSON()
if err != nil {
panic("this should not have failed")
}

return string(p)
}
24 changes: 0 additions & 24 deletions util/helpers.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package util

import (
"encoding/json"
"strings"

"github.com/linode/linodego"
)

Expand All @@ -12,27 +9,6 @@ func Pointer[T any](t T) *T {
return &t
}

// CreateLinodeAPIFilter converts variables to API filter string
func CreateLinodeAPIFilter(label string, tags []string) string {
filter := map[string]string{}

if label != "" {
filter["label"] = label
}

if len(tags) != 0 {
filter["tags"] = strings.Join(tags, ",")
}

rawFilter, err := json.Marshal(filter)
if err != nil {
// This should never happen
panic(err.Error() + " Oh, snap... Earth has over, we can't parse map[string]string to JSON! I'm going to die ...")
}

return string(rawFilter)
}

// IgnoreLinodeAPIError returns the error except matches to status code
func IgnoreLinodeAPIError(err error, code int) error {
apiErr := linodego.Error{Code: code}
Expand Down

0 comments on commit b16ad05

Please sign in to comment.