Skip to content

Commit

Permalink
add ability to turn off private IPs and fix some misc api spec fields
Browse files Browse the repository at this point in the history
  • Loading branch information
eljohnson92 authored and AshleyDumaine committed Apr 19, 2024
1 parent 93c223c commit 72741ed
Show file tree
Hide file tree
Showing 15 changed files with 533 additions and 61 deletions.
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ issues:
- path: _test(ing)?\.go
linters:
- gocyclo
- maintidx
- errcheck
- dupl
- gosec
Expand Down
6 changes: 3 additions & 3 deletions api/v1alpha1/linodemachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ type LinodeMachineSpec struct {
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
AuthorizedUsers []string `json:"authorizedUsers,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
BackupID int `json:"backupId,omitempty"`
BackupID int `json:"backupID,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
Image string `json:"image,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
Interfaces []InstanceConfigInterfaceCreateOptions `json:"interfaces,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
BackupsEnabled bool `json:"backupsEnabled,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
PrivateIP bool `json:"privateIp,omitempty"`
PrivateIP *bool `json:"privateIP,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
Tags []string `json:"tags,omitempty"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
FirewallID int `json:"firewallId,omitempty"`
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
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/linodeobjectstoragebucket_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ type LinodeObjectStorageBucketStatus struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=linodeobjectstoragebuckets,scope=Namespaced,shortName=lobj
// +kubebuilder:resource:path=linodeobjectstoragebuckets,scope=Namespaced,categories=cluster-api,shortName=lobj
// +kubebuilder:subresource:status
// +kubebuilder:metadata:labels="clusterctl.cluster.x-k8s.io/move-hierarchy=true"
// +kubebuilder:printcolumn:name="Label",type="string",JSONPath=".spec.label",description="The name of the bucket"
Expand All @@ -116,7 +116,7 @@ func (b *LinodeObjectStorageBucket) SetConditions(conditions clusterv1.Condition
b.Status.Conditions = conditions
}

//+kubebuilder:object:root=true
// +kubebuilder:object:root=true

// LinodeObjectStorageBucketList contains a list of LinodeObjectStorageBucket
type LinodeObjectStorageBucketList struct {
Expand Down
2 changes: 2 additions & 0 deletions api/v1alpha1/linodevpc_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ type LinodeVPCStatus struct {
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=linodevpcs,scope=Namespaced,categories=cluster-api,shortName=lvpc
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready",description="VPC is ready"
// +kubebuilder:metadata:labels="clusterctl.cluster.x-k8s.io/move-hierarchy=true"

// LinodeVPC is the Schema for the linodemachines API
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.

7 changes: 3 additions & 4 deletions cloud/scope/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ type MachineScopeParams struct {
}

type MachineScope struct {
client k8sClient

Client k8sClient
PatchHelper *patch.Helper
Cluster *clusterv1.Cluster
Machine *clusterv1.Machine
Expand Down Expand Up @@ -93,7 +92,7 @@ func NewMachineScope(ctx context.Context, apiKey string, params MachineScopePara
}

return &MachineScope{
client: params.Client,
Client: params.Client,
PatchHelper: helper,
Cluster: params.Cluster,
Machine: params.Machine,
Expand Down Expand Up @@ -135,7 +134,7 @@ func (m *MachineScope) GetBootstrapData(ctx context.Context) ([]byte, error) {

secret := &corev1.Secret{}
key := types.NamespacedName{Namespace: m.LinodeMachine.Namespace, Name: *m.Machine.Spec.Bootstrap.DataSecretName}
if err := m.client.Get(ctx, key, secret); err != nil {
if err := m.Client.Get(ctx, key, secret); err != nil {
return []byte{}, fmt.Errorf(
"failed to retrieve bootstrap data secret for LinodeMachine %s/%s",
m.LinodeMachine.Namespace,
Expand Down
2 changes: 1 addition & 1 deletion cloud/scope/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ func TestMachineScopeGetBootstrapData(t *testing.T) {
testcase.expects(mockK8sClient)

mScope := &MachineScope{
client: mockK8sClient,
Client: mockK8sClient,
PatchHelper: &patch.Helper{}, // empty patch helper
Cluster: testcase.fields.Cluster,
Machine: testcase.fields.Machine,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
backupId:
backupID:
type: integer
x-kubernetes-validations:
- message: Value is immutable
Expand Down Expand Up @@ -107,7 +107,7 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
firewallId:
firewallID:
type: integer
x-kubernetes-validations:
- message: Value is immutable
Expand Down Expand Up @@ -161,7 +161,7 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
privateIp:
privateIP:
type: boolean
x-kubernetes-validations:
- message: Value is immutable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
backupId:
backupID:
type: integer
x-kubernetes-validations:
- message: Value is immutable
Expand Down Expand Up @@ -94,7 +94,7 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
firewallId:
firewallID:
type: integer
x-kubernetes-validations:
- message: Value is immutable
Expand Down Expand Up @@ -150,7 +150,7 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
privateIp:
privateIP:
type: boolean
x-kubernetes-validations:
- message: Value is immutable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ metadata:
spec:
group: infrastructure.cluster.x-k8s.io
names:
categories:
- cluster-api
kind: LinodeObjectStorageBucket
listKind: LinodeObjectStorageBucketList
plural: linodeobjectstoragebuckets
Expand Down
11 changes: 10 additions & 1 deletion config/crd/bases/infrastructure.cluster.x-k8s.io_linodevpcs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ metadata:
spec:
group: infrastructure.cluster.x-k8s.io
names:
categories:
- cluster-api
kind: LinodeVPC
listKind: LinodeVPCList
plural: linodevpcs
shortNames:
- lvpc
singular: linodevpc
scope: Namespaced
versions:
- name: v1alpha1
- additionalPrinterColumns:
- description: VPC is ready
jsonPath: .status.ready
name: Ready
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: LinodeVPC is the Schema for the linodemachines API
Expand Down
96 changes: 55 additions & 41 deletions controller/linodemachine_controller_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,51 +62,14 @@ func (r *LinodeMachineReconciler) newCreateConfig(ctx context.Context, machineSc

createConfig.Booted = util.Pointer(false)

createConfig.PrivateIP = true

bootstrapData, err := machineScope.GetBootstrapData(ctx)
if err != nil {
logger.Info("Failed to get bootstrap data", "error", err.Error())

return nil, err
}
if len(bootstrapData) > maxBootstrapDataBytes {
err = errors.New("bootstrap data too large")
logger.Info(fmt.Sprintf("decoded bootstrap data exceeds size limit of %d bytes", maxBootstrapDataBytes), "error", err.Error())

if err := setUserData(ctx, machineScope, createConfig, logger); err != nil {
return nil, err
}

region, err := machineScope.LinodeClient.GetRegion(ctx, machineScope.LinodeMachine.Spec.Region)
if err != nil {
return nil, err
}
regionMetadataSupport := slices.Contains(region.Capabilities, "Metadata")
image, err := machineScope.LinodeClient.GetImage(ctx, machineScope.LinodeMachine.Spec.Image)
if err != nil {
return nil, err
}
imageMetadataSupport := slices.Contains(image.Capabilities, "cloud-init")
if imageMetadataSupport && regionMetadataSupport {
createConfig.Metadata = &linodego.InstanceMetadataOptions{
UserData: b64.StdEncoding.EncodeToString(bootstrapData),
}
if machineScope.LinodeMachine.Spec.PrivateIP != nil {
createConfig.PrivateIP = *machineScope.LinodeMachine.Spec.PrivateIP
} else {
logger.Info(fmt.Sprintf("using StackScripts for bootstrapping. imageMetadataSupport: %t, regionMetadataSupport: %t",
imageMetadataSupport, regionMetadataSupport))
capiStackScriptID, err := services.EnsureStackscript(ctx, machineScope)
if err != nil {
return nil, err
}
createConfig.StackScriptID = capiStackScriptID
// ###### WARNING, currently label, region and type are supported as cloud-init variables, any changes ######
// any changes to this could be potentially backwards incompatible and should be noted through a backwards incompatible version update #####
instanceData := fmt.Sprintf("label: %s\nregion: %s\ntype: %s", machineScope.LinodeMachine.Name, machineScope.LinodeMachine.Spec.Region, machineScope.LinodeMachine.Spec.Type)
// ###### WARNING ######
createConfig.StackScriptData = map[string]string{
"instancedata": b64.StdEncoding.EncodeToString([]byte(instanceData)),
"userdata": b64.StdEncoding.EncodeToString(bootstrapData),
}
createConfig.PrivateIP = true
}

if createConfig.Tags == nil {
Expand Down Expand Up @@ -394,3 +357,54 @@ func linodeMachineSpecToInstanceCreateConfig(machineSpec infrav1alpha1.LinodeMac

return &createConfig
}

func setUserData(ctx context.Context, machineScope *scope.MachineScope, createConfig *linodego.InstanceCreateOptions, logger logr.Logger) error {
bootstrapData, err := machineScope.GetBootstrapData(ctx)
if err != nil {
logger.Error(err, "Failed to get bootstrap data")

return err
}
if len(bootstrapData) > maxBootstrapDataBytes {
err = errors.New("bootstrap data too large")
logger.Error(err, "decoded bootstrap data exceeds size limit",
"limit", maxBootstrapDataBytes,
)

return err
}

region, err := machineScope.LinodeClient.GetRegion(ctx, machineScope.LinodeMachine.Spec.Region)
if err != nil {
return fmt.Errorf("get region: %w", err)
}
regionMetadataSupport := slices.Contains(region.Capabilities, "Metadata")
image, err := machineScope.LinodeClient.GetImage(ctx, machineScope.LinodeMachine.Spec.Image)
if err != nil {
return fmt.Errorf("get image: %w", err)
}
imageMetadataSupport := slices.Contains(image.Capabilities, "cloud-init")
if imageMetadataSupport && regionMetadataSupport {
createConfig.Metadata = &linodego.InstanceMetadataOptions{
UserData: b64.StdEncoding.EncodeToString(bootstrapData),
}
} else {
logger.Info("using StackScripts for bootstrapping",
"imageMetadataSupport", imageMetadataSupport,
"regionMetadataSupport", regionMetadataSupport,
)
capiStackScriptID, err := services.EnsureStackscript(ctx, machineScope)
if err != nil {
return fmt.Errorf("ensure stackscript: %w", err)
}
createConfig.StackScriptID = capiStackScriptID
// WARNING: label, region and type are currently supported as cloud-init variables,
// any changes to this could be potentially backwards incompatible and should be noted through a backwards incompatible version update
instanceData := fmt.Sprintf("label: %s\nregion: %s\ntype: %s", machineScope.LinodeMachine.Name, machineScope.LinodeMachine.Spec.Region, machineScope.LinodeMachine.Spec.Type)
createConfig.StackScriptData = map[string]string{
"instancedata": b64.StdEncoding.EncodeToString([]byte(instanceData)),
"userdata": b64.StdEncoding.EncodeToString(bootstrapData),
}
}
return nil
}
Loading

0 comments on commit 72741ed

Please sign in to comment.