| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- package preview
- import (
- "fmt"
- "github.com/porter-dev/switchboard/pkg/types"
- )
- type dependencyResolver struct {
- resources []*types.Resource
- graph map[string][]string
- resolved map[string]bool
- unresolved map[string]bool
- }
- func newDependencyResolver(resources []*types.Resource) *dependencyResolver {
- return &dependencyResolver{
- resources: resources,
- graph: make(map[string][]string),
- resolved: make(map[string]bool),
- unresolved: make(map[string]bool),
- }
- }
- func (r *dependencyResolver) Resolve() error {
- if len(r.resources) > 0 {
- // construct dependency graph
- for _, resource := range r.resources {
- // check for duplicate resource
- if _, ok := r.graph[resource.Name]; ok {
- return fmt.Errorf("duplicate resource detected: '%s'", resource.Name)
- }
- r.graph[resource.Name] = append(r.graph[resource.Name], resource.DependsOn...)
- }
- for _, resource := range r.resources {
- err := r.depResolve(resource.Name)
- if err != nil {
- return err
- }
- }
- }
- return nil
- }
- func (r *dependencyResolver) depResolve(name string) error {
- r.unresolved[name] = true
- for _, dep := range r.graph[name] {
- if _, ok := r.graph[dep]; !ok {
- return fmt.Errorf("for resource '%s': invalid dependency '%s'", name, dep)
- }
- if _, ok := r.resolved[dep]; !ok {
- if _, ok = r.unresolved[dep]; ok {
- return fmt.Errorf("circular depedency detected: '%s' -> '%s'", name, dep)
- }
- err := r.depResolve(dep)
- if err != nil {
- return err
- }
- }
- }
- r.resolved[name] = true
- delete(r.unresolved, name)
- return nil
- }
|