-
Notifications
You must be signed in to change notification settings - Fork 2
/
dogu_dependency_validator.go
124 lines (100 loc) · 4.11 KB
/
dogu_dependency_validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package dependency
import (
"context"
"errors"
"fmt"
"sigs.k8s.io/controller-runtime/pkg/log"
"github.com/cloudogu/cesapp-lib/core"
"github.com/cloudogu/cesapp-lib/registry"
"github.com/cloudogu/k8s-dogu-operator/controllers/cesregistry"
"github.com/cloudogu/k8s-dogu-operator/internal/cloudogu"
)
// dependencyValidationError is returned when a given dependency cloud not be validated.
type dependencyValidationError struct {
sourceError error
dependency core.Dependency
}
// Report returns the error in string representation
func (e *dependencyValidationError) Error() string {
return fmt.Sprintf("failed to resolve dependency: %v, source error: %s", e.dependency, e.sourceError.Error())
}
// Requeue determines if the current dogu operation should be requeue when this error was responsible for its failure
func (e *dependencyValidationError) Requeue() bool {
return true
}
// doguDependencyValidator is responsible to check if all dogu dependencies are valid for a given dogu
type doguDependencyValidator struct {
fetcher cloudogu.LocalDoguFetcher
}
// NewDoguDependencyValidator creates a new dogu dependencies checker
func NewDoguDependencyValidator(localDoguRegistry registry.DoguRegistry) *doguDependencyValidator {
doguDependencyChecker := cesregistry.NewLocalDoguFetcher(localDoguRegistry)
return &doguDependencyValidator{
fetcher: doguDependencyChecker,
}
}
// ValidateAllDependencies validates mandatory and optional dogu dependencies
func (dc *doguDependencyValidator) ValidateAllDependencies(ctx context.Context, dogu *core.Dogu) error {
var allProblems error
deps := dogu.GetDependenciesOfType(core.DependencyTypeDogu)
err := dc.validateDoguDependencies(ctx, deps, false)
if err != nil {
allProblems = errors.Join(allProblems, err)
}
optionalDeps := dogu.GetOptionalDependenciesOfType(core.DependencyTypeDogu)
err = dc.validateDoguDependencies(ctx, optionalDeps, true)
if err != nil {
allProblems = errors.Join(allProblems, err)
}
return allProblems
}
func (dc *doguDependencyValidator) validateDoguDependencies(ctx context.Context, dependencies []core.Dependency, optional bool) error {
var problems error
for _, doguDependency := range dependencies {
err := dc.checkDoguDependency(ctx, doguDependency, optional)
if err != nil {
dependencyError := dependencyValidationError{
sourceError: err,
dependency: doguDependency,
}
problems = errors.Join(problems, &dependencyError)
}
}
return problems
}
func (dc *doguDependencyValidator) checkDoguDependency(ctx context.Context, doguDependency core.Dependency, optional bool) error {
log.FromContext(ctx).Info(fmt.Sprintf("checking dogu dependency %s:%s", doguDependency.Name, doguDependency.Version))
localDependency, err := dc.fetcher.FetchInstalled(doguDependency.Name)
if err != nil {
if optional && registry.IsKeyNotFoundError(err) {
return nil // not installed => no error as this is ok for optional dependencies
}
return fmt.Errorf("failed to resolve dependencies %s: %w", doguDependency.Name, err)
}
if localDependency == nil {
if optional {
return nil // not installed => no error as this is ok for optional dependencies
}
return fmt.Errorf("dependency %s seems not to be installed", doguDependency.Name)
}
// it does not count as an error if no version is specified as the field is optional
if doguDependency.Version == "" {
return nil
}
localDependencyVersion, err := core.ParseVersion(localDependency.Version)
if err != nil {
return fmt.Errorf("failed to parse version of dependency %s: %w", localDependency.Name, err)
}
comparator, err := core.ParseVersionComparator(doguDependency.Version)
if err != nil {
return fmt.Errorf("failed to parse ParseVersionComparator of version %s for doguDependency %s: %w", doguDependency.Version, doguDependency.Name, err)
}
allows, err := comparator.Allows(localDependencyVersion)
if err != nil {
return fmt.Errorf("an error occurred when comparing the versions: %w", err)
}
if !allows {
return fmt.Errorf("%s parsed Version does not fulfill version requirement of %s dogu %s", localDependency.Version, doguDependency.Version, doguDependency.Name)
}
return nil
}