Skip to content

Commit

Permalink
feat: extend multi-tenancy for LinodeMachines (#163)
Browse files Browse the repository at this point in the history
* feat: extend multi-tenancy for LinodeMachines

Updates LinodeMachines to be able to supply an (optional) CredentialsRef field to override the
credentials of their owner LinodeCluster.

This allows clusters to provision Linode resources cross-account.

* docs: update multi-tenant clusters
  • Loading branch information
cbzzz authored Mar 6, 2024
1 parent 6c9f0a8 commit 8dff126
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 3 deletions.
10 changes: 10 additions & 0 deletions api/v1alpha1/linodemachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package v1alpha1

import (
"github.com/linode/linodego"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
Expand Down Expand Up @@ -75,6 +76,15 @@ type LinodeMachineSpec struct {
Metadata *InstanceMetadataOptions `json:"metadata,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
FirewallID int `json:"firewallId,omitempty"`

// CredentialsRef is a reference to a Secret that contains the credentials
// to use for provisioning this machine. If not supplied then these
// credentials will be used in-order:
// 1. LinodeMachine
// 2. Owner LinodeCluster
// 3. Controller
// +optional
CredentialsRef *corev1.SecretReference `json:"credentialsRef,omitempty"`
}

// InstanceMetadataOptions defines metadata of instance
Expand Down
25 changes: 22 additions & 3 deletions cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,28 @@ func NewMachineScope(ctx context.Context, apiKey string, params MachineScopePara
return nil, err
}

// Override the controller credentials with ones from the Cluster's Secret reference (if supplied).
if params.LinodeCluster.Spec.CredentialsRef != nil {
data, err := getCredentialDataFromRef(ctx, params.Client, *params.LinodeCluster.Spec.CredentialsRef, params.LinodeCluster.GetNamespace())
// Override the controller credentials with ones from the Machine's Secret reference (if supplied).
// Credentials will be used in the following order:
// 1. LinodeMachine
// 2. Owner LinodeCluster
// 3. Controller
var (
credentialRef *corev1.SecretReference
defaultNamespace string
)
switch {
case params.LinodeMachine.Spec.CredentialsRef != nil:
credentialRef = params.LinodeMachine.Spec.CredentialsRef
defaultNamespace = params.LinodeMachine.GetNamespace()
case params.LinodeCluster.Spec.CredentialsRef != nil:
credentialRef = params.LinodeCluster.Spec.CredentialsRef
defaultNamespace = params.LinodeCluster.GetNamespace()
default:
// Use default (controller) credentials
}

if credentialRef != nil {
data, err := getCredentialDataFromRef(ctx, params.Client, *credentialRef, defaultNamespace)
if err != nil {
return nil, fmt.Errorf("credentials from cluster secret ref: %w", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,25 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
credentialsRef:
description: |-
CredentialsRef is a reference to a Secret that contains the credentials
to use for provisioning this machine. If not supplied then these
credentials will be used in-order:
1. Machine
2. Cluster
2. Controller
properties:
name:
description: name is unique within a namespace to reference a
secret resource.
type: string
namespace:
description: namespace defines the space within which the secret
name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
firewallId:
type: integer
x-kubernetes-validations:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,25 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
credentialsRef:
description: |-
CredentialsRef is a reference to a Secret that contains the credentials
to use for provisioning this machine. If not supplied then these
credentials will be used in-order:
1. Machine
2. Cluster
2. Controller
properties:
name:
description: name is unique within a namespace to reference
a secret resource.
type: string
namespace:
description: namespace defines the space within which
the secret name must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
firewallId:
type: integer
x-kubernetes-validations:
Expand Down
15 changes: 15 additions & 0 deletions docs/src/topics/multi-tenancy.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ spec:
credentialsRef:
name: linode-credentials
...
---
# Example: LinodeMachine
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
kind: LinodeMachine
metadata:
name: test-machine
spec:
credentialsRef:
name: linode-credentials
...
```

Secrets from other namespaces by additionally specifying an optional
Expand All @@ -49,3 +59,8 @@ Secrets from other namespaces by additionally specifying an optional
```admonish warning
If `.spec.credentialsRef` is set for a LinodeCluster, it should also be set for adjacent resources (e.g. LinodeVPC).
```

## LinodeMachine

For LinodeMachines, credentials set on the LinodeMachine object will override any credentials supplied by the owner
LinodeCluster. This can allow cross-account deployment of the Linodes for a cluster.

0 comments on commit 8dff126

Please sign in to comment.