Skip to content

Commit

Permalink
feat: initial version of ReplaceReferences
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasjarosch committed Mar 5, 2024
1 parent 8dd7093 commit f27692a
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
64 changes: 64 additions & 0 deletions reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package skipper

import (
"fmt"
"strings"

"github.com/dominikbraun/graph"

Expand Down Expand Up @@ -66,6 +67,7 @@ func NewValueReferenceManager(source ValueReferenceSource) (*ValueReferenceManag
return nil, err
}
}

manager.allReferences = references

// deduplicate references in map
Expand All @@ -84,6 +86,68 @@ func NewValueReferenceManager(source ValueReferenceSource) (*ValueReferenceManag
return manager, nil
}

func (manager *ValueReferenceManager) getAllReferencesWithHash(hash string) []reference.ValueReference {
var result []reference.ValueReference
for _, ref := range manager.AllReferences() {
if ref.Hash() == hash {
result = append(result, ref)
}
}
return result
}

// ReplaceReferences will replace all - currently known - references
// within the source of the manager.
// If any references are added/removed after this call, this
// method needs to be called again.
func (manager *ValueReferenceManager) ReplaceReferences() error {
uniqueReplacementOrder, err := reference.ValueReplacementOrder(manager.dependencyGraph)
if err != nil {
return err
}

// The replacementOrder is derived from the hash-map, hence it does
// not know about duplicate references.
// Calculate the actual replacement order including the duplicates.
var replacementOrder []reference.ValueReference
for _, orderedRef := range uniqueReplacementOrder {
replacementOrder = append(replacementOrder, manager.getAllReferencesWithHash(orderedRef.Hash())...)
}

for _, ref := range replacementOrder {

targetValue, err := manager.source.GetPath(ref.AbsoluteTargetPath)
if err != nil {
return err
}

sourceValue, err := manager.source.GetPath(ref.Path)
if err != nil {
return err
}

// If the sourceValue is the full reference name,
// we can just replace the value with the targetValue completely.
if strings.EqualFold(sourceValue.String(), ref.Name()) {
err = manager.source.SetPath(ref.Path, targetValue.Raw)
if err != nil {
return err
}
continue
}

// Otherwise, we need to do a string substitution.
replacedValue := strings.Replace(sourceValue.String(), ref.Name(), targetValue.String(), 1)
err = manager.source.SetPath(ref.Path, replacedValue)
if err != nil {
return err
}

}

return nil
}

// registerHooks is responsible for registering all possible hooks which
// this manager provides.
// It will always register the 'preSetHook' and 'postSetHook' functions
Expand Down
32 changes: 32 additions & 0 deletions reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package skipper_test
import (
"testing"

"github.com/davecgh/go-spew/spew"
"github.com/stretchr/testify/assert"

. "github.com/lukasjarosch/skipper"
Expand Down Expand Up @@ -72,3 +73,34 @@ func TestValueManager_SetHooks(t *testing.T) {
assert.ErrorIs(t, err, ErrInvalidReferenceTargetPath)
})
}

func TestValueManager_ReplaceReferences(t *testing.T) {
filePath := "testdata/references/class/valid.yaml"
class, err := NewClass(filePath, codec.NewYamlCodec(), data.NewPath("valid"))
assert.NoError(t, err)
assert.NotNil(t, class)

manager, err := NewValueReferenceManager(class)
assert.NoError(t, err)
assert.NotNil(t, manager)

t.Run("valid class without modifications", func(t *testing.T) {
err := manager.ReplaceReferences()
assert.NoError(t, err)

expected := map[string]data.Value{
"valid.person.age": data.NewValue(35),
"valid.greetings.casual": data.NewValue("Hey John"),
"valid.greetings.formal": data.NewValue("Welcome, John Doe"),
"valid.greetings.age": data.NewValue("You are 35 years old"),
}

for path, expectedValue := range expected {
val, err := class.Get(path)
assert.NoError(t, err)
assert.Equal(t, expectedValue, val)
}

spew.Dump(class.GetAll())
})
}

0 comments on commit f27692a

Please sign in to comment.