-
Notifications
You must be signed in to change notification settings - Fork 0
/
reader.go
137 lines (122 loc) · 3.87 KB
/
reader.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package file
import (
"context"
"fmt"
"github.com/blang/semver/v4"
"github.com/rainest/decklib/pkg/dump"
"github.com/rainest/decklib/pkg/state"
"github.com/rainest/decklib/pkg/utils"
"github.com/kong/go-kong/kong"
)
var (
// ErrorTransformFalseNotSupported indicates that no transform mode is not supported
ErrorTransformFalseNotSupported = fmt.Errorf("_transform: false is not supported")
// ErrorFilenameEmpty indicates that you must provide a filename
ErrorFilenameEmpty = fmt.Errorf("filename cannot be empty")
)
// RenderConfig contains necessary information to render a correct
// KongConfig from a file.
type RenderConfig struct {
CurrentState *state.KongState
KongVersion semver.Version
}
// GetContentFromFiles reads in a file with a slice of filenames and constructs
// a state. If filename is `-`, then it will read from os.Stdin.
// If filename represents a directory, it will traverse the tree
// rooted at filename, read all the files with .yaml, .yml and .json extensions
// and generate a content after a merge of the content from all the files.
//
// It will return an error if the file representation is invalid
// or if there is any error during processing.
func GetContentFromFiles(filenames []string, mockEnvVars bool) (*Content, error) {
if len(filenames) == 0 {
return nil, ErrorFilenameEmpty
}
return getContent(filenames, mockEnvVars)
}
// GetForKonnect processes the fileContent and renders a RawState and KonnectRawState
func GetForKonnect(ctx context.Context, fileContent *Content,
opt RenderConfig, client *kong.Client,
) (*utils.KongRawState, *utils.KonnectRawState, error) {
var builder stateBuilder
// setup
builder.targetContent = fileContent
builder.currentState = opt.CurrentState
builder.kongVersion = opt.KongVersion
builder.client = client
builder.ctx = ctx
builder.disableDynamicDefaults = true
if fileContent.Transform != nil && !*fileContent.Transform {
return nil, nil, ErrorTransformFalseNotSupported
}
kongState, konnectState, err := builder.build()
if err != nil {
return nil, nil, fmt.Errorf("building state: %w", err)
}
return kongState, konnectState, nil
}
// Get process the fileContent and renders a RawState.
// IDs of entities are matches based on currentState.
func Get(ctx context.Context, fileContent *Content, opt RenderConfig, dumpConfig dump.Config, wsClient *kong.Client) (
*utils.KongRawState, error,
) {
var builder stateBuilder
// setup
builder.targetContent = fileContent
builder.currentState = opt.CurrentState
builder.kongVersion = opt.KongVersion
builder.client = wsClient
builder.ctx = ctx
builder.skipCACerts = dumpConfig.SkipCACerts
builder.isKonnect = dumpConfig.KonnectControlPlane != ""
if len(dumpConfig.SelectorTags) > 0 {
builder.selectTags = dumpConfig.SelectorTags
}
if fileContent.Transform != nil && !*fileContent.Transform {
return nil, ErrorTransformFalseNotSupported
}
state, _, err := builder.build()
if err != nil {
return nil, fmt.Errorf("building state: %w", err)
}
return state, nil
}
func ensureJSON(m map[string]interface{}) map[string]interface{} {
res := map[string]interface{}{}
for k, v := range m {
switch v2 := v.(type) {
case map[interface{}]interface{}:
res[fmt.Sprint(k)] = yamlToJSON(v2)
case []interface{}:
var array []interface{}
for _, element := range v2 {
switch el := element.(type) {
case map[interface{}]interface{}:
array = append(array, yamlToJSON(el))
default:
array = append(array, el)
}
}
if array != nil {
res[fmt.Sprint(k)] = array
} else {
res[fmt.Sprint(k)] = v
}
default:
res[fmt.Sprint(k)] = v
}
}
return res
}
func yamlToJSON(m map[interface{}]interface{}) map[string]interface{} {
res := map[string]interface{}{}
for k, v := range m {
switch v2 := v.(type) {
case map[interface{}]interface{}:
res[fmt.Sprint(k)] = yamlToJSON(v2)
default:
res[fmt.Sprint(k)] = v
}
}
return res
}