Skip to content

Commit ded7a28

Browse files
chengfangvsychov
andauthored
feat(registry): Improve repository selection, based on prefixes in config and full image name (#1233)
Signed-off-by: Cheng Fang <[email protected]> Co-authored-by: Viacheslav Sychov <[email protected]>
1 parent 9daecb3 commit ded7a28

File tree

8 files changed

+91
-41
lines changed

8 files changed

+91
-41
lines changed

cmd/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/argoproj-labs/argocd-image-updater/pkg/version"
1919
"github.com/argoproj-labs/argocd-image-updater/pkg/webhook"
2020
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/env"
21+
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"
2122
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/log"
2223
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/registry"
2324

@@ -476,7 +477,7 @@ func warmupImageCache(cfg *ImageUpdaterConfig) error {
476477
entries := 0
477478
eps := registry.ConfiguredEndpoints()
478479
for _, ep := range eps {
479-
r, err := registry.GetRegistryEndpoint(ep)
480+
r, err := registry.GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ep})
480481
if err == nil {
481482
entries += r.Cache.NumEntries()
482483
}

cmd/test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ argocd-image-updater test nginx --allow-tags '^1.19.\d+(\-.*)*$' --update-strate
113113
}
114114
}
115115

116-
ep, err := registry.GetRegistryEndpoint(img.RegistryURL)
116+
ep, err := registry.GetRegistryEndpoint(img)
117117
if err != nil {
118118
logCtx.Fatalf("could not get registry endpoint: %v", err)
119119
}

pkg/argocd/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func UpdateApplication(updateConf *UpdateConfiguration, state *SyncIterationStat
204204

205205
imgCtx.Debugf("Considering this image for update")
206206

207-
rep, err := registry.GetRegistryEndpoint(applicationImage.RegistryURL)
207+
rep, err := registry.GetRegistryEndpoint(applicationImage)
208208
if err != nil {
209209
imgCtx.Errorf("Could not get registry endpoint from configuration: %v", err)
210210
result.NumErrors += 1

registry-scanner/pkg/registry/client_test.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/stretchr/testify/require"
2323

2424
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/log"
25+
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"
2526
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/options"
2627
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/registry/mocks"
2728
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/tag"
@@ -46,7 +47,7 @@ func TestBasic(t *testing.T) {
4647

4748
func TestNewRepository(t *testing.T) {
4849
t.Run("Invalid Reference Format", func(t *testing.T) {
49-
ep, err := GetRegistryEndpoint("")
50+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
5051
require.NoError(t, err)
5152
client, err := NewClient(ep, "", "")
5253
require.NoError(t, err)
@@ -56,7 +57,7 @@ func TestNewRepository(t *testing.T) {
5657

5758
})
5859
t.Run("Success Ping", func(t *testing.T) {
59-
ep, err := GetRegistryEndpoint("")
60+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
6061
require.NoError(t, err)
6162
client, err := NewClient(ep, "", "")
6263
require.NoError(t, err)
@@ -156,7 +157,7 @@ func TestSetRefreshToken(t *testing.T) {
156157
}
157158
func TestNewClient(t *testing.T) {
158159
t.Run("Create client with provided username and password", func(t *testing.T) {
159-
ep, err := GetRegistryEndpoint("")
160+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
160161
require.NoError(t, err)
161162
_, err = NewClient(ep, "testuser", "pass")
162163
require.NoError(t, err)
@@ -402,7 +403,7 @@ func Test_TagMetadata(t *testing.T) {
402403
History: []schema1.History{}, //nolint:staticcheck
403404
},
404405
}
405-
ep, err := GetRegistryEndpoint("")
406+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
406407
require.NoError(t, err)
407408
client, err := NewClient(ep, "", "")
408409
require.NoError(t, err)
@@ -421,7 +422,7 @@ func Test_TagMetadata(t *testing.T) {
421422
},
422423
}
423424

424-
ep, err := GetRegistryEndpoint("")
425+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
425426
require.NoError(t, err)
426427
client, err := NewClient(ep, "", "")
427428
require.NoError(t, err)
@@ -440,7 +441,7 @@ func Test_TagMetadata(t *testing.T) {
440441
},
441442
}
442443

443-
ep, err := GetRegistryEndpoint("")
444+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
444445
require.NoError(t, err)
445446
client, err := NewClient(ep, "", "")
446447
require.NoError(t, err)
@@ -460,7 +461,7 @@ func Test_TagMetadata(t *testing.T) {
460461
},
461462
},
462463
}
463-
ep, err := GetRegistryEndpoint("")
464+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
464465
require.NoError(t, err)
465466
client, err := NewClient(ep, "", "")
466467
require.NoError(t, err)
@@ -490,7 +491,7 @@ func Test_TagMetadata_2(t *testing.T) {
490491
},
491492
},
492493
}
493-
ep, err := GetRegistryEndpoint("")
494+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
494495
require.NoError(t, err)
495496
client, err := NewClient(ep, "", "")
496497

@@ -513,7 +514,7 @@ func Test_TagMetadata_2(t *testing.T) {
513514
},
514515
},
515516
}
516-
ep, err := GetRegistryEndpoint("")
517+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
517518
require.NoError(t, err)
518519
client, err := NewClient(ep, "", "")
519520

@@ -534,7 +535,7 @@ func Test_TagMetadata_2(t *testing.T) {
534535
Annotations: nil,
535536
},
536537
}
537-
ep, err := GetRegistryEndpoint("")
538+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
538539
require.NoError(t, err)
539540
client, err := NewClient(ep, "", "")
540541

