From 380dd40949bd347ded03be69d942a5937d05b33c Mon Sep 17 00:00:00 2001 From: Simon Murray Date: Fri, 29 Nov 2024 11:21:59 +0000 Subject: [PATCH] Use Generics from Common Library --- go.mod | 5 +- go.sum | 10 ++-- .../managers/application/provisioner.go | 12 ++--- pkg/solver/solver.go | 47 +++++++------------ 4 files changed, 32 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index 04cf845..71307c1 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,9 @@ require ( github.com/google/uuid v1.6.0 github.com/oapi-codegen/runtime v1.1.1 github.com/spf13/pflag v1.0.5 - github.com/spjmurray/go-sat v0.3.1 - github.com/stretchr/testify v1.9.0 + github.com/spjmurray/go-sat v0.4.0 + github.com/spjmurray/go-util v0.1.2 + github.com/stretchr/testify v1.10.0 github.com/unikorn-cloud/core v0.1.86 github.com/unikorn-cloud/identity v0.2.45 github.com/unikorn-cloud/kubernetes v0.2.51 diff --git a/go.sum b/go.sum index cf17fcb..2416351 100644 --- a/go.sum +++ b/go.sum @@ -126,13 +126,15 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spjmurray/go-sat v0.3.1 h1:6EAi0GtbSUwS1fJtVJx7e8X+1q/IbClI5BQ5TAuyPgk= -github.com/spjmurray/go-sat v0.3.1/go.mod h1:PfXzQbyb3Tucoyw9jNb3/Kj0VQUrK2KQ8F1NWBvCPPk= +github.com/spjmurray/go-sat v0.4.0 h1:BFD20Ot3wKN4Rf26vVOjfosda2MJW/uJ6GrDruKiTdU= +github.com/spjmurray/go-sat v0.4.0/go.mod h1:DCU2g/lAREdvbec/Szz+Sqcg4NiO1RxzAP+nJHExoq8= +github.com/spjmurray/go-util v0.1.2 h1:dZ9ZGus+P95kcFMDY+aR/0SAj+c3WMC8ZAT/CHLa9UM= +github.com/spjmurray/go-util v0.1.2/go.mod h1:fARcBeaHio/6h9H7Ht+egZPBZMNxEwxmHC1vyjBtPbs= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/unikorn-cloud/core v0.1.86 h1:U8+V5CcTgWT0tVqM6nxlOqLmLP+43Zu0og3OzSe84aI= diff --git a/pkg/provisioners/managers/application/provisioner.go b/pkg/provisioners/managers/application/provisioner.go index e49b912..a54d290 100644 --- a/pkg/provisioners/managers/application/provisioner.go +++ b/pkg/provisioners/managers/application/provisioner.go @@ -22,7 +22,7 @@ import ( "fmt" "github.com/spf13/pflag" - sat "github.com/spjmurray/go-sat" + "github.com/spjmurray/go-util/pkg/set" unikornv1 "github.com/unikorn-cloud/application/pkg/apis/unikorn/v1alpha1" "github.com/unikorn-cloud/application/pkg/solver" @@ -115,7 +115,7 @@ type schedulerVistor struct { applications solver.ApplicationIndex appVersions map[string]solver.AppVersion dependers map[string][]string - seen sat.Set[string] + seen set.Set[string] order []solver.AppVersion } @@ -140,7 +140,7 @@ func (v *schedulerVistor) Visit(av solver.AppVersion, enqueue func(solver.AppVer satisfied := true for _, dep := range version.Dependencies { - if !v.seen.Has(dep.Name) { + if !v.seen.Contains(dep.Name) { satisfied = false break @@ -157,7 +157,7 @@ func (v *schedulerVistor) Visit(av solver.AppVersion, enqueue func(solver.AppVer } // Schedule takes a SAT solution and creates an installation order for the applications. -func Schedule(ctx context.Context, applications solver.ApplicationIndex, solution sat.Set[solver.AppVersion]) ([]solver.AppVersion, error) { +func Schedule(ctx context.Context, applications solver.ApplicationIndex, solution set.Set[solver.AppVersion]) ([]solver.AppVersion, error) { // Okay, we need to build up a reverse map of dependencies and also // record the packages with no dependencies as those will be installed // first. @@ -199,7 +199,7 @@ func Schedule(ctx context.Context, applications solver.ApplicationIndex, solutio applications: applications, appVersions: appVersions, dependers: dependers, - seen: sat.Set[string]{}, + seen: set.Set[string]{}, } if err := graph.Walk(visitor); err != nil { @@ -233,7 +233,7 @@ func (p *Provisioner) getClusterManager(ctx context.Context, cluster *unikornv1k // removeOrphanedApplications does exactly that, we can only see what the user currently // wants installed, so we need to inspect what the CD driver can see on the system and // manually prune anything that's installed by shouldn't be. -func (p *Provisioner) removeOrphanedApplications(ctx context.Context, required sat.Set[solver.AppVersion]) error { +func (p *Provisioner) removeOrphanedApplications(ctx context.Context, required set.Set[solver.AppVersion]) error { // List all applications that exist for this resource. labels, err := p.applicationset.ResourceLabels() if err != nil { diff --git a/pkg/solver/solver.go b/pkg/solver/solver.go index 27072ea..baaa04e 100644 --- a/pkg/solver/solver.go +++ b/pkg/solver/solver.go @@ -21,7 +21,9 @@ import ( "errors" "fmt" - sat "github.com/spjmurray/go-sat" + "github.com/spjmurray/go-sat/pkg/cdcl" + "github.com/spjmurray/go-util/pkg/queue" + "github.com/spjmurray/go-util/pkg/set" unikornv1 "github.com/unikorn-cloud/application/pkg/apis/unikorn/v1alpha1" unikornv1core "github.com/unikorn-cloud/core/pkg/apis/unikorn/v1alpha1" @@ -38,25 +40,6 @@ var ( ErrConstraint = errors.New("constraint error") ) -type Queue[T any] struct { - items []T -} - -func (q *Queue[T]) Empty() bool { - return len(q.items) == 0 -} - -func (q *Queue[T]) Push(value T) { - q.items = append(q.items, value) -} - -func (q *Queue[T]) Pop() T { - value := q.items[0] - q.items = q.items[1:] - - return value -} - // GraphVisitor is used to visit a node in the graph. type GraphVisitor[T comparable] interface { // Visit is called when a new node is encountered, it accepts @@ -65,13 +48,14 @@ type GraphVisitor[T comparable] interface { } type GraphWalker[T comparable] struct { - queue Queue[T] - seen sat.Set[T] + queue *queue.Queue[T] + seen set.Set[T] } func NewGraphWalker[T comparable]() *GraphWalker[T] { return &GraphWalker[T]{ - seen: sat.Set[T]{}, + queue: queue.New[T](), + seen: set.New[T](), } } @@ -81,9 +65,12 @@ func (g *GraphWalker[T]) Enqueue(t T) { func (g *GraphWalker[T]) Walk(visitor GraphVisitor[T]) error { for !g.queue.Empty() { - t := g.queue.Pop() + t, err := g.queue.Pop() + if err != nil { + return err + } - if g.seen.Has(t) { + if g.seen.Contains(t) { continue } @@ -143,7 +130,7 @@ func (i ApplicationIndex) Get(name string) (*unikornv1core.HelmApplication, erro type solverVisitor struct { applications ApplicationIndex - model *sat.Model[AppVersion] + model *cdcl.Model[AppVersion] } //nolint:cyclop @@ -217,12 +204,12 @@ func (v *solverVisitor) Visit(name string, enqueue func(string)) error { // then we have a conflict, and have to backtrack and try again with another version. // Unlike typical SAT solver problems, choosing a different version can have the fun // effect of changing its dependencies! -func SolveApplicationSet(ctx context.Context, applications ApplicationIndex, applicationset *unikornv1.ApplicationSet) (sat.Set[AppVersion], error) { +func SolveApplicationSet(ctx context.Context, applications ApplicationIndex, applicationset *unikornv1.ApplicationSet) (set.Set[AppVersion], error) { // We're going to do an exhaustive walk of the dependency graph gathering // all application/version tuples as variables, and also create any clauses along the way. graph := NewGraphWalker[string]() - model := sat.NewModel[AppVersion]() + model := cdcl.NewModel[AppVersion]() // Populate the work queue with any application IDs that are requested by the // user and any clauses relevant to the solver. @@ -266,12 +253,12 @@ func SolveApplicationSet(ctx context.Context, applications ApplicationIndex, app } // Solve the problem. - if err := sat.NewCDCLSolver().Solve(model, sat.DefaultChooser); err != nil { + if err := cdcl.New().Solve(model, cdcl.DefaultChooser); err != nil { return nil, err } // Get the result. - result := sat.Set[AppVersion]{} + result := set.Set[AppVersion]{} for av, b := range model.Variables() { if b.Value() {