Skip to content

Commit 7eb6f61

Browse files
authored
Merge pull request #440 from docker/replacen
feat: (generic realm) expansion
2 parents 5c579f1 + 6cba750 commit 7eb6f61

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

runtime/internal/launcher/plugin_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,14 @@ func (m maliciousPattern) String() string {
339339
return "a*a"
340340
}
341341

342+
func (m maliciousPattern) ExpandID(secrets.ID) (secrets.ID, error) {
343+
panic("implement me")
344+
}
345+
346+
func (m maliciousPattern) ExpandPattern(secrets.Pattern) (secrets.Pattern, error) {
347+
panic("implement me")
348+
}
349+
342350
func testExternalPluginConfig(t *testing.T) p.Config {
343351
t.Helper()
344352
return p.Config{Version: api.MustNewVersion("v4"), Pattern: mockPattern, Logger: testhelper.TestLogger(t)}

x/api/resolver/resolver_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,14 @@ func (m maliciousPattern) String() string {
147147
return "/"
148148
}
149149

150+
func (m maliciousPattern) ExpandID(secrets.ID) (secrets.ID, error) {
151+
panic("implement me")
152+
}
153+
154+
func (m maliciousPattern) ExpandPattern(secrets.Pattern) (secrets.Pattern, error) {
155+
panic("implement me")
156+
}
157+
150158
func newGetSecretRequest(pattern secrets.Pattern) *connect.Request[resolverv1.GetSecretsRequest] {
151159
return connect.NewRequest(resolverv1.GetSecretsRequest_builder{
152160
Pattern: proto.String(pattern.String()),

x/secrets/pattern.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package secrets
22

33
import (
44
"errors"
5+
"fmt"
6+
"strings"
57
)
68

79
var ErrInvalidPattern = errors.New("invalid pattern")
@@ -71,6 +73,9 @@ type Pattern interface {
7173
Includes(other Pattern) bool
7274
// String formats the [Pattern] as a string
7375
String() string
76+
77+
ExpandID(other ID) (ID, error)
78+
ExpandPattern(other Pattern) (Pattern, error)
7479
}
7580

7681
type pattern string
@@ -118,6 +123,22 @@ func MustParsePattern(s string) Pattern {
118123
return pattern(s)
119124
}
120125

126+
func (p pattern) ExpandID(other ID) (ID, error) {
127+
val, err := replace1(string(p), other.String())
128+
if err != nil {
129+
return nil, err
130+
}
131+
return id(val), err
132+
}
133+
134+
func (p pattern) ExpandPattern(other Pattern) (Pattern, error) {
135+
val, err := replace1(string(p), other.String())
136+
if err != nil {
137+
return nil, err
138+
}
139+
return pattern(val), err
140+
}
141+
121142
// Filter returns a reduced [Pattern] that is subset equal to [filter].
122143
// Returns false if there's no overlap between [filter] and [other].
123144
// Examples:
@@ -134,3 +155,18 @@ func Filter(filter, other Pattern) (Pattern, bool) {
134155
}
135156
return nil, false
136157
}
158+
159+
func replace1(original, other string) (string, error) {
160+
components := split(original)
161+
var candidates []int
162+
for idx, val := range components {
163+
if val == "**" {
164+
candidates = append(candidates, idx)
165+
}
166+
}
167+
if len(candidates) != 1 {
168+
return "", fmt.Errorf("expand only supports one expansion glob, pattern %s has %d", original, len(candidates))
169+
}
170+
components[candidates[0]] = other
171+
return strings.Join(components, "/"), nil
172+
}

x/secrets/pattern_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,72 @@ func Test_Filter(t *testing.T) {
141141
})
142142
}
143143
}
144+
145+
func Test_apply(t *testing.T) {
146+
type query struct {
147+
pattern string
148+
result string
149+
}
150+
tests := []struct {
151+
pattern string
152+
queries []query
153+
}{
154+
{
155+
pattern: "foo/bar/**",
156+
queries: []query{
157+
{
158+
pattern: "baz",
159+
result: "foo/bar/baz",
160+
},
161+
{
162+
pattern: "**",
163+
result: "foo/bar/**",
164+
},
165+
{
166+
pattern: "**/*",
167+
result: "foo/bar/**/*",
168+
},
169+
},
170+
},
171+
{
172+
pattern: "**/*",
173+
queries: []query{
174+
{
175+
pattern: "baz",
176+
result: "baz/*",
177+
},
178+
{
179+
pattern: "bar/baz",
180+
result: "bar/baz/*",
181+
},
182+
{
183+
pattern: "**",
184+
result: "**/*",
185+
},
186+
},
187+
},
188+
{
189+
pattern: "**/**",
190+
queries: []query{
191+
{
192+
pattern: "**/bar",
193+
},
194+
},
195+
},
196+
}
197+
for idx, test := range tests {
198+
t.Run(fmt.Sprintf("%d - %s", idx, test.pattern), func(t *testing.T) {
199+
for inner, query := range test.queries {
200+
t.Run(fmt.Sprintf("%d-%d %s %s", idx, inner, test.pattern, query.pattern), func(t *testing.T) {
201+
result, err := replace1(test.pattern, query.pattern)
202+
if query.result == "" {
203+
assert.Error(t, err, fmt.Sprintf("got: %s", result))
204+
return
205+
}
206+
require.NoError(t, err, fmt.Sprintf("query: %s, expected out: %s", query.pattern, query.result))
207+
assert.Equal(t, query.result, result)
208+
})
209+
}
210+
})
211+
}
212+
}

0 commit comments

Comments
 (0)