Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(k8s): recursivly find refs and selectors #29

Merged
merged 1 commit into from
Jan 19, 2023
Merged
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
3 changes: 1 addition & 2 deletions tools/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ func GenerateExamplesList(c config.Provider) tea.Msg {
k.ExampleID = strings.ToLower(fmt.Sprintf("%s.%s", k.Kind, k.APIVersion))

// check for selector
k.Selectors = k.FindForProvider("Selector")
k.Refs = k.FindForProvider("Refs")
k.Selectors, k.Refs = k.FindSelectorsAndRefs()
k.DependenciesFiles = map[string]bool{}

// check for extra file examples
Expand Down
96 changes: 73 additions & 23 deletions tui/tui.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package tui

import (
"fmt"
"regexp"
"sort"
"strings"

"github.com/charmbracelet/bubbles/list"
"golang.org/x/exp/maps"
)

var (
reRefs, _ = regexp.Compile(`^\w+Refs$`)
reSelector, _ = regexp.Compile(`^\w+Selector$`)
)

// Example is a struct that holds the details of an example
type Example struct {
FileName string
Expand All @@ -35,7 +39,7 @@ type Example struct {
Name string `yaml:"name"`
} `yaml:"metadata"`
Spec struct {
ForProvider map[interface{}]interface{} `yaml:"forProvider"`
ForProvider map[string]interface{} `yaml:"forProvider"`
} `yaml:"spec"`
}

Expand Down Expand Up @@ -82,37 +86,83 @@ func (e Example) DependenciesFilesList() []string {
return list
}

// FindForProvider returns a map of all the fields containing the pattern
func (e *Example) FindForProvider(pattern string) map[string]bool {
// FindForProvider Recursively search all fields containing $parameter in the ForProvider.Spec

maps := make(map[string]bool)
// FindSelectorsAndRefs returns the selectors and refs of the example
func (e *Example) FindSelectorsAndRefs() (map[string]bool, map[string]bool) {
mapsSelector := make(map[string]bool)
mapsRefs := make(map[string]bool)

for k, v := range e.Spec.ForProvider {
// TODO use regex to find the pattern
if strings.Contains(fmt.Sprintf("%v", k), pattern) {
if reSelector.MatchString(k) {
if _, ok := v.(map[string]interface{}); ok {
m := getSelector(v.(map[string]interface{}))
maps.Copy(mapsSelector, m)
}
} else if reRefs.MatchString(k) {
for _, v2 := range v.([]interface{}) {
m, ok := v2.(map[string]interface{})
if !ok {
continue
}

switch pattern {
case "Selector":
if v.(map[string]interface{})["matchLabels"].(map[string]interface{})["testing.upbound.io/example-name"] != nil {
maps[v.(map[string]interface{})["matchLabels"].(map[string]interface{})["testing.upbound.io/example-name"].(string)] = true
if name, ok := m["name"].(string); ok {
mapsRefs[name] = true
}
case "Refs":
for _, v2 := range v.([]interface{}) {
m, ok := v2.(map[string]interface{})
if !ok {
continue
}
}
} else {
if _, ok := v.([]interface{}); ok {
isArrayInterface(v.([]interface{}), mapsSelector, mapsRefs)
}
}
}

return mapsSelector, mapsRefs
}

if name, ok := m["name"].(string); ok {
maps[name] = true
func isArrayInterface(i []interface{}, mapsSelector map[string]bool, mapsRefs map[string]bool) {
for _, a := range i {
if _, ok := a.(map[string]interface{}); ok {
for k, v := range a.(map[string]interface{}) {
if reSelector.MatchString(k) {
if _, ok := v.(map[string]interface{}); ok {
m := getSelector(v.(map[string]interface{}))
maps.Copy(mapsSelector, m)
}
} else if reRefs.MatchString(k) {
for _, v2 := range v.([]interface{}) {
m, ok := v2.(map[string]interface{})
if !ok {
continue
}

if name, ok := m["name"].(string); ok {
mapsRefs[name] = true
}
}
} else {
if _, ok := v.([]interface{}); ok {
isArrayInterface(v.([]interface{}), mapsSelector, mapsRefs)
}
}
}
}
}
}

func getSelector(v map[string]interface{}) map[string]bool {
m := make(map[string]bool)
if _, ok := v["matchLabels"].(map[string]interface{}); !ok {
return nil
}
matchLabels := v["matchLabels"].(map[string]interface{})
exampleName := matchLabels["testing.upbound.io/example-name"]
if exampleName != nil {
if _, ok := exampleName.(string); ok {
m[exampleName.(string)] = true
} else {
return nil
}
}
return maps
return m
}

// FindDependencies Find Selector and Ref in all files examples
Expand Down