Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
AshleyDumaine committed Mar 5, 2024
1 parent 43e45b5 commit 81d22c0
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 341 deletions.
31 changes: 23 additions & 8 deletions api/v1alpha1/linodecluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,10 @@ type LinodeClusterSpec struct {
// +optional
CredentialsRef *corev1.SecretReference `json:"credentialsRef,omitempty"`

// ControlPlaneFirewall encapsulates all things related to the Firewall for the
// control plane nodes.
// +optional
// ControlPlaneFirewallRefs contains a list of LinodeFirewall references to restrict traffic
// to/from the control plane nodes
ControlPlaneFirewallRefs []*corev1.ObjectReference `json:"controlPlaneFirewallRefs,omitempty"`

// +optional
// WorkerFirewallRefs contains a list of LinodeFirewall references to restrict traffic
// to/from the worker nodes
WorkerFirewallRefs []*corev1.ObjectReference `json:"workerFirewallRefs,omitempty"`
ControlPlaneFirewall FirewallSpec `json:"controlPlaneFirewallRefs,omitempty"`
}

// LinodeClusterStatus defines the observed state of LinodeCluster
Expand Down Expand Up @@ -123,6 +118,26 @@ type NetworkSpec struct {
NodeBalancerConfigID *int `json:"nodeBalancerConfigID,omitempty"`
}

type FirewallSpec struct {
// +optional
// Enabled specifies if the default api server firewall should be enabled
Enabled bool `json:"enabled,omitempty"`
// +optional
// AllowedIPV4Addresses specifies additional IPV4 addresses aside from the worker nodes
// that should be permitted to reach the K8s API server
AllowedIPV4Addresses string `json:"allowedIPV4Addresses,omitempty"`
// +optional
// AllowedIPV6Addresses specifies additional IPV6 addresses aside from the worker nodes
// that should be permitted to reach the K8s API server
AllowedIPV6Addresses string `json:"allowedIPV6Addresses,omitempty"`
// +optional
// AllowSSH specifies if SSH should be permitted for the firewall
AllowSSH bool `json:"allowSSH,omitempty"`
// FirewallID is the ID of api server Firewall.
// +optional
FirewallID *int `json:"firewallID,omitempty"`
}

// +kubebuilder:object:root=true

// LinodeClusterList contains a list of LinodeCluster
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha1/linodefirewall_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ type LinodeFirewallSpec struct {
// +optional
FirewallID *int `json:"firewallID,omitempty"`

// +optional
// ClusterUID is used by the LinodeCluster controller to associate a Cloud Firewall to a LinodeCluster
ClusterUID string `json:"clusterUID,omitempty"`

// +optional
// +kubebuilder:default=false
Enabled bool `json:"enabled,omitempty"`
Expand Down
43 changes: 21 additions & 22 deletions api/v1alpha1/zz_generated.deepcopy.go

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

30 changes: 18 additions & 12 deletions cloud/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ import (

// ClusterScopeParams defines the input parameters used to create a new Scope.
type ClusterScopeParams struct {
Client client.Client
Cluster *clusterv1.Cluster
LinodeCluster *infrav1alpha1.LinodeCluster
Client client.Client
Cluster *clusterv1.Cluster
LinodeCluster *infrav1alpha1.LinodeCluster
ControlPlaneFirewall *infrav1alpha1.LinodeFirewall
}

func validateClusterScopeParams(params ClusterScopeParams) error {
Expand All @@ -44,6 +45,9 @@ func validateClusterScopeParams(params ClusterScopeParams) error {
if params.LinodeCluster == nil {
return errors.New("linodeCluster is required when creating a ClusterScope")
}
if params.ControlPlaneFirewall == nil {
return errors.New("controlPlaneFirewall is required when creating a ClusterScope")
}

return nil
}
Expand Down Expand Up @@ -71,22 +75,24 @@ func NewClusterScope(ctx context.Context, apiKey string, params ClusterScopePara
}

return &ClusterScope{
client: params.Client,
Cluster: params.Cluster,
LinodeClient: linodeClient,
LinodeCluster: params.LinodeCluster,
PatchHelper: helper,
client: params.Client,
Cluster: params.Cluster,
LinodeClient: linodeClient,
LinodeCluster: params.LinodeCluster,
ControlPlaneFirewall: params.ControlPlaneFirewall,
PatchHelper: helper,
}, nil
}

// ClusterScope defines the basic context for an actuator to operate upon.
type ClusterScope struct {
client client.Client

PatchHelper *patch.Helper
LinodeClient *linodego.Client
Cluster *clusterv1.Cluster
LinodeCluster *infrav1alpha1.LinodeCluster
PatchHelper *patch.Helper
LinodeClient *linodego.Client
Cluster *clusterv1.Cluster
LinodeCluster *infrav1alpha1.LinodeCluster
ControlPlaneFirewall *infrav1alpha1.LinodeFirewall
}

// PatchObject persists the cluster configuration and status.
Expand Down
7 changes: 0 additions & 7 deletions cloud/scope/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ type FirewallScope struct {

PatchHelper *patch.Helper
LinodeClient *linodego.Client
LinodeCluster *infrav1alpha1.LinodeCluster
LinodeFirewall *infrav1alpha1.LinodeFirewall
}

// FirewallScopeParams defines the input parameters used to create a new Scope.
type FirewallScopeParams struct {
Client client.Client
LinodeCluster *infrav1alpha1.LinodeCluster
LinodeFirewall *infrav1alpha1.LinodeFirewall
}

Expand All @@ -51,10 +49,6 @@ func validateFirewallScopeParams(params FirewallScopeParams) error {
return errors.New("linodeFirewall is required when creating a FirewallScope")
}

if params.LinodeCluster == nil {
return errors.New("linodeCluster is required when creating a FirewallScope")
}

return nil
}

Expand All @@ -76,7 +70,6 @@ func NewFirewallScope(apiKey string, params FirewallScopeParams) (*FirewallScope
client: params.Client,
LinodeClient: linodeClient,
LinodeFirewall: params.LinodeFirewall,
LinodeCluster: params.LinodeCluster,
PatchHelper: helper,
}, nil
}
Expand Down
41 changes: 19 additions & 22 deletions cloud/services/firewalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/linode/linodego"

