Skip to content
This repository has been archived by the owner on Mar 26, 2024. It is now read-only.

Support for modifying annotations before and after migrations #19

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions controller-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ check_dioscuri_log () {
}

tear_down () {
echo -e "${GREEN}==>${NOCOLOR} Controller logs"
check_dioscuri_log
echo -e "${GREEN}============= TEAR DOWN =============${NOCOLOR}"
kind delete cluster --name ${KIND_NAME}
}
Expand Down
89 changes: 89 additions & 0 deletions controllers/helpers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package controllers

import (
"encoding/json"

dioscuriv1 "github.com/amazeeio/dioscuri/api/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
)
Expand Down Expand Up @@ -72,3 +74,90 @@ func HostMigrationContainsStatus(slice []dioscuriv1.HostMigrationConditions, s d
}
return false
}

// ProcessAnnotationRules will return new annotations based on a given ruleset and existing annotations
func ProcessAnnotationRules(ruleset string, annotations *map[string]interface{}) (map[string]interface{}, error) {
var rules Rules
if err := json.Unmarshal([]byte(ruleset), &rules); err != nil {
return nil, err
}
newAnnos := *annotations
for _, rule := range rules {
ifOk := 0
for _, rif := range rule.If {
switch rif.Operator {
case "doesnotexist":
dne := true
for key := range *annotations {
if key == rif.Name {
dne = false
}
}
if dne {
ifOk++
}
case "equals":
for key, val := range *annotations {
if rif.Name == key && rif.Value == val {
ifOk++
}
}
}
}
if ifOk == len(rule.If) {
for _, rthen := range rule.Then {
switch rthen.Operator {
case "source":
updateAnnotation(rthen.Name, &newAnnos, getAnnotationValue(rthen.Value, *annotations))
}
}
for _, rthen := range rule.Then {
switch rthen.Operator {
case "equals":
updateAnnotation(rthen.Name, &newAnnos, rthen.Value)
}
}
for _, rthen := range rule.Then {
switch rthen.Operator {
case "delete":
removeAnnotation(rthen.Name, &newAnnos)
}
}
break
}
}
return newAnnos, nil
}

func removeAnnotation(annotation string, annotations *map[string]interface{}) {
// delete(*annotations, annotation)
(*annotations)[annotation] = nil
}

func updateAnnotation(annotation string, annotations *map[string]interface{}, value string) {
(*annotations)[annotation] = value
}

func getAnnotationValue(annotation string, annotations map[string]interface{}) string {
return annotations[annotation].(string)
}

// Rules .
type Rules []struct {
If []RulesIf `json:"if"`
Then []RulesThen `json:"then"`
}

// RulesIf .
type RulesIf struct {
Name string `json:"name"`
Value string `json:"value"`
Operator string `json:"operator"`
}

// RulesThen .
type RulesThen struct {
Name string `json:"name"`
Value string `json:"value"`
Operator string `json:"operator"`
}
93 changes: 93 additions & 0 deletions controllers/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package controllers

import (
"reflect"
"testing"
)

func TestProcessAnnotationRules(t *testing.T) {
var testCases = map[string]struct {
input *map[string]interface{}
rules string
expect map[string]interface{}
}{
"pre-migrate": {
input: &map[string]interface{}{
"fastly.amazee.io/paused": "false",
"fastly.amazee.io/watch": "true",
"other.amazee.io/annotation1": "some-other-data",
"other.amazee.io/annotation2": "more-other-data",
},
rules: `[
{
"if": [
{"name": "fastly.amazee.io/paused", "value": "false", "operator": "equals"},
{"name": "fastly.amazee.io/watch", "value": "true", "operator": "equals"}
],
"then": [
{"name": "fastly.amazee.io/paused", "value": "true", "operator": "equals"},
{"name": "fastly.amazee.io/watch", "value": "false", "operator": "equals"},
{"name": "fastly.amazee.io/delete-external-resources", "value": "false", "operator": "equals"},
{"name": "fastly.amazee.io/backup-paused", "value": "fastly.amazee.io/paused", "operator": "source"},
{"name": "fastly.amazee.io/backup-watch", "value": "fastly.amazee.io/watch", "operator": "source"}
]
}
]`,
expect: map[string]interface{}{
"fastly.amazee.io/paused": "true",
"fastly.amazee.io/watch": "false",
"fastly.amazee.io/backup-paused": "false",
"fastly.amazee.io/backup-watch": "true",
"fastly.amazee.io/delete-external-resources": "false",
"other.amazee.io/annotation1": "some-other-data",
"other.amazee.io/annotation2": "more-other-data",
},
},
"post-migrate": {
input: &map[string]interface{}{
"fastly.amazee.io/paused": "true",
"fastly.amazee.io/watch": "false",
"fastly.amazee.io/backup-paused": "false",
"fastly.amazee.io/backup-watch": "true",
"fastly.amazee.io/delete-external-resources": "false",
},
rules: `[
{
"if": [
{"name": "fastly.amazee.io/paused", "value": "true", "operator": "equals"},
{"name": "fastly.amazee.io/watch", "value": "false", "operator": "equals"}
],
"then": [
{"name": "fastly.amazee.io/delete-external-resources", "operator": "delete"},
{"name": "fastly.amazee.io/backup-delete-external-resources", "operator": "delete"},
{"name": "fastly.amazee.io/backup-paused", "operator": "delete"},
{"name": "fastly.amazee.io/backup-watch", "operator": "delete"},
{"name": "fastly.amazee.io/paused", "value": "fastly.amazee.io/backup-paused", "operator": "source"},
{"name": "fastly.amazee.io/watch", "value": "fastly.amazee.io/backup-watch", "operator": "source"}
]
}
]`,
expect: map[string]interface{}{
"fastly.amazee.io/paused": "false",
"fastly.amazee.io/watch": "true",
"fastly.amazee.io/backup-paused": nil,
"fastly.amazee.io/backup-watch": nil,
"fastly.amazee.io/delete-external-resources": nil,
"fastly.amazee.io/backup-delete-external-resources": nil,
},
},
}
for name, tc := range testCases {
t.Run(name, func(tt *testing.T) {
preAnnos, err := ProcessAnnotationRules(tc.rules, tc.input)
if err != nil {
tt.Fatal(err)
}
// fmt.Println(preAnnos)
// fmt.Println(tc.expect)
if !reflect.DeepEqual(preAnnos, tc.expect) {
tt.Fatalf("Does not equal expected")
}
})
}
}
Loading