|
| 1 | +package controller |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "regexp" |
| 6 | + "slices" |
| 7 | + |
| 8 | + valkeyClient "github.com/valkey-io/valkey-go" |
| 9 | +) |
| 10 | + |
| 11 | +// valkeyCluster represents a Valkey cluster. It contains a list of shards, each with its own nodes. |
| 12 | +type valkeyCluster struct { |
| 13 | + shards []*valkeyShard |
| 14 | +} |
| 15 | + |
| 16 | +// valkeyShard represents a shard in the Valkey cluster. It contains slot information and a list of nodes. |
| 17 | +type valkeyShard struct { |
| 18 | + id int |
| 19 | + slotMin int |
| 20 | + slotMax int |
| 21 | + nodes []*valkeyNode |
| 22 | +} |
| 23 | + |
| 24 | +// valkeyNode represents a node in the Valkey cluster. |
| 25 | +type valkeyNode struct { |
| 26 | + // id is the node id in the Valkey cluster |
| 27 | + id string |
| 28 | + // name is the pod name in Kubernetes |
| 29 | + name string |
| 30 | + // ip is the pod ip in Kubernetes |
| 31 | + ip string |
| 32 | + // port is the port of the Valkey service |
| 33 | + port int |
| 34 | + // flags are the Valkey flags for this pod |
| 35 | + flags []string |
| 36 | + // primary is the id of the primary node when this node is a replica |
| 37 | + primary string |
| 38 | + // connected is true when the pod is reachable from the operator |
| 39 | + connected bool |
| 40 | + // shard is the id of the shard this node belongs to |
| 41 | + shard int |
| 42 | + // client is the Valkey client for this node, if connected. |
| 43 | + client valkeyClient.Client |
| 44 | +} |
| 45 | + |
| 46 | +// isPrimary checks if this node is a primary node for the shard in the Valkey cluster. |
| 47 | +func (vn *valkeyNode) isPrimary() bool { |
| 48 | + return slices.Contains(vn.flags, "master") |
| 49 | +} |
| 50 | + |
| 51 | +// stsPodIndex extracts the pod index number from the pod name. The pod name is expected to be in |
| 52 | +// the format <name>-<number>. The pod index is the pod number from a StatefulSet. |
| 53 | +func stsPodIndex(podName string) (int, error) { |
| 54 | + pattern := `.*-(\d+)$` |
| 55 | + re := regexp.MustCompile(pattern) |
| 56 | + |
| 57 | + matches := re.FindStringSubmatch(podName) |
| 58 | + if len(matches) < 2 { |
| 59 | + return 0, fmt.Errorf("no number found in pod name: %s", podName) |
| 60 | + } |
| 61 | + |
| 62 | + // Convert the captured group to an integer |
| 63 | + var number int |
| 64 | + _, err := fmt.Sscanf(matches[1], "%d", &number) |
| 65 | + if err != nil { |
| 66 | + return 0, fmt.Errorf("failed to parse number: %w", err) |
| 67 | + } |
| 68 | + |
| 69 | + return number, nil |
| 70 | +} |
0 commit comments