Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit 8c78b08

Browse files
authored
Merge pull request #32 from gianarb/feature/get-master-ip
get ip from control plan during cluster reconciliation
2 parents aa900b3 + 8b6f4e7 commit 8c78b08

File tree

6 files changed

+122
-12
lines changed

6 files changed

+122
-12
lines changed

api/v1alpha3/types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ type PacketResourceStatus string
66
var (
77
// PacketResourceStatus is the string representing a Packet resource just created and in a provisioning state.
88
PacketResourceStatusNew = PacketResourceStatus("new")
9+
// PacketResourceStatusQueued is the string representing a Packet resource that is waiting in a queue to be created.
10+
PacketResourceStatusQueued = PacketResourceStatus("queued")
11+
// PacketResourceStatusQueued is the string representing a Packet resource
12+
// that got picked from a worker that is not provisioning it.
13+
PacketResourceStatusProvisioning = PacketResourceStatus("provisioning")
914
// PacketResourceStatusRunning is the string representing a Packet resource already provisioned and in a active state.
1015
PacketResourceStatusRunning = PacketResourceStatus("active")
1116
// PacketResourceStatusErrored is the string representing a Packet resource in a errored state.

controllers/packetcluster_controller.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package controllers
1818

1919
import (
2020
"context"
21+
"fmt"
2122
"time"
2223

2324
"github.com/go-logr/logr"
@@ -33,15 +34,17 @@ import (
3334
"sigs.k8s.io/controller-runtime/pkg/source"
3435

3536
infrastructurev1alpha3 "github.com/packethost/cluster-api-provider-packet/api/v1alpha3"
37+
packet "github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet"
3638
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet/scope"
3739
)
3840

3941
// PacketClusterReconciler reconciles a PacketCluster object
4042
type PacketClusterReconciler struct {
4143
client.Client
42-
Log logr.Logger
43-
Recorder record.EventRecorder
44-
Scheme *runtime.Scheme
44+
Log logr.Logger
45+
Recorder record.EventRecorder
46+
Scheme *runtime.Scheme
47+
PacketClient *packet.PacketClient
4548
}
4649

4750
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=packetclusters,verbs=get;list;watch;create;update;patch;delete
@@ -94,9 +97,30 @@ func (r *PacketClusterReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
9497
}
9598
}()
9699

97-
// we have no setup to be done
98100
clusterScope.PacketCluster.Status.Ready = true
99101

102+
address, err := r.getIP(clusterScope.PacketCluster)
103+
_, isNoMachine := err.(*MachineNotFound)
104+
_, isNoIP := err.(*MachineNoIP)
105+
switch {
106+
case err != nil && isNoMachine:
107+
logger.Info("Control plan device not found. Requeueing...")
108+
return ctrl.Result{Requeue: true, RequeueAfter: 30 * time.Second}, nil
109+
case err != nil && isNoIP:
110+
logger.Info("Control plan device not found. Requeueing...")
111+
return ctrl.Result{Requeue: true, RequeueAfter: 30 * time.Second}, nil
112+
case err != nil:
113+
logger.Error(err, "error getting a control plan ip")
114+
return ctrl.Result{}, err
115+
case err == nil:
116+
clusterScope.PacketCluster.Status.APIEndpoints = []infrastructurev1alpha3.APIEndpoint{
117+
{
118+
Host: address,
119+
Port: 6443,
120+
},
121+
}
122+
}
123+
100124
return ctrl.Result{}, nil
101125
}
102126

@@ -111,3 +135,45 @@ func (r *PacketClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
111135
).
112136
Complete(r)
113137
}
138+
139+
func (r *PacketClusterReconciler) getIP(cluster *infrastructurev1alpha3.PacketCluster) (string, error) {
140+
if cluster == nil {
141+
return "", fmt.Errorf("cannot get IP of machine in nil cluster")
142+
}
143+
tags := []string{
144+
packet.GenerateClusterTag(string(cluster.Name)),
145+
infrastructurev1alpha3.MasterTag,
146+
}
147+
device, err := r.PacketClient.GetDeviceByTags(cluster.Spec.ProjectID, tags)
148+
if err != nil {
149+
return "", fmt.Errorf("error retrieving machine: %v", err)
150+
}
151+
if device == nil {
152+
return "", &MachineNotFound{err: fmt.Sprintf("machine does not exist")}
153+
}
154+
if device.Network == nil || len(device.Network) == 0 || device.Network[0].Address == "" {
155+
return "", &MachineNoIP{err: "machine does not yet have an IP address"}
156+
}
157+
// TODO: validate that this address exists, so we don't hit nil pointer
158+
// TODO: check which address to return
159+
// TODO: check address format (cidr, subnet, etc.)
160+
return device.Network[0].Address, nil
161+
}
162+
163+
// MachineNotFound error representing that the requested device was not yet found
164+
type MachineNotFound struct {
165+
err string
166+
}
167+
168+
func (e *MachineNotFound) Error() string {
169+
return e.err
170+
}
171+
172+
// MachineNoIP error representing that the requested device does not have an IP yet assigned
173+
type MachineNoIP struct {
174+
err string
175+
}
176+
177+
func (e *MachineNoIP) Error() string {
178+
return e.err
179+
}

