Skip to content

Commit 2d93f83

Browse files
authored
Replace string replace w lexer (#12)
* fix: add strings.Replace * fix: remove unused methods * fix: pkg generator layout changes (still work to do there...) updated tests
1 parent c87523a commit 2d93f83

File tree

17 files changed

+376
-165
lines changed

17 files changed

+376
-165
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
OWNER := dnitsch
33
NAME := configmanager
4-
GIT_TAG := "1.17.3"
4+
GIT_TAG := "1.18.0"
55
VERSION := "v$(GIT_TAG)"
66
# VERSION := "$(shell git describe --tags --abbrev=0)"
77
REVISION := $(shell git rev-parse --short HEAD)
@@ -57,5 +57,5 @@ echo:
5757

5858
tagbuildrelease: tag cross-build release
5959

60-
coverage_interactive: test
60+
show_coverage: test
6161
go tool cover -html=.coverage/out

configmanager.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,34 @@ func retrieveWithInputReplaced(input string, gv GenerateAPI) (string, error) {
5858

5959
// replaceString fills tokens in a provided input with their actual secret/config values
6060
func replaceString(inputMap generator.ParsedMap, inputString string) string {
61+
62+
oldNew := []string(nil)
63+
// ordered values by index
64+
for _, ov := range orderedKeysList(inputMap) {
65+
oldNew = append(oldNew, ov, fmt.Sprint(inputMap[ov]))
66+
}
67+
replacer := strings.NewReplacer(oldNew...)
68+
return replacer.Replace(inputString)
69+
}
70+
71+
func orderedKeysList(inputMap generator.ParsedMap) []string {
6172
mkeys := make([]string, 0, len(inputMap))
6273
for k := range inputMap {
6374
mkeys = append(mkeys, k)
6475
}
6576

66-
// order map by keys length
67-
sort.Slice(mkeys, func(i, j int) bool {
77+
// order map by keys length so that when passed to the
78+
// replacer it will replace the longest first
79+
// removing the possibility of partially overwriting
80+
// another token with same prefix
81+
sort.SliceStable(mkeys, func(i, j int) bool {
6882
l1, l2 := len(mkeys[i]), len(mkeys[j])
6983
if l1 != l2 {
7084
return l1 > l2
7185
}
7286
return mkeys[i] > mkeys[j]
7387
})
74-
75-
// ordered values by index
76-
for _, oval := range mkeys {
77-
inputString = strings.ReplaceAll(inputString, oval, fmt.Sprint(inputMap[oval]))
78-
}
79-
return inputString
88+
return mkeys
8089
}
8190

8291
type CMRetrieveWithInputReplacediface interface {
@@ -172,8 +181,3 @@ func RetrieveUnmarshalledFromYaml[T any](input []byte, output *T, cm CMRetrieveW
172181
}
173182
return output, nil
174183
}
175-
176-
// Insert will update
177-
func (c *ConfigManager) Insert(force bool) error {
178-
return fmt.Errorf("not yet implemented")
179-
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/aws/aws-sdk-go-v2/config v1.18.8
1010
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.18.1
1111
github.com/aws/aws-sdk-go-v2/service/ssm v1.35.0
12+
github.com/go-test/deep v1.0.2
1213
github.com/rs/zerolog v1.28.0
1314
github.com/spf13/cobra v1.6.1
1415
)

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
9696
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
9797
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
9898
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
99+
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
99100
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
100101
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
101102
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=

internal/cmdutils/cmdutils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (c *CmdUtils) generateFromStrOutOverwrite(input, outtemp string, outtmp io.
126126
}
127127

128128
// move temp file to output path
129-
return os.WriteFile(c.generator.ConfigOutputPath(), tr, 0644)
129+
return os.WriteFile(c.generator.Config().OutputPath(), tr, 0644)
130130
}
131131

132132
// generateStrOutFromInput takes a reader and writer as input

internal/cmdutils/cmdutils_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ func Test_generateFromStrOutOverwrite(t *testing.T) {
116116
},
117117
genMock: func(t *testing.T, out string) generator.GenVarsiface {
118118
gen := &mockGenVars{}
119-
gen.confOutputPath = out
120-
gen.config = generator.NewConfig()
121-
119+
gen.config = generator.NewConfig().WithOutputPath(out)
122120
return gen
123121
},
124122
in: "pass=FOO#/test",

pkg/generator/config.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package generator
2+
3+
// GenVarsConfig defines the input config object to be passed
4+
type GenVarsConfig struct {
5+
outpath string
6+
tokenSeparator string
7+
keySeparator string
8+
}
9+
10+
// NewConfig
11+
func NewConfig() *GenVarsConfig {
12+
return &GenVarsConfig{
13+
tokenSeparator: tokenSeparator,
14+
keySeparator: keySeparator,
15+
}
16+
}
17+
18+
// WithOutputPath
19+
func (c *GenVarsConfig) WithOutputPath(out string) *GenVarsConfig {
20+
c.outpath = out
21+
return c
22+
}
23+
24+
// WithTokenSeparator adds a custom token separator
25+
// token is the actual value of the parameter/secret in the
26+
// provider store
27+
func (c *GenVarsConfig) WithTokenSeparator(tokenSeparator string) *GenVarsConfig {
28+
c.tokenSeparator = tokenSeparator
29+
return c
30+
}
31+
32+
// WithKeySeparator adds a custom key separotor
33+
func (c *GenVarsConfig) WithKeySeparator(keySeparator string) *GenVarsConfig {
34+
c.keySeparator = keySeparator
35+
return c
36+
}
37+
38+
// OutputPath returns the outpath set in the config
39+
func (c *GenVarsConfig) OutputPath() string {
40+
return c.outpath
41+
}
42+
43+
// TokenSeparator returns the tokenSeparator set in the config
44+
func (c *GenVarsConfig) TokenSeparator() string {
45+
return c.tokenSeparator
46+
}
47+
48+
// KeySeparator returns the keySeparator set in the config
49+
func (c *GenVarsConfig) KeySeparator() string {
50+
return c.keySeparator
51+
}

pkg/generator/gcpsecrets.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ func (imp *GcpSecrets) setToken(token string) {
4040
imp.token = token
4141
}
4242

43-
func (imp *GcpSecrets) setValue(val string) {
44-
}
45-
4643
func (imp *GcpSecrets) getTokenValue(v *retrieveStrategy) (string, error) {
4744
defer imp.close()
4845

pkg/generator/gcpsecrets_test.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,27 @@ func (m mockGcpSecretsApi) AccessSecretVersion(ctx context.Context, req *gcpsecr
1818
return m(ctx, req, opts...)
1919
}
2020

21+
var TEST_GCP_CREDS = []byte(`{
22+
"type": "service_account",
23+
"project_id": "xxxxx",
24+
"private_key_id": "yyyyyyyyyyyy",
25+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDf842hcn5Nvp6e\n7yKARaCVIDfLXpKDhRwUOvHMzJ1ioRgQo/kbv1n4yHGCSUFyY6hKGj0HBjaGj5kE\n79H/6Y3dJNGhnsMnxBhHdo+3FI8QF0CHZh460NMZSAJ41UMQSBGssGVsNfyUzXGH\nLc45sIx/Twx3yr1k2GD3E8FlDcKlZqa3xGHf+aipg2X3NxbYi+Sz7Yed+SOMhNHl\ncX6E/TqG9n1aTyIwjMIHscCYarJqURkJxr24ukDroCeMxAfxYTdMvRU2e8pFEdoY\nrgUC88fYfaVI5txJ6j/ZKauKQX9Pa8tSyXJeGva3JYp4VC7V4IyoVviCUgEGWZDN\n6/i3zoF/AgMBAAECggEAcVBCcVYFIkE48SH+Svjv74SFtpj7eSB4vKO2hPFjEOyB\nyKmu+aMwWvjQtiNqwf46wIPWLR+vpxYxTpYpo1sBNMvUZfp2tEA8KKyMuw3j9ThO\npjO9R/UxWrFcztbZP/u3NbFrH/2Q95mbv9IlbnsuG5xbqqEig0wYg+uzBvaXbig3\n/Jr0vLT2BkRCBKQkYGjVZcHlHVLoF7/J8cghFgkV1PGvknOv6/q7qzn9L4TjQIet\nfhrhN8Z1vgFiSYtpjP6YQEUEPSHmCQeD3WzJcnASPpU2uCUwd/z65ltKPnn+rqMt\n6jt9R1S1Ju2ZSjv+kR5fIXzihdOzncyzDDm33c/QwQKBgQD2QDZuzLjTxnhsfGii\nKJDAts+Jqfs/6SeEJcJKtEngj4m7rgzyEjbKVp8qtRHIzglKRWAe62/qzzy2BkKi\nvAd4+ZzmG2SkgypGsKVfjGXVFixz2gtUdmBOmK/TnYsxNT9yTt+rX9IGqKK60q73\nOWl8VsliLIsfvSH7+bqi7sRcXQKBgQDo0VUebyQHoTAXPdzGy2ysrVPDiHcldH0Y\n/hvhQTZwxYaJr3HpOCGol2Xl6zyawuudEQsoQwJ3Li6yeb0YMGiWX77/t+qX3pSn\nkGuoftGaNDV7sLn9UV2y+InF8EL1CasrhG1k5RIuxyfV0w+QUo+E7LpVR5XkbJqT\n9QNKnDQXiwKBgQDvvEYCCqbp7e/xVhEbxbhfFdro4Cat6tRAz+3egrTlvXhO0jzi\nMp9Kz5f3oP5ma0gaGX5hu75icE1fvKqE+d+ghAqe7w5FJzkyRulJI0tEb2jphN7A\n5NoPypBqyZboWjmhlG4mzouPVf/POCuEnk028truDAWJ6by7Lj3oP+HFNQKBgQCc\n5BQ8QiFBkvnZb7LLtGIzq0n7RockEnAK25LmJRAOxs13E2fsBguIlR3x5qgckqY8\nXjPqmd2bet+1HhyzpEuWqkcIBGRum2wJz2T9UxjklbJE/D8Z2i8OYDZX0SUOA8n5\ntXASwduS8lqB2Y1vcHOO3AhlV6xHFnjEpCPnr4PbKQKBgAhQ9D9MPeuz+5yw3yHg\nkvULZRtud+uuaKrOayprN25RTxr9c0erxqnvM7KHeo6/urOXeEa7x2n21kAT0Nch\nkF2RtWBLZKXGZEVBtw1Fw0UKNh4IDgM26dwlzRfTVHCiw6M6dCiTNk9KkP2vlkim\n3QFDSSUp+eBTXA17WkDAQf7w\n-----END PRIVATE KEY-----\n",
26+
"client_email": "[email protected]",
27+
"client_id": "99999911111111",
28+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
29+
"token_uri": "https://oauth2.googleapis.com/token",
30+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
31+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/bla"
32+
}`)
33+
2134
func fixtureInitMockClient() struct {
2235
name string
2336
close func() error
2437
delete func(name string) error
2538
} {
26-
creds := []byte(`{
27-
"type": "service_account",
28-
"project_id": "xxxxx",
29-
"private_key_id": "yyyyyyyyyyyy",
30-
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDf842hcn5Nvp6e\n7yKARaCVIDfLXpKDhRwUOvHMzJ1ioRgQo/kbv1n4yHGCSUFyY6hKGj0HBjaGj5kE\n79H/6Y3dJNGhnsMnxBhHdo+3FI8QF0CHZh460NMZSAJ41UMQSBGssGVsNfyUzXGH\nLc45sIx/Twx3yr1k2GD3E8FlDcKlZqa3xGHf+aipg2X3NxbYi+Sz7Yed+SOMhNHl\ncX6E/TqG9n1aTyIwjMIHscCYarJqURkJxr24ukDroCeMxAfxYTdMvRU2e8pFEdoY\nrgUC88fYfaVI5txJ6j/ZKauKQX9Pa8tSyXJeGva3JYp4VC7V4IyoVviCUgEGWZDN\n6/i3zoF/AgMBAAECggEAcVBCcVYFIkE48SH+Svjv74SFtpj7eSB4vKO2hPFjEOyB\nyKmu+aMwWvjQtiNqwf46wIPWLR+vpxYxTpYpo1sBNMvUZfp2tEA8KKyMuw3j9ThO\npjO9R/UxWrFcztbZP/u3NbFrH/2Q95mbv9IlbnsuG5xbqqEig0wYg+uzBvaXbig3\n/Jr0vLT2BkRCBKQkYGjVZcHlHVLoF7/J8cghFgkV1PGvknOv6/q7qzn9L4TjQIet\nfhrhN8Z1vgFiSYtpjP6YQEUEPSHmCQeD3WzJcnASPpU2uCUwd/z65ltKPnn+rqMt\n6jt9R1S1Ju2ZSjv+kR5fIXzihdOzncyzDDm33c/QwQKBgQD2QDZuzLjTxnhsfGii\nKJDAts+Jqfs/6SeEJcJKtEngj4m7rgzyEjbKVp8qtRHIzglKRWAe62/qzzy2BkKi\nvAd4+ZzmG2SkgypGsKVfjGXVFixz2gtUdmBOmK/TnYsxNT9yTt+rX9IGqKK60q73\nOWl8VsliLIsfvSH7+bqi7sRcXQKBgQDo0VUebyQHoTAXPdzGy2ysrVPDiHcldH0Y\n/hvhQTZwxYaJr3HpOCGol2Xl6zyawuudEQsoQwJ3Li6yeb0YMGiWX77/t+qX3pSn\nkGuoftGaNDV7sLn9UV2y+InF8EL1CasrhG1k5RIuxyfV0w+QUo+E7LpVR5XkbJqT\n9QNKnDQXiwKBgQDvvEYCCqbp7e/xVhEbxbhfFdro4Cat6tRAz+3egrTlvXhO0jzi\nMp9Kz5f3oP5ma0gaGX5hu75icE1fvKqE+d+ghAqe7w5FJzkyRulJI0tEb2jphN7A\n5NoPypBqyZboWjmhlG4mzouPVf/POCuEnk028truDAWJ6by7Lj3oP+HFNQKBgQCc\n5BQ8QiFBkvnZb7LLtGIzq0n7RockEnAK25LmJRAOxs13E2fsBguIlR3x5qgckqY8\nXjPqmd2bet+1HhyzpEuWqkcIBGRum2wJz2T9UxjklbJE/D8Z2i8OYDZX0SUOA8n5\ntXASwduS8lqB2Y1vcHOO3AhlV6xHFnjEpCPnr4PbKQKBgAhQ9D9MPeuz+5yw3yHg\nkvULZRtud+uuaKrOayprN25RTxr9c0erxqnvM7KHeo6/urOXeEa7x2n21kAT0Nch\nkF2RtWBLZKXGZEVBtw1Fw0UKNh4IDgM26dwlzRfTVHCiw6M6dCiTNk9KkP2vlkim\n3QFDSSUp+eBTXA17WkDAQf7w\n-----END PRIVATE KEY-----\n",
31-
"client_email": "[email protected]",
32-
"client_id": "99999911111111",
33-
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
34-
"token_uri": "https://oauth2.googleapis.com/token",
35-
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
36-
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/bla"
37-
}`)
39+
3840
cf, _ := os.CreateTemp(".", "*")
39-
cf.Write(creds)
41+
cf.Write(TEST_GCP_CREDS)
4042
resp := struct {
4143
name string
4244
close func() error

pkg/generator/generator.go

Lines changed: 11 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ type Generatoriface interface {
5757
type GenVarsiface interface {
5858
Generatoriface
5959
Config() *GenVarsConfig
60-
ConfigOutputPath() string
6160
}
6261

6362
type muRawMap struct {
@@ -76,15 +75,12 @@ type GenVars struct {
7675
ctx context.Context
7776
config GenVarsConfig
7877
outString []string
79-
// rawMap is the internal object that holds the values of original token => retrieved value - decrypted in plain text
78+
// rawMap is the internal object that holds the values
79+
// of original token => retrieved value - decrypted in plain text
80+
// with a mutex RW locker
8081
rawMap muRawMap //ParsedMap
8182
}
8283

83-
// setValue implements GenVarsiface
84-
func (*GenVars) setValue(s string) {
85-
panic("unimplemented")
86-
}
87-
8884
// ParsedMap is the internal working object definition and
8985
// the return type if results are not flushed to file
9086
type ParsedMap map[string]any
@@ -131,12 +127,6 @@ func (c *GenVars) Config() *GenVarsConfig {
131127
return &c.config
132128
}
133129

134-
// ConfigOutputPath returns the output path set on GenVars create
135-
// withconfig or default value
136-
func (c *GenVars) ConfigOutputPath() string {
137-
return c.config.outpath
138-
}
139-
140130
func (c *GenVars) RawMap() ParsedMap {
141131
c.rawMap.RLock()
142132
defer c.rawMap.RUnlock()
@@ -154,41 +144,6 @@ func (c *GenVars) AddRawMap(key, val string) {
154144
c.rawMap.tokenMap[key] = c.keySeparatorLookup(key, val)
155145
}
156146

157-
// GenVarsConfig defines the input config object to be passed
158-
type GenVarsConfig struct {
159-
outpath string
160-
tokenSeparator string
161-
keySeparator string
162-
}
163-
164-
// NewConfig
165-
func NewConfig() *GenVarsConfig {
166-
return &GenVarsConfig{
167-
tokenSeparator: tokenSeparator,
168-
keySeparator: keySeparator,
169-
}
170-
}
171-
172-
// WithOutputPath
173-
func (c *GenVarsConfig) WithOutputPath(out string) *GenVarsConfig {
174-
c.outpath = out
175-
return c
176-
}
177-
178-
// WithTokenSeparator adds a custom token separator
179-
// token is the actual value of the parameter/secret in the
180-
// provider store
181-
func (c *GenVarsConfig) WithTokenSeparator(tokenSeparator string) *GenVarsConfig {
182-
c.tokenSeparator = tokenSeparator
183-
return c
184-
}
185-
186-
// WithKeySeparator adds a custom key separotor
187-
func (c *GenVarsConfig) WithKeySeparator(keySeparator string) *GenVarsConfig {
188-
c.keySeparator = keySeparator
189-
return c
190-
}
191-
192147
// Generate generates a k/v map of the tokens with their corresponding secret/paramstore values
193148
// the standard pattern of a token should follow a path like
194149
func (c *GenVars) Generate(tokens []string) (ParsedMap, error) {
@@ -215,7 +170,8 @@ type chanResp struct {
215170
}
216171

217172
type retrieveIface interface {
218-
retrieveSpecificCh(ctx context.Context, prefix ImplementationPrefix, in string) chanResp
173+
RetrieveByToken(ctx context.Context, impl genVarsStrategy, prefix ImplementationPrefix, in string) chanResp
174+
SelectImplementation(ctx context.Context, prefix ImplementationPrefix, in string, config *GenVarsConfig) (genVarsStrategy, error)
219175
}
220176

221177
// generate checks if any tokens found
@@ -238,7 +194,12 @@ func (c *GenVars) generate(rawMap map[string]string, rs retrieveIface) error {
238194
for token, prefix := range rawMap {
239195
go func(a string, p ImplementationPrefix) {
240196
defer wg.Done()
241-
outCh <- rs.retrieveSpecificCh(c.ctx, p, a)
197+
strategy, err := rs.SelectImplementation(c.ctx, p, a, c.Config())
198+
if err != nil {
199+
outCh <- chanResp{err: err}
200+
return
201+
}
202+
outCh <- rs.RetrieveByToken(c.ctx, strategy, p, a)
242203
}(token, ImplementationPrefix(prefix))
243204
}
244205

0 commit comments

Comments
 (0)