@@ -554,7 +555,7 @@ func Test_TagMetadata_2(t *testing.T) {
554555
Manifests: nil,
555556
},
556557
}
557-
ep, err := GetRegistryEndpoint("")
558+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
558559
require.NoError(t, err)
559560
client, err := NewClient(ep, "", "")
560561

@@ -569,7 +570,7 @@ func Test_TagMetadata_2(t *testing.T) {
569570
func TestPing(t *testing.T) {
570571
t.Run("fail ping", func(t *testing.T) {
571572
mockManager := new(mocks.Manager)
572-
ep, err := GetRegistryEndpoint("")
573+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
573574
require.NoError(t, err)
574575
mockManager.On("AddResponse", mock.Anything).Return(fmt.Errorf("fail ping"))
575576
_, err = ping(mockManager, ep, "")
@@ -578,7 +579,7 @@ func TestPing(t *testing.T) {
578579

579580
t.Run("success ping", func(t *testing.T) {
580581
mockManager := new(mocks.Manager)
581-
ep, err := GetRegistryEndpoint("")
582+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
582583
require.NoError(t, err)
583584
mockManager.On("AddResponse", mock.Anything).Return(nil)
584585
_, err = ping(mockManager, ep, "")

registry-scanner/pkg/registry/config_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55
"time"
66

7+
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"
78
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/test/fixture"
89

910
"github.com/stretchr/testify/assert"
@@ -81,15 +82,15 @@ func Test_LoadRegistryConfiguration(t *testing.T) {
8182
err := LoadRegistryConfiguration("../../config/example-config.yaml", true)
8283
require.NoError(t, err)
8384
assert.Len(t, registries, 4)
84-
reg, err := GetRegistryEndpoint("gcr.io")
85+
reg, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "gcr.io"})
8586
require.NoError(t, err)
8687
assert.Equal(t, "pullsecret:foo/bar", reg.Credentials)
87-
reg, err = GetRegistryEndpoint("ghcr.io")
88+
reg, err = GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "ghcr.io"})
8889
require.NoError(t, err)
8990
assert.Equal(t, "ext:/some/script", reg.Credentials)
9091
assert.Equal(t, 5*time.Hour, reg.CredsExpire)
9192
RestoreDefaultRegistryConfiguration()
92-
reg, err = GetRegistryEndpoint("gcr.io")
93+
reg, err = GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "gcr.io"})
9394
require.NoError(t, err)
9495
assert.Equal(t, "", reg.Credentials)
9596
})

registry-scanner/pkg/registry/endpoints.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/cache"
13+
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"
1314
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/log"
1415

1516
"go.uber.org/ratelimit"
@@ -183,8 +184,28 @@ func inferRegistryEndpointFromPrefix(prefix string) *RegistryEndpoint {
183184
return NewRegistryEndpoint(prefix, prefix, apiURL, "", "", false, TagListSortUnsorted, 20, 0)
184185
}
185186