controllers/packetmachine_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ func (r *PacketMachineReconciler) reconcile(ctx context.Context, machineScope *s
234234
var result = ctrl.Result{}
235235

236236
switch infrastructurev1alpha3.PacketResourceStatus(dev.State) {
237-
case infrastructurev1alpha3.PacketResourceStatusNew:
237+
case infrastructurev1alpha3.PacketResourceStatusNew, infrastructurev1alpha3.PacketResourceStatusQueued:
238238
machineScope.Info("Machine instance is pending", "instance-id", machineScope.GetInstanceID())
239239
result = ctrl.Result{RequeueAfter: 10 * time.Second}
240240
case infrastructurev1alpha3.PacketResourceStatusRunning:

main.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ func main() {
8585
}
8686

8787
if err = (&controllers.PacketClusterReconciler{
88-
Client: mgr.GetClient(),
89-
Log: ctrl.Log.WithName("controllers").WithName("PacketCluster"),
90-
Recorder: mgr.GetEventRecorderFor("packetcluster-controller"),
91-
Scheme: mgr.GetScheme(),
88+
Client: mgr.GetClient(),
89+
Log: ctrl.Log.WithName("controllers").WithName("PacketCluster"),
90+
Recorder: mgr.GetEventRecorderFor("packetcluster-controller"),
91+
PacketClient: client,
92+
Scheme: mgr.GetScheme(),
9293
}).SetupWithManager(mgr); err != nil {
9394
setupLog.Error(err, "unable to create controller", "controller", "PacketCluster")
9495
os.Exit(1)

pkg/cloud/packet/client.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,17 @@ func (p *PacketClient) GetDeviceAddresses(device *packngo.Device) ([]corev1.Node
7474
}
7575
return addrs, nil
7676
}
77+
78+
func (p *PacketClient) GetDeviceByTags(project string, tags []string) (*packngo.Device, error) {
79+
devices, _, err := p.Devices.List(project, nil)
80+
if err != nil {
81+
return nil, fmt.Errorf("Error retrieving devices: %v", err)
82+
}
83+
// returns the first one that matches all of the tags
84+
for _, device := range devices {
85+
if ItemsInList(device.Tags, tags) {
86+
return &device, nil
87+
}
88+
}
89+
return nil, nil
90+
}

pkg/cloud/packet/util.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,40 @@
11
package packet
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
)
46

57
const (
6-
machineUIDTag = "cluster-api-provider-packet:machine-uid"
8+
MachineUIDTag = "cluster-api-provider-packet:machine-uid"
79
clusterIDTag = "cluster-api-provider-packet:cluster-id"
810
AnnotationUID = "cluster.k8s.io/machine-uid"
911
)
1012

1113
func GenerateMachineTag(ID string) string {
12-
return fmt.Sprintf("%s:%s", machineUIDTag, ID)
14+
return fmt.Sprintf("%s:%s", MachineUIDTag, ID)
1315
}
1416
func GenerateClusterTag(ID string) string {
1517
return fmt.Sprintf("%s:%s", clusterIDTag, ID)
1618
}
19+
20+
// ItemsInList checks if all items are in the list
21+
func ItemsInList(list []string, items []string) bool {
22+
// convert the items against which we are mapping into a map
23+
itemMap := map[string]bool{}
24+
for _, elm := range items {
25+
itemMap[elm] = false
26+
}
27+
// every one that is matched goes from false to true in the map
28+
for _, elm := range list {
29+
if _, ok := itemMap[elm]; ok {
30+
itemMap[elm] = true
31+
}
32+
}
33+
// go through the map; if any is false, return false, else all matched so return true
34+
for _, v := range itemMap {
35+
if !v {
36+
return false
37+
}
38+
}
39+
return true
40+
}

0 commit comments

Comments
 (0)