/
create.go
120 lines (101 loc) · 3.88 KB
/
create.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
package component
import (
"fmt"
"runtime/debug"
"time"
"github.com/Aptomi/aptomi/pkg/engine/apply/action"
"github.com/Aptomi/aptomi/pkg/engine/resolve"
"github.com/Aptomi/aptomi/pkg/lang"
"github.com/Aptomi/aptomi/pkg/plugin"
"github.com/Aptomi/aptomi/pkg/runtime"
"github.com/Aptomi/aptomi/pkg/util"
)
// CreateActionObject is an informational data structure with Kind and Constructor for the action
var CreateActionObject = &runtime.Info{
Kind: "action-component-create",
Constructor: func() runtime.Object { return &CreateAction{} },
}
// CreateAction is a action which gets called when a new component needs to be instantiated (i.e. new instance of code to be deployed to the cloud)
type CreateAction struct {
runtime.TypeKind `yaml:",inline"`
*action.Metadata
ComponentKey string
Params util.NestedParameterMap
}
// NewCreateAction creates new CreateAction
func NewCreateAction(componentKey string, params util.NestedParameterMap) *CreateAction {
return &CreateAction{
TypeKind: CreateActionObject.GetTypeKind(),
Metadata: action.NewMetadata(CreateActionObject.Kind, componentKey),
ComponentKey: componentKey,
Params: params,
}
}
// Apply applies the action
func (a *CreateAction) Apply(context *action.Context) (errResult error) {
start := time.Now()
defer func() {
if err := recover(); err != nil {
errResult = fmt.Errorf("panic: %s\n%s", err, string(debug.Stack()))
}
action.CollectMetricsFor(a, start, errResult)
}()
context.EventLog.NewEntry().Debugf("Creating component instance: %s", a.ComponentKey)
// deploy to cloud
instance, err := a.processDeployment(context)
if err != nil {
return fmt.Errorf("unable to deploy component instance '%s': %s", a.ComponentKey, err)
}
// update actual state
return context.ActualStateUpdater.CreateComponentInstance(instance)
}
// DescribeChanges returns text-based description of changes that will be applied
func (a *CreateAction) DescribeChanges() util.NestedParameterMap {
return util.NestedParameterMap{
"kind": a.Kind,
"key": a.ComponentKey,
"params": a.Params,
"pretty": fmt.Sprintf("[+] %s", a.ComponentKey),
}
}
func (a *CreateAction) processDeployment(context *action.Context) (*resolve.ComponentInstance, error) {
instance := context.DesiredState.ComponentInstanceMap[a.ComponentKey]
if instance == nil {
panic(fmt.Sprintf("component instance not found in desired state: %s", a.ComponentKey))
}
bundleObj, err := context.DesiredPolicy.GetObject(lang.BundleObject.Kind, instance.Metadata.Key.BundleName, instance.Metadata.Key.Namespace)
if err != nil {
return nil, err
}
component := bundleObj.(*lang.Bundle).GetComponentsMap()[instance.Metadata.Key.ComponentName] // nolint: errcheck
if component == nil {
// If this is a bundle instance, do nothing and proceed to object creation
return instance, nil
}
if component.Code == nil {
// If this is not a code component, do nothing and proceed to object creation
return instance, nil
}
// Instantiate code component
context.EventLog.NewEntry().Infof("Deploying new component instance: %s", instance.GetKey())
clusterObj, err := context.DesiredPolicy.GetObject(lang.ClusterObject.Kind, instance.Metadata.Key.ClusterName, instance.Metadata.Key.ClusterNameSpace)
if err != nil {
return nil, err
}
if clusterObj == nil {
return nil, fmt.Errorf("cluster '%s/%s' in not present in policy", instance.Metadata.Key.ClusterNameSpace, instance.Metadata.Key.ClusterName)
}
cluster := clusterObj.(*lang.Cluster) // nolint: errcheck
p, err := context.Plugins.ForCodeType(cluster, component.Code.Type)
if err != nil {
return nil, err
}
return instance, p.Create(
&plugin.CodePluginInvocationParams{
DeployName: instance.GetDeployName(),
Params: instance.CalculatedCodeParams,
PluginParams: map[string]string{plugin.ParamTargetSuffix: instance.Metadata.Key.TargetSuffix},
EventLog: context.EventLog,
},
)
}