186-
// GetRegistryEndpoint retrieves the endpoint information for the given prefix
187-
func GetRegistryEndpoint(prefix string) (*RegistryEndpoint, error) {
187+
// findRegistryEndpointByImage finds registry by prefix based on full image name
188+
func findRegistryEndpointByImage(img *image.ContainerImage) (ep *RegistryEndpoint) {
189+
imgName := fmt.Sprintf("%s/%s", img.RegistryURL, img.ImageName)
190+
log.Debugf("Try to find endpoint by image: %s", imgName)
191+
registryLock.RLock()
192+
defer registryLock.RUnlock()
193+
194+
for _, registry := range registries {
195+
matchRegistryPrefix := strings.HasPrefix(imgName, registry.RegistryPrefix)
196+
if (ep == nil && matchRegistryPrefix) || (matchRegistryPrefix && len(registry.RegistryPrefix) > len(ep.RegistryPrefix)) {
197+
log.Debugf("Selected registry: '%s' (last selection in log - final)", registry.RegistryName)
198+
ep = registry
199+
}
200+
}
201+
202+
return
203+
}
204+
205+
// GetRegistryEndpoint retrieves the endpoint information for the given image
206+
func GetRegistryEndpoint(img *image.ContainerImage) (*RegistryEndpoint, error) {
207+
prefix := img.RegistryURL
208+
188209
if prefix == "" {
189210
if defaultRegistry == nil {
190211
return nil, fmt.Errorf("no default endpoint configured")
@@ -200,8 +221,13 @@ func GetRegistryEndpoint(prefix string) (*RegistryEndpoint, error) {
200221
if ok {
201222
return registry, nil
202223
} else {
224+
ep := findRegistryEndpointByImage(img)
225+
if ep != nil {
226+
return ep, nil
227+
}
228+
203229
var err error
204-
ep := inferRegistryEndpointFromPrefix(prefix)
230+
ep = inferRegistryEndpointFromPrefix(prefix)
205231
if ep != nil {
206232
err = AddRegistryEndpoint(ep)
207233
} else {
@@ -239,7 +265,7 @@ func GetDefaultRegistry() *RegistryEndpoint {
239265
// SetRegistryEndpointCredentials allows to change the credentials used for
240266
// endpoint access for existing RegistryEndpoint configuration
241267
func SetRegistryEndpointCredentials(prefix, credentials string) error {
242-
registry, err := GetRegistryEndpoint(prefix)
268+
registry, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: prefix})
243269
if err != nil {
244270
return err
245271
}

registry-scanner/pkg/registry/endpoints_test.go

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ import (
77
"testing"
88
"time"
99

10+
"github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/image"
11+
1012
"github.com/stretchr/testify/assert"
1113
"github.com/stretchr/testify/require"
14+
1215
)
1316

1417
func TestInferRegistryEndpointFromPrefix(t *testing.T) {
@@ -116,21 +119,21 @@ func Test_GetEndpoints(t *testing.T) {
116119
RestoreDefaultRegistryConfiguration()
117120

118121
t.Run("Get default endpoint", func(t *testing.T) {
119-
ep, err := GetRegistryEndpoint("")
122+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
120123
require.NoError(t, err)
121124
require.NotNil(t, ep)
122125
assert.Equal(t, "docker.io", ep.RegistryPrefix)
123126
})
124127

125128
t.Run("Get GCR endpoint", func(t *testing.T) {
126-
ep, err := GetRegistryEndpoint("gcr.io")
129+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "gcr.io"})
127130
require.NoError(t, err)
128131
require.NotNil(t, ep)
129132
assert.Equal(t, ep.RegistryPrefix, "gcr.io")
130133
})
131134

132135
t.Run("Infer endpoint", func(t *testing.T) {
133-
ep, err := GetRegistryEndpoint("foobar.com")
136+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "foobar.com"})
134137
require.NoError(t, err)
135138
require.NotNil(t, ep)
136139
assert.Equal(t, "foobar.com", ep.RegistryPrefix)
@@ -146,7 +149,7 @@ func Test_AddEndpoint(t *testing.T) {
146149
require.NoError(t, err)
147150
})
148151
t.Run("Get example.com endpoint", func(t *testing.T) {
149-
ep, err := GetRegistryEndpoint("example.com")
152+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "example.com"})
150153
require.NoError(t, err)
151154
require.NotNil(t, ep)
152155
assert.Equal(t, ep.RegistryPrefix, "example.com")
@@ -159,7 +162,7 @@ func Test_AddEndpoint(t *testing.T) {
159162
t.Run("Change existing endpoint", func(t *testing.T) {
160163
err := AddRegistryEndpoint(NewRegistryEndpoint("example.com", "Example", "https://example.com", "", "library", true, TagListSortLatestFirst, 5, 0))
161164
require.NoError(t, err)
162-
ep, err := GetRegistryEndpoint("example.com")
165+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "example.com"})
163166
require.NoError(t, err)
164167
require.NotNil(t, ep)
165168
assert.Equal(t, ep.Insecure, true)
@@ -174,7 +177,7 @@ func Test_SetEndpointCredentials(t *testing.T) {
174177
t.Run("Set credentials on default registry", func(t *testing.T) {
175178
err := SetRegistryEndpointCredentials("", "env:FOOBAR")
176179
require.NoError(t, err)
177-
ep, err := GetRegistryEndpoint("")
180+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
178181
require.NoError(t, err)
179182
require.NotNil(t, ep)
180183
assert.Equal(t, ep.Credentials, "env:FOOBAR")
@@ -183,13 +186,31 @@ func Test_SetEndpointCredentials(t *testing.T) {
183186
t.Run("Unset credentials on default registry", func(t *testing.T) {
184187
err := SetRegistryEndpointCredentials("", "")
185188
require.NoError(t, err)
186-
ep, err := GetRegistryEndpoint("")
189+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
187190
require.NoError(t, err)
188191
require.NotNil(t, ep)
189192
assert.Equal(t, ep.Credentials, "")
190193
})
191194
}
192195

196+
func Test_SelectRegistryBasedOnMaxPrefixContains(t *testing.T) {
197+
RestoreDefaultRegistryConfiguration()
198+
199+
t.Run("Set credentials on default registry", func(t *testing.T) {
200+
err := SetRegistryEndpointCredentials("foo.bar/prefix1", "env:FOOBAR_1")
201+
require.NoError(t, err)
202+
err = SetRegistryEndpointCredentials("foo.bar/prefix2", "env:FOOBAR_2")
203+
require.NoError(t, err)
204+
err = SetRegistryEndpointCredentials("foo.bar/prefix1/sub-prefix", "env:FOOBAR_SUB_1")
205+
require.NoError(t, err)
206+
207+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "foo.bar", ImageName: "prefix1/sub-prefix/image"})
208+
require.NoError(t, err)
209+
require.NotNil(t, ep)
210+
assert.Equal(t, ep.Credentials, "env:FOOBAR_SUB_1")
211+
})
212+
}
213+
193214
func Test_EndpointConcurrentAccess(t *testing.T) {
194215
RestoreDefaultRegistryConfiguration()
195216
const numRuns = 50
@@ -199,7 +220,7 @@ func Test_EndpointConcurrentAccess(t *testing.T) {
199220
wg.Add(numRuns)
200221
for i := 0; i < numRuns; i++ {
201222
go func() {
202-
ep, err := GetRegistryEndpoint("gcr.io")
223+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "gcr.io"})
203224
require.NoError(t, err)
204225
require.NotNil(t, ep)
205226
wg.Done()
@@ -217,7 +238,7 @@ func Test_EndpointConcurrentAccess(t *testing.T) {
217238
creds := fmt.Sprintf("secret:foo/secret-%d", i)
218239
err := SetRegistryEndpointCredentials("", creds)
219240
require.NoError(t, err)
220-
ep, err := GetRegistryEndpoint("")
241+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: ""})
221242
require.NoError(t, err)
222243
require.NotNil(t, ep)
223244
wg.Done()
@@ -235,7 +256,7 @@ func Test_SetDefault(t *testing.T) {
235256
assert.Equal(t, "docker.io", dep.RegistryPrefix)
236257
assert.True(t, dep.IsDefault)
237258

238-
ep, err := GetRegistryEndpoint("ghcr.io")
259+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "ghcr.io"})
239260
require.NoError(t, err)
240261
require.NotNil(t, ep)
241262
require.False(t, ep.IsDefault)
@@ -249,7 +270,7 @@ func Test_SetDefault(t *testing.T) {
249270

250271
func Test_DeepCopy(t *testing.T) {
251272
t.Run("DeepCopy endpoint object", func(t *testing.T) {
252-
ep, err := GetRegistryEndpoint("docker.pkg.github.com")
273+
ep, err := GetRegistryEndpoint(&image.ContainerImage{RegistryURL: "docker.pkg.github.com"})
253274
require.NoError(t, err)
254275
require.NotNil(t, ep)
255276
newEp := ep.DeepCopy()

0 commit comments

Comments
 (0)