infrav1alpha1 "github.com/linode/cluster-api-provider-linode/api/v1alpha1"
"github.com/linode/cluster-api-provider-linode/cloud/scope"
)

const (
Expand All @@ -27,16 +26,16 @@ var (
errDuplicateFirewalls = errors.New("duplicate firewalls found")
)

// HandleFirewall takes the CAPL firewall representation and uses it to either create or update the Cloud Firewall
// via the given linode client
func HandleFirewall(
ctx context.Context,
firewallScope *scope.FirewallScope,
firewall *infrav1alpha1.LinodeFirewall,
linodeClient *linodego.Client,
logger logr.Logger,
) (linodeFW *linodego.Firewall, err error) {
clusterUID := string(firewallScope.LinodeCluster.UID)
tags := []string{string(firewallScope.LinodeCluster.UID)}
fwName := firewallScope.LinodeFirewall.Name

linodeFWs, err := fetchFirewalls(ctx, firewallScope)
clusterUID := firewall.Spec.ClusterUID
linodeFWs, err := fetchFirewalls(ctx, firewall.Name, *linodeClient)
if err != nil {
logger.Info("Failed to list Firewalls", "error", err.Error())

Expand All @@ -51,17 +50,17 @@ func HandleFirewall(
}

// build out the firewall rules for create or update
fwConfig, err := processACL(firewallScope.LinodeFirewall, tags)
fwConfig, err := processACL(firewall, []string{clusterUID})
if err != nil {
logger.Info("Failed to process ACL", "error", err.Error())

return nil, err
}

if len(linodeFWs) == 0 {
logger.Info(fmt.Sprintf("Creating firewall %s", fwName))
logger.Info(fmt.Sprintf("Creating firewall %s", firewall.Name))

if linodeFW, err = firewallScope.LinodeClient.CreateFirewall(ctx, *fwConfig); err != nil {
if linodeFW, err = linodeClient.CreateFirewall(ctx, *fwConfig); err != nil {
logger.Info("Failed to create Linode Firewall", "error", err.Error())
// Already exists is not an error
apiErr := linodego.Error{}
Expand All @@ -70,27 +69,27 @@ func HandleFirewall(
}

if linodeFW != nil {
logger.Info(fmt.Sprintf("Linode Firewall %s already exists", fwName))
logger.Info(fmt.Sprintf("Linode Firewall %s already exists", firewall.Name))
}
}

} else {
logger.Info(fmt.Sprintf("Updating firewall %s", fwName))
logger.Info(fmt.Sprintf("Updating firewall %s", firewall.Name))

linodeFW = &linodeFWs[0]
if !slices.Contains(linodeFW.Tags, clusterUID) {
err := errors.New("firewall conflict")
logger.Error(err, fmt.Sprintf(
"Firewall %s is not associated with cluster UID %s. Owner cluster is %s",
fwName,
firewall.Name,
clusterUID,
linodeFW.Tags[0],
))

return nil, err
}

if _, err := firewallScope.LinodeClient.UpdateFirewallRules(ctx, linodeFW.ID, fwConfig.Rules); err != nil {
if _, err := linodeClient.UpdateFirewallRules(ctx, linodeFW.ID, fwConfig.Rules); err != nil {
logger.Info("Failed to update Linode Firewall", "error", err.Error())

return nil, err
Expand All @@ -100,17 +99,17 @@ func HandleFirewall(
// Need to make sure the firewall is appropriately enabled or disabled after
// create or update and the tags are properly set
var status linodego.FirewallStatus
if firewallScope.LinodeFirewall.Spec.Enabled {
if firewall.Spec.Enabled {
status = linodego.FirewallEnabled
} else {
status = linodego.FirewallDisabled
}
if _, err = firewallScope.LinodeClient.UpdateFirewall(
if _, err = linodeClient.UpdateFirewall(
ctx,
linodeFW.ID,
linodego.FirewallUpdateOptions{
Status: status,
Tags: util.Pointer(tags),
Tags: util.Pointer([]string{clusterUID}),
},
); err != nil {
logger.Info("Failed to update Linode Firewall status and tags", "error", err.Error())
Expand All @@ -122,17 +121,15 @@ func HandleFirewall(
}

// fetch Firewalls returns all Linode firewalls with a label matching the CAPL Firewall name
func fetchFirewalls(ctx context.Context, firewallScope *scope.FirewallScope) (firewalls []linodego.Firewall, err error) {
func fetchFirewalls(ctx context.Context, name string, linodeClient linodego.Client) (firewalls []linodego.Firewall, err error) {
var linodeFWs []linodego.Firewall
filter := map[string]string{
"label": firewallScope.LinodeFirewall.Name,
}
filter := map[string]string{"label": name}

rawFilter, err := json.Marshal(filter)
if err != nil {
return nil, err
}
if linodeFWs, err = firewallScope.LinodeClient.ListFirewalls(ctx, linodego.NewListOptions(1, string(rawFilter))); err != nil {
if linodeFWs, err = linodeClient.ListFirewalls(ctx, linodego.NewListOptions(1, string(rawFilter))); err != nil {
return nil, err
}
return linodeFWs, nil
Expand Down
Loading

0 comments on commit 81d22c0

Please sign in to comment.