/
blueprint_mgr.go
98 lines (90 loc) · 3.91 KB
/
blueprint_mgr.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
// Copyright 2020 IBM Corp.
// SPDX-License-Identifier: Apache-2.0
package app
import (
"github.com/rs/zerolog"
fapp "fybrik.io/fybrik/manager/apis/app/v1beta1"
"fybrik.io/fybrik/manager/controllers/utils"
"fybrik.io/fybrik/pkg/logging"
)
// ModuleInstanceSpec consists of the module spec and arguments
type ModuleInstanceSpec struct {
Module fapp.BlueprintModule
ClusterName string
Scope fapp.CapabilityScope
}
// RefineInstances collects all instances of the same read/write module with non "Asset" scope
// and creates a new instance instead, with accumulated arguments.
func (r *PlotterReconciler) RefineInstances(instances []ModuleInstanceSpec) []ModuleInstanceSpec {
newInstances := make([]ModuleInstanceSpec, 0)
// map instances to be unified, according to the cluster and module
instanceMap := make(map[string]ModuleInstanceSpec)
for ind := range instances {
// If the module scope is of type "asset" then avoid trying to unify it with another module.
// Copy module is assumed to be of "asset" scope
if instances[ind].Scope == fapp.Asset {
newInstances = append(newInstances, instances[ind])
continue
}
key := instances[ind].Module.Name + "," + instances[ind].ClusterName
if instance, ok := instanceMap[key]; !ok {
instanceMap[key] = instances[ind]
} else {
instance.Module.Arguments.Assets = append(instance.Module.Arguments.Assets, instances[ind].Module.Arguments.Assets...)
// AssetID is used for step name generation
instance.Module.AssetIDs = append(instance.Module.AssetIDs, instances[ind].Module.AssetIDs...)
instanceMap[key] = instance
}
}
for moduleName := range instanceMap {
newInstances = append(newInstances, instanceMap[moduleName])
}
return newInstances
}
// GenerateBlueprints creates Blueprint specs (one per cluster)
func (r *PlotterReconciler) GenerateBlueprints(instances []ModuleInstanceSpec, plotter *fapp.Plotter) map[string]fapp.BlueprintSpec {
blueprintMap := make(map[string]fapp.BlueprintSpec)
instanceMap := make(map[string][]ModuleInstanceSpec)
uuid := utils.GetFybrikApplicationUUIDfromAnnotations(plotter.GetAnnotations())
for ind := range instances {
instanceMap[instances[ind].ClusterName] = append(instanceMap[instances[ind].ClusterName], instances[ind])
}
for key, instanceList := range instanceMap {
// unite several instances of a read/write module
instances := r.RefineInstances(instanceList)
blueprintMap[key] = r.GenerateBlueprint(instances, key, plotter)
}
log := r.Log.With().Str(utils.FybrikAppUUID, uuid).Logger()
logging.LogStructure("BlueprintMap", blueprintMap, &log, zerolog.DebugLevel, false, false)
return blueprintMap
}
// GenerateBlueprint creates the Blueprint spec based on the datasets and the governance actions required,
// which dictate the modules that must run in the fybrik
// Credentials for accessing data set are stored in a credential management system (such as vault) and
// the paths for accessing them are included in the blueprint.
// The credentials themselves are not included in the blueprint.
func (r *PlotterReconciler) GenerateBlueprint(instances []ModuleInstanceSpec,
clusterName string,
plotter *fapp.Plotter) fapp.BlueprintSpec {
spec := fapp.BlueprintSpec{
Cluster: clusterName,
ModulesNamespace: plotter.Spec.ModulesNamespace,
Modules: map[string]fapp.BlueprintModule{},
Application: &fapp.ApplicationDetails{
WorkloadSelector: plotter.Spec.Selector.WorkloadSelector,
Context: plotter.Spec.AppInfo,
},
}
// Create the map that contains BlueprintModules
for ind := range instances {
modulename := instances[ind].Module.Name
instanceName := modulename
if instances[ind].Scope == fapp.Asset {
// Need unique name for each module
// if the module scope is one per asset then concat the id of the asset to it
instanceName = utils.CreateStepName(modulename, instances[ind].Module.AssetIDs[0])
}
spec.Modules[instanceName] = instances[ind].Module
}
return spec
}