Skip to content

Commit ff40deb

Browse files
authored
Merge pull request #336 from merico-dev/feat-outputs-rework
feat: outputs rework with unit tests and functional tests
2 parents e13e2fa + 487041a commit ff40deb

File tree

12 files changed

+317
-354
lines changed

12 files changed

+317
-354
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ require (
129129
github.com/modern-go/reflect2 v1.0.2 // indirect
130130
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
131131
github.com/morikuni/aec v1.0.0 // indirect
132-
github.com/onsi/ginkgo v1.16.5 // indirect
133132
github.com/opencontainers/go-digest v1.0.0 // indirect
134133
github.com/opencontainers/image-spec v1.0.1 // indirect
135134
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect

go.sum

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -965,9 +965,8 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
965965
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
966966
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
967967
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
968+
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
968969
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
969-
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
970-
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
971970
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
972971
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
973972
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=

internal/pkg/pluginengine/change.go

Lines changed: 11 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,14 @@
11
package pluginengine
22

33
import (
4-
"errors"
54
"fmt"
6-
"strings"
75
"time"
86

97
"github.com/merico-dev/stream/internal/pkg/configloader"
108
"github.com/merico-dev/stream/internal/pkg/statemanager"
119
"github.com/merico-dev/stream/pkg/util/log"
1210
)
1311

14-
const REF_PREFIX = "${{"
15-
const REF_SUFFIX = "}}"
16-
17-
// eg. ${{name.kind.outputs.key}},name setgment number is 0
18-
const NAME_SEGMENT_NUM = 0
19-
20-
// eg. ${{name.kind.outputs.key}},kind setgment number is 1
21-
const KIND_SEGMENT_NUM = 1
22-
23-
// eg. ${{name.kind.outputs.key}},key setgment number is 3
24-
const REF_SEGMENT_NUM = 3
25-
2612
// Change is a wrapper with a single Tool and its Action should be execute.
2713
type Change struct {
2814
Tool *configloader.Tool
@@ -111,12 +97,19 @@ func execute(smgr statemanager.Manager, changes []*Change) map[string]error {
11197
var returnValue map[string]interface{}
11298

11399
log.Debugf("Tool's raw changes are: %s.", c.Tool.Options)
114-
// fill ref inputs
115-
err = fillRefValueWithOutputs(smgr, c.Tool.Options)
116-
if err != nil {
100+
101+
errs := HandleOutputsReferences(smgr, c.Tool.Options)
102+
if len(errs) != 0 {
117103
succeeded = false
104+
105+
for _, e := range errs {
106+
log.Errorf("Error: %s.", e)
107+
}
108+
log.Errorf("The outputs reference in tool %s (%s) can't be resolved. Please double check your config.", c.Tool.Name, c.Tool.Plugin.Kind)
109+
110+
// not executing this change since its input isn't valid
111+
continue
118112
}
119-
log.Debugf("Tool's changes with filled inputs: %s.", c.Tool.Options)
120113

121114
switch c.ActionName {
122115
case statemanager.ActionCreate:
@@ -192,56 +185,3 @@ func handleResult(smgr statemanager.Manager, change *Change) error {
192185
log.Successf("Plugin %s(%s) %s done.", change.Tool.Name, change.Tool.Plugin.Kind, change.ActionName)
193186
return nil
194187
}
195-
196-
// fillRefValueWithOutputs fill inputs from state
197-
func fillRefValueWithOutputs(smgr statemanager.Manager, options map[string]interface{}) error {
198-
for key, value := range options {
199-
log.Debugf("Key: %s, Value: %s.", key, value)
200-
// judge whether the value is a string
201-
if inst, ok := value.(string); ok {
202-
// judge whether the format is ${{xxx}}
203-
if isValidRefFormat(inst) {
204-
ref := getRefFormatString(inst)
205-
log.Debug("Ref inputs: ", ref)
206-
refParam := strings.Split(ref, ".")
207-
if len(refParam) <= 3 {
208-
return errors.New("incorrect output reference: " + ref)
209-
}
210-
211-
outputs, err := smgr.GetOutputs(statemanager.GenStateKey(refParam[NAME_SEGMENT_NUM], refParam[KIND_SEGMENT_NUM]))
212-
if err != nil {
213-
return err
214-
}
215-
log.Debug("Ref outputs: ", outputs)
216-
217-
if outs, ok := outputs.(map[string]interface{}); ok {
218-
log.Debug("Ref outs: ", outs)
219-
log.Debug("Ref param: ", refParam[REF_SEGMENT_NUM])
220-
if value == nil {
221-
return errors.New("ref input value is null: " + refParam[REF_SEGMENT_NUM])
222-
}
223-
if options[key], ok = outs[refParam[REF_SEGMENT_NUM]]; !ok {
224-
return fmt.Errorf("can not find %s in dependency outputs", refParam[REF_SEGMENT_NUM])
225-
}
226-
}
227-
}
228-
}
229-
// judge wheter the format is map[string]interface{}, if true, then recursion
230-
if _, ok := value.(map[string]interface{}); ok {
231-
if err := fillRefValueWithOutputs(smgr, value.(map[string]interface{})); err != nil {
232-
return err
233-
}
234-
}
235-
}
236-
return nil
237-
}
238-
239-
// isValidRefFormat if the format is ${{abc}}
240-
func isValidRefFormat(ref string) bool {
241-
return strings.HasPrefix(ref, REF_PREFIX) && strings.HasSuffix(ref, REF_SUFFIX)
242-
}
243-
244-
// getRefFormatString get abc from ${{abc}} or ${{ abc }}
245-
func getRefFormatString(rawFormatString string) string {
246-
return strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(rawFormatString, REF_PREFIX), REF_SUFFIX))
247-
}

internal/pkg/pluginengine/change_helper.go

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,12 @@ func changesForApply(smgr statemanager.Manager, cfg *configloader.Config) ([]*Ch
8282
description := fmt.Sprintf("Tool %s (%s) found in config but doesn't exist in the state, will be created.", tool.Name, tool.Plugin.Kind)
8383
changes = append(changes, generateCreateAction(&tool, description))
8484
} else {
85-
if err := renderRefByDependency(&tool, cfg.Tools, smgr); err != nil {
86-
return nil, err
87-
}
8885
// tool found in the state
86+
87+
// first, handle possible "outputs" referneces in the tool's config
88+
// ignoring errors, since at this stage we are calculating changes, and the dependency might not have its output in the state yet
89+
_ = HandleOutputsReferences(smgr, tool.Options)
90+
8991
if drifted(tool.Options, state.Options) {
9092
// tool's config differs from State's, Update
9193
description := fmt.Sprintf("Tool %s (%s) config drifted from the state, will be updated.", tool.Name, tool.Plugin.Kind)
@@ -169,33 +171,3 @@ func changesForForceDelete(smgr statemanager.Manager, cfg *configloader.Config)
169171
}
170172
return changes
171173
}
172-
173-
// renderRefByDependency
174-
// 1. if dependency plugin changed, do not fill ${{***}} with ref value;
175-
// 2. if dependency plugin did not change, fill ${{***}} with ref value;
176-
func renderRefByDependency(tool *configloader.Tool, tools []configloader.Tool, smgr statemanager.Manager) error {
177-
if len(tool.DependsOn) > 0 {
178-
for _, dependency := range tool.DependsOn {
179-
dependencyChange := false
180-
for _, c := range tools {
181-
log.Debugf("====== Name: %s kind: %s dependency: %s =====", c.Name, c.Plugin.Kind, dependency)
182-
if fmt.Sprintf("%s%s%s", c.Name, ".", c.Plugin.Kind) == dependency {
183-
state := smgr.GetState(statemanager.StateKeyGenerateFunc(&c))
184-
if drifted(c.Options, state.Options) {
185-
dependencyChange = true
186-
}
187-
}
188-
}
189-
if !dependencyChange {
190-
// fill ref inputs,
191-
if err := fillRefValueWithOutputs(smgr, tool.Options); err != nil {
192-
return err
193-
}
194-
log.Infof("Dependency plugin no changes, ref inputs will be filled: %s.", tool.Options)
195-
} else {
196-
log.Infof("Do not fill ref inputs now, they will be filled when dependency plugin complete: %s.", tool.Options)
197-
}
198-
}
199-
}
200-
return nil
201-
}

internal/pkg/pluginengine/fillRefValueWithOutputs_test.go

Lines changed: 0 additions & 158 deletions
This file was deleted.

0 commit comments

Comments
 (0)