Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set operator name of 'KudoOperator' tasks for dependencies #1560

Merged
merged 7 commits into from
Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 28 additions & 18 deletions pkg/kudoctl/packages/install/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,35 @@ func (g *dependencyGraph) Visit(v int, do func(w int, c int64) bool) bool {
return false
}

type Dependency struct {
packages.Resources

PackageName string
}

// gatherDependencies resolved all dependencies of a package.
// Dependencies are resolved recursively.
// Cyclic dependencies are detected and result in an error.
func gatherDependencies(root packages.Resources, resolver pkgresolver.Resolver) ([]packages.Resources, error) {
pkgs := []packages.Resources{
root,
func gatherDependencies(root packages.Resources, resolver pkgresolver.Resolver) ([]Dependency, error) {
dependencies := []Dependency{
{Resources: root},
}

// Each vertex in 'g' matches an index in 'pkgs'.
// Each vertex in 'g' matches an index in 'dependencies'.
g := dependencyGraph{
edges: []map[int]struct{}{{}},
}

if err := dependencyWalk(&pkgs, &g, root, 0, resolver); err != nil {
if err := dependencyWalk(&dependencies, &g, root, 0, resolver); err != nil {
return nil, err
}

// Remove 'root' from the list of dependencies.
pkgs = funk.Drop(pkgs, 1).([]packages.Resources) //nolint:errcheck

return pkgs, nil
return dependencies[1:], nil
}

func dependencyWalk(
pkgs *[]packages.Resources,
dependencies *[]Dependency,
g *dependencyGraph,
parent packages.Resources,
parentIndex int,
Expand All @@ -87,14 +91,19 @@ func dependencyWalk(
"failed to resolve package %s, dependency of package %s: %v", fullyQualifiedName(childTask.Spec.KudoOperatorTaskSpec), parent.OperatorVersion.FullyQualifiedName(), err)
}

childDependency := Dependency{
Resources: *childPkg.Resources,
PackageName: childTask.Spec.KudoOperatorTaskSpec.Package,
}

newPackage := false
childIndex := indexOf(pkgs, childPkg.Resources)
childIndex := indexOf(dependencies, &childDependency)
if childIndex == -1 {
clog.Printf("Adding new dependency %s", childPkg.Resources.OperatorVersion.FullyQualifiedName())
newPackage = true

*pkgs = append(*pkgs, *childPkg.Resources)
childIndex = len(*pkgs) - 1
*dependencies = append(*dependencies, childDependency)
childIndex = len(*dependencies) - 1

// The number of vertices in 'g' has to match the number of packages we're tracking.
g.AddVertex()
Expand All @@ -110,7 +119,7 @@ func dependencyWalk(

// We only need to walk the dependencies if the package is new
if newPackage {
if err := dependencyWalk(pkgs, g, *childPkg.Resources, childIndex, resolver); err != nil {
if err := dependencyWalk(dependencies, g, *childPkg.Resources, childIndex, resolver); err != nil {
return err
}
}
Expand All @@ -119,11 +128,12 @@ func dependencyWalk(
return nil
}

// indexOf method searches for the pkg in pkgs that has the same OperatorVersion/AppVersion (using
// EqualOperatorVersion method) and returns its index or -1 if not found.
func indexOf(pkgs *[]packages.Resources, pkg *packages.Resources) int {
for i, p := range *pkgs {
if p.OperatorVersion.EqualOperatorVersion(pkg.OperatorVersion) {
// indexOf method searches for the dependency in dependencies that has the same
// OperatorVersion/AppVersion (using EqualOperatorVersion method) and returns
// its index or -1 if not found.
func indexOf(dependencies *[]Dependency, dependency *Dependency) int {
for i, p := range *dependencies {
nfnt marked this conversation as resolved.
Show resolved Hide resolved
if p.OperatorVersion.EqualOperatorVersion(dependency.OperatorVersion) {
return i
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/kudoctl/packages/install/dependencies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ func TestGatherDependencies(t *testing.T) {
for _, operatorName := range tt.want {
operatorName := operatorName

assert.NotNil(t, funk.Find(got, func(p packages.Resources) bool {
return p.Operator.Name == operatorName
assert.NotNil(t, funk.Find(got, func(dep Dependency) bool {
return dep.Operator.Name == operatorName
}), tt.name)
}
})
Expand Down
26 changes: 25 additions & 1 deletion pkg/kudoctl/packages/install/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/kudobuilder/kudo/pkg/apis/kudo/v1beta1"
engtask "github.com/kudobuilder/kudo/pkg/engine/task"
"github.com/kudobuilder/kudo/pkg/kudoctl/clog"
"github.com/kudobuilder/kudo/pkg/kudoctl/packages"
"github.com/kudobuilder/kudo/pkg/kudoctl/packages/resolver"
Expand Down Expand Up @@ -64,11 +65,15 @@ func Package(
return err
}

updateOperatorTasks(dependencies, resources.OperatorVersion)
nfnt marked this conversation as resolved.
Show resolved Hide resolved

for _, dependency := range dependencies {
dependency.Operator.SetNamespace(namespace)
dependency.OperatorVersion.SetNamespace(namespace)

if err := installOperatorAndOperatorVersion(client, dependency); err != nil {
updateOperatorTasks(dependencies, dependency.OperatorVersion)

if err := installOperatorAndOperatorVersion(client, dependency.Resources); err != nil {
return err
}
}
Expand Down Expand Up @@ -139,3 +144,22 @@ func validateParameters(instance v1beta1.Instance, parameters []v1beta1.Paramete

return nil
}

func updateOperatorTasks(pkgs []Dependency, operatorVersion *v1beta1.OperatorVersion) {
nfnt marked this conversation as resolved.
Show resolved Hide resolved
tasks := operatorVersion.Spec.Tasks

for i := range tasks {
if tasks[i].Kind == engtask.KudoOperatorTaskKind {
for _, pkg := range pkgs {
if tasks[i].Spec.KudoOperatorTaskSpec.Package == pkg.PackageName {
// TODO: remove 'OperatorName' once the controller uses 'Package'
tasks[i].Spec.KudoOperatorTaskSpec.Package = pkg.Operator.Name
tasks[i].Spec.KudoOperatorTaskSpec.OperatorName = pkg.Operator.Name
break
}
}
}
}

operatorVersion.Spec.Tasks = tasks
}
12 changes: 12 additions & 0 deletions test/integration/operator-with-dependencies/01-assert.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
apiVersion: kudo.dev/v1beta1
kind: OperatorVersion
metadata:
name: parent-0.1.0
spec:
tasks:
- name: deploy-child
kind: KudoOperator
spec:
package: child
operatorName: child
---
apiVersion: kudo.dev/v1beta1
kind: Instance
metadata:
name: dummy-instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ tasks:
kind: KudoOperator
spec:
package: "./child-operator"
operatorName: child
operatorVersion: 0.0.1

plans:
Expand Down