refactor: machine listing for replicated plan

This commit is contained in:
Pavel Sviderski
2025-04-14 22:04:39 +10:00
parent 590a1b231f
commit 7705db2c4f
2 changed files with 17 additions and 23 deletions
+1 -6
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/psviderski/uncloud/internal/machine/api/pb" "github.com/psviderski/uncloud/internal/machine/api/pb"
"github.com/psviderski/uncloud/pkg/api" "github.com/psviderski/uncloud/pkg/api"
) )
@@ -68,15 +69,9 @@ func (d *Deployment) Plan(ctx context.Context) (Plan, error) {
if err != nil && !errors.Is(err, api.ErrNotFound) { if err != nil && !errors.Is(err, api.ErrNotFound) {
return Plan{}, fmt.Errorf("get cluster domain: %w", err) return Plan{}, fmt.Errorf("get cluster domain: %w", err)
} }
// TODO: enable image resolver when it's ready to pin digests and look up existing images.
//imageResolver := &ImageDigestResolver{
// Ctx: ctx,
// Client: d.cli,
//}
specResolver := &ServiceSpecResolver{ specResolver := &ServiceSpecResolver{
// If the domain is not found (not reserved), an empty domain is used for the resolver. // If the domain is not found (not reserved), an empty domain is used for the resolver.
ClusterDomain: clusterDomain, ClusterDomain: clusterDomain,
//ImageResolver: imageResolver,
} }
resolvedSpec, err := specResolver.Resolve(d.Spec) resolvedSpec, err := specResolver.Resolve(d.Spec)
+16 -17
View File
@@ -58,35 +58,34 @@ func (s *RollingStrategy) planReplicated(
return plan, err return plan, err
} }
machines, err := cli.ListMachines(ctx, nil) availableMachines, err := cli.ListMachines(ctx, &api.MachineFilter{Available: true})
if err != nil { if err != nil {
return plan, fmt.Errorf("list machines: %w", err) return plan, fmt.Errorf("list machines: %w", err)
} }
// Filter machines that are not DOWN and match the machine filter if provided.
var availableMachines []*pb.MachineInfo // Filter machines that match the machine filter if provided.
var matchedMachines []*pb.MachineInfo
var unmatchedMachines []*pb.MachineInfo var unmatchedMachines []*pb.MachineInfo
var downMachines []*pb.MachineInfo for _, m := range availableMachines {
for _, m := range machines { if s.MachineFilter == nil || s.MachineFilter(m.Machine) {
if m.State == pb.MachineMember_DOWN { matchedMachines = append(matchedMachines, m.Machine)
downMachines = append(downMachines, m.Machine)
} else { } else {
if s.MachineFilter == nil || s.MachineFilter(m.Machine) { unmatchedMachines = append(unmatchedMachines, m.Machine)
availableMachines = append(availableMachines, m.Machine)
} else {
unmatchedMachines = append(unmatchedMachines, m.Machine)
}
} }
} }
if len(availableMachines) == 0 { if len(matchedMachines) == 0 {
if s.MachineFilter != nil { if s.MachineFilter != nil {
return plan, ErrNoMatchingMachines return plan, ErrNoMatchingMachines
} }
return plan, fmt.Errorf("no available machines to deploy service") return plan, fmt.Errorf("no available machines to deploy service")
} }
// TODO: filter machines that contain the service volumes if the service uses any.s
// Randomise the order of machines to avoid always deploying to the same machines first. // Randomise the order of machines to avoid always deploying to the same machines first.
rand.Shuffle(len(availableMachines), func(i, j int) { rand.Shuffle(len(matchedMachines), func(i, j int) {
availableMachines[i], availableMachines[j] = availableMachines[j], availableMachines[i] matchedMachines[i], matchedMachines[j] = matchedMachines[j], matchedMachines[i]
}) })
// Organise existing containers by machine. // Organise existing containers by machine.
@@ -125,7 +124,7 @@ func (s *RollingStrategy) planReplicated(
// Sort machines such that machines with the most up-to-date containers are first, followed by machines with // Sort machines such that machines with the most up-to-date containers are first, followed by machines with
// existing containers, and finally machines without containers. // existing containers, and finally machines without containers.
slices.SortFunc(availableMachines, func(m1, m2 *pb.MachineInfo) int { slices.SortFunc(matchedMachines, func(m1, m2 *pb.MachineInfo) int {
if upToDateContainersOnMachine[m1.Id] > 0 && upToDateContainersOnMachine[m2.Id] > 0 { if upToDateContainersOnMachine[m1.Id] > 0 && upToDateContainersOnMachine[m2.Id] > 0 {
return upToDateContainersOnMachine[m2.Id] - upToDateContainersOnMachine[m1.Id] return upToDateContainersOnMachine[m2.Id] - upToDateContainersOnMachine[m1.Id]
} }
@@ -142,7 +141,7 @@ func (s *RollingStrategy) planReplicated(
// Spread the containers across the available machines evenly using a simple round-robin approach, starting with // Spread the containers across the available machines evenly using a simple round-robin approach, starting with
// machines that already have containers and prioritising machines with containers that match the desired spec. // machines that already have containers and prioritising machines with containers that match the desired spec.
for i := 0; i < int(spec.Replicas); i++ { for i := 0; i < int(spec.Replicas); i++ {
m := availableMachines[i%len(availableMachines)] m := matchedMachines[i%len(matchedMachines)]
containers := containersOnMachine[m.Id] containers := containersOnMachine[m.Id]
if len(containers) == 0 { if len(containers) == 0 {