From e84f62e3a0553974e4e9be68f4246a8ba57d276c Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 20 Mar 2026 11:52:36 +0100 Subject: [PATCH 1/8] fix: update validation schema to include 'url' and adjust required fields --- validations.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/validations.go b/validations.go index 11fe5ba..4a10edf 100644 --- a/validations.go +++ b/validations.go @@ -14,11 +14,11 @@ const SCHEMA = `{ "properties": { "name": { "type": "string" }, "registry": { "type": "string" }, + "url": { "type": "string" }, "image_types": { "type": "array", "items": { "type": "string", "enum": ["snapshots", "releases"] } }, - "default": { "type": "boolean" }, "auth_strategy": { "type": "string", "enum": ["aws_oidc", "azure_oidc", "generic", "ghcr", "dockerhub"] @@ -32,7 +32,11 @@ const SCHEMA = `{ "required": ["services", "charts"] } }, - "required": ["name", "registry", "image_types", "default", "auth_strategy", "base_paths"] + "required": ["name", "image_types", "default", "auth_strategy", "base_paths"], + "oneOf": [ + { "required": ["registry"] }, + { "required": ["url"] } + ] }` func validate() { From d6150399cdcf911400b16e16cf2c909590b32d5a Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 20 Mar 2026 17:02:23 +0100 Subject: [PATCH 2/8] refactor: update registry handling to use 'url' instead of 'registryHost' and adjust validation schema --- io.go | 11 +++--- io_test.go | 14 ++++---- multilogin.go | 4 +-- types.go | 85 +++++++++++++++++++++++++++++++++++++++++++-- validations.go | 2 +- validations_test.go | 4 +-- 6 files changed, 102 insertions(+), 18 deletions(-) diff --git a/io.go b/io.go index 51bbc8f..651a376 100644 --- a/io.go +++ b/io.go @@ -25,15 +25,18 @@ func parseRegistriesFromDir(dir string) []Registry { registry, err := validateRegistryFileSchema(path) + // Skip registries without auth strategy, as they are considered public + if registry.AuthStrategy == "" { return nil } + if err != nil { panic(err) } - if mapRegistriesByHost[registry.RegistryHost] { + if mapRegistriesByHost[registry.Url] { - panic(fmt.Sprintf("Duplicated registry %s", registry.RegistryHost)) + panic(fmt.Sprintf("Duplicated registry %s", registry.Url)) } @@ -43,7 +46,7 @@ func parseRegistriesFromDir(dir string) []Registry { } - mapRegistriesByHost[registry.RegistryHost] = true + mapRegistriesByHost[registry.Url] = true mapRegistriesByName[registry.Name] = true registries = append(registries, registry) @@ -59,7 +62,7 @@ func findRegistryByUrl(url string, registries []Registry) Registry { for _, r := range registries { - if r.RegistryHost == url { + if r.Url == url { return r diff --git a/io_test.go b/io_test.go index dc1d6fe..1e45234 100644 --- a/io_test.go +++ b/io_test.go @@ -9,7 +9,7 @@ func TestRegistriesParser(t *testing.T) { registries := parseRegistriesFromDir("./test/fixtures/registries") - fmt.Printf("Registries: %v\n", registries[0].RegistryHost) + fmt.Printf("Registries: %v\n", registries[0].Url) t.Run("Registries number are ok", func(t *testing.T) { if len(registries) != 2 { @@ -18,12 +18,12 @@ func TestRegistriesParser(t *testing.T) { }) t.Run("Registries are parsed correctly", func(t *testing.T) { - if registries[0].RegistryHost != "acrsnapshots2.azurecr.io" { - t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registries[0].RegistryHost) + if registries[0].Url != "acrsnapshots2.azurecr.io" { + t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registries[0].Url) } - if registries[1].RegistryHost != "acrsnapshots.azurecr.io" { - t.Errorf("Expected acrsnapshots.azurecr.io, got %v", registries[1].RegistryHost) + if registries[1].Url != "acrsnapshots.azurecr.io" { + t.Errorf("Expected acrsnapshots.azurecr.io, got %v", registries[1].Url) } }) @@ -33,8 +33,8 @@ func TestRegistriesParser(t *testing.T) { fmt.Printf("Registry: %v\n", registry) - if registry.RegistryHost != "acrsnapshots2.azurecr.io" { - t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registry.RegistryHost) + if registry.Url != "acrsnapshots2.azurecr.io" { + t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registry.Url) } }) diff --git a/multilogin.go b/multilogin.go index 960bae3..d06451e 100644 --- a/multilogin.go +++ b/multilogin.go @@ -27,7 +27,7 @@ func multilogin() { auth = loginAWS() case "azure_oidc": - auth = loginAzure(registry.RegistryHost) + auth = loginAzure(registry.Url) case "dockerhub": auth = RegistryAuth{ @@ -40,7 +40,7 @@ func multilogin() { auth = RegistryAuth{ Username: creds[registryType+"_user"], Password: creds[registryType+"_pass"], - Registry: registry.RegistryHost, + Registry: registry.Url, } default: diff --git a/types.go b/types.go index f620cba..c652f33 100644 --- a/types.go +++ b/types.go @@ -1,10 +1,91 @@ package main +import "encoding/json" + type Registry struct { Name string `yaml:"name" json:"name"` - RegistryHost string `yaml:"registry" json:"registry"` - AuthStrategy string `yaml:"auth_strategy" json:"auth_strategy"` + Url string `yaml:"registry,omitempty" json:"registry,omitempty"` + AuthStrategy string `yaml:"auth_strategy" json:"auth_strategy,omitempty"` Default bool `yaml:"default" json:"default"` ImageTypes []string `yaml:"image_types" json:"image_types"` BasePaths map[string]string `yaml:"base_paths" json:"base_paths"` } + +// Custom YAML unmarshaling to support both 'registry' and 'url' mapping to RegistryHost +func (r *Registry) UnmarshalYAML(unmarshal func(interface{}) error) error { + var aux map[string]interface{} + if err := unmarshal(&aux); err != nil { + return err + } + if name, ok := aux["name"].(string); ok { + r.Name = name + } + if reg, ok := aux["registry"].(string); ok { + r.Url = reg + } else if url, ok := aux["url"].(string); ok { + r.Url = url + } + if auth, ok := aux["auth_strategy"].(string); ok { + r.AuthStrategy = auth + } + if def, ok := aux["default"].(bool); ok { + r.Default = def + } + if img, ok := aux["image_types"].([]interface{}); ok { + r.ImageTypes = make([]string, len(img)) + for i, v := range img { + if s, ok := v.(string); ok { + r.ImageTypes[i] = s + } + } + } + if bp, ok := aux["base_paths"].(map[string]interface{}); ok { + r.BasePaths = make(map[string]string) + for k, v := range bp { + if s, ok := v.(string); ok { + r.BasePaths[k] = s + } + } + } + return nil +} + +// Custom JSON unmarshaling to support both 'registry' and 'url' mapping to RegistryHost +func (r *Registry) UnmarshalJSON(data []byte) error { + type Alias Registry + var aux map[string]interface{} + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + if name, ok := aux["name"].(string); ok { + r.Name = name + } + if reg, ok := aux["registry"].(string); ok { + r.Url = reg + } else if url, ok := aux["url"].(string); ok { + r.Url = url + } + if auth, ok := aux["auth_strategy"].(string); ok { + r.AuthStrategy = auth + } + if def, ok := aux["default"].(bool); ok { + r.Default = def + } + if img, ok := aux["image_types"].([]interface{}); ok { + r.ImageTypes = make([]string, len(img)) + for i, v := range img { + if s, ok := v.(string); ok { + r.ImageTypes[i] = s + } + } + } + if bp, ok := aux["base_paths"].(map[string]interface{}); ok { + r.BasePaths = make(map[string]string) + for k, v := range bp { + if s, ok := v.(string); ok { + r.BasePaths[k] = s + } + } + } + return nil +} diff --git a/validations.go b/validations.go index 4a10edf..18bb1d4 100644 --- a/validations.go +++ b/validations.go @@ -32,7 +32,7 @@ const SCHEMA = `{ "required": ["services", "charts"] } }, - "required": ["name", "image_types", "default", "auth_strategy", "base_paths"], + "required": ["name", "image_types", "default", "base_paths"], "oneOf": [ { "required": ["registry"] }, { "required": ["url"] } diff --git a/validations_test.go b/validations_test.go index cf83be4..e5d50d3 100644 --- a/validations_test.go +++ b/validations_test.go @@ -7,7 +7,7 @@ import ( func TestValidateRegistryAgainstSchema(t *testing.T) { validRegistry := Registry{ Name: "example", - RegistryHost: "https://example.com", + Url: "https://example.com", ImageTypes: []string{"snapshots", "releases"}, Default: true, AuthStrategy: "aws_oidc", @@ -28,7 +28,7 @@ func TestValidateRegistryAgainstSchema(t *testing.T) { func TestValidateRegistryAgainstSchemaInvalid(t *testing.T) { invalidRegistry := Registry{ Name: "example", - RegistryHost: "https://example.com", + Url: "https://example.com", ImageTypes: []string{"NOT_VALID", ""}, Default: true, AuthStrategy: "NOT_VALID_STRATEGY", From 5189ac8208528f139693f07290c8c7e9d28e6055 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Tue, 24 Mar 2026 17:08:55 +0100 Subject: [PATCH 3/8] fix: update registry validation to use 'url' instead of 'registry' and adjust required fields --- io.go | 7 ++++--- types.go | 5 ++--- validations.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/io.go b/io.go index 651a376..2779237 100644 --- a/io.go +++ b/io.go @@ -25,15 +25,16 @@ func parseRegistriesFromDir(dir string) []Registry { registry, err := validateRegistryFileSchema(path) - // Skip registries without auth strategy, as they are considered public - if registry.AuthStrategy == "" { return nil } - if err != nil { panic(err) } + // Skip registries without auth strategy, as they are considered public + if registry.AuthStrategy == "" { + return nil + } if mapRegistriesByHost[registry.Url] { panic(fmt.Sprintf("Duplicated registry %s", registry.Url)) diff --git a/types.go b/types.go index c652f33..5ada057 100644 --- a/types.go +++ b/types.go @@ -4,7 +4,7 @@ import "encoding/json" type Registry struct { Name string `yaml:"name" json:"name"` - Url string `yaml:"registry,omitempty" json:"registry,omitempty"` + Url string `yaml:"url,omitempty" json:"url,omitempty"` AuthStrategy string `yaml:"auth_strategy" json:"auth_strategy,omitempty"` Default bool `yaml:"default" json:"default"` ImageTypes []string `yaml:"image_types" json:"image_types"` @@ -50,9 +50,8 @@ func (r *Registry) UnmarshalYAML(unmarshal func(interface{}) error) error { return nil } -// Custom JSON unmarshaling to support both 'registry' and 'url' mapping to RegistryHost +// Custom JSON unmarshaling to support both 'registry' and 'url' mapping to Url func (r *Registry) UnmarshalJSON(data []byte) error { - type Alias Registry var aux map[string]interface{} if err := json.Unmarshal(data, &aux); err != nil { return err diff --git a/validations.go b/validations.go index 18bb1d4..e8d9f33 100644 --- a/validations.go +++ b/validations.go @@ -32,7 +32,7 @@ const SCHEMA = `{ "required": ["services", "charts"] } }, - "required": ["name", "image_types", "default", "base_paths"], + "required": ["name", "image_types", "base_paths"], "oneOf": [ { "required": ["registry"] }, { "required": ["url"] } From de8eb1f8b841f0a2b1ce58a1e78337690c9f870d Mon Sep 17 00:00:00 2001 From: Jose Alvarez <47305925+jalvarezit@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:43:19 +0200 Subject: [PATCH 4/8] update oauth oci --- io.go | 8 ++++---- io_test.go | 14 +++++++------- multilogin.go | 4 ++-- types.go | 6 ++---- validations.go | 6 +----- validations_test.go | 4 ++-- 6 files changed, 18 insertions(+), 24 deletions(-) diff --git a/io.go b/io.go index 2779237..0bb32e3 100644 --- a/io.go +++ b/io.go @@ -35,9 +35,9 @@ func parseRegistriesFromDir(dir string) []Registry { if registry.AuthStrategy == "" { return nil } - if mapRegistriesByHost[registry.Url] { + if mapRegistriesByHost[registry.RegistryHost] { - panic(fmt.Sprintf("Duplicated registry %s", registry.Url)) + panic(fmt.Sprintf("Duplicated registry %s", registry.RegistryHost)) } @@ -47,7 +47,7 @@ func parseRegistriesFromDir(dir string) []Registry { } - mapRegistriesByHost[registry.Url] = true + mapRegistriesByHost[registry.RegistryHost] = true mapRegistriesByName[registry.Name] = true registries = append(registries, registry) @@ -63,7 +63,7 @@ func findRegistryByUrl(url string, registries []Registry) Registry { for _, r := range registries { - if r.Url == url { + if r.RegistryHost == url { return r diff --git a/io_test.go b/io_test.go index 1e45234..dc1d6fe 100644 --- a/io_test.go +++ b/io_test.go @@ -9,7 +9,7 @@ func TestRegistriesParser(t *testing.T) { registries := parseRegistriesFromDir("./test/fixtures/registries") - fmt.Printf("Registries: %v\n", registries[0].Url) + fmt.Printf("Registries: %v\n", registries[0].RegistryHost) t.Run("Registries number are ok", func(t *testing.T) { if len(registries) != 2 { @@ -18,12 +18,12 @@ func TestRegistriesParser(t *testing.T) { }) t.Run("Registries are parsed correctly", func(t *testing.T) { - if registries[0].Url != "acrsnapshots2.azurecr.io" { - t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registries[0].Url) + if registries[0].RegistryHost != "acrsnapshots2.azurecr.io" { + t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registries[0].RegistryHost) } - if registries[1].Url != "acrsnapshots.azurecr.io" { - t.Errorf("Expected acrsnapshots.azurecr.io, got %v", registries[1].Url) + if registries[1].RegistryHost != "acrsnapshots.azurecr.io" { + t.Errorf("Expected acrsnapshots.azurecr.io, got %v", registries[1].RegistryHost) } }) @@ -33,8 +33,8 @@ func TestRegistriesParser(t *testing.T) { fmt.Printf("Registry: %v\n", registry) - if registry.Url != "acrsnapshots2.azurecr.io" { - t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registry.Url) + if registry.RegistryHost != "acrsnapshots2.azurecr.io" { + t.Errorf("Expected acrsnapshots2.azurecr.io, got %v", registry.RegistryHost) } }) diff --git a/multilogin.go b/multilogin.go index d06451e..960bae3 100644 --- a/multilogin.go +++ b/multilogin.go @@ -27,7 +27,7 @@ func multilogin() { auth = loginAWS() case "azure_oidc": - auth = loginAzure(registry.Url) + auth = loginAzure(registry.RegistryHost) case "dockerhub": auth = RegistryAuth{ @@ -40,7 +40,7 @@ func multilogin() { auth = RegistryAuth{ Username: creds[registryType+"_user"], Password: creds[registryType+"_pass"], - Registry: registry.Url, + Registry: registry.RegistryHost, } default: diff --git a/types.go b/types.go index 5ada057..43b972c 100644 --- a/types.go +++ b/types.go @@ -4,7 +4,7 @@ import "encoding/json" type Registry struct { Name string `yaml:"name" json:"name"` - Url string `yaml:"url,omitempty" json:"url,omitempty"` + RegistryHost string `yaml:"url,omitempty" json:"registry,omitempty"` AuthStrategy string `yaml:"auth_strategy" json:"auth_strategy,omitempty"` Default bool `yaml:"default" json:"default"` ImageTypes []string `yaml:"image_types" json:"image_types"` @@ -60,9 +60,7 @@ func (r *Registry) UnmarshalJSON(data []byte) error { r.Name = name } if reg, ok := aux["registry"].(string); ok { - r.Url = reg - } else if url, ok := aux["url"].(string); ok { - r.Url = url + r.RegistryHost = reg } if auth, ok := aux["auth_strategy"].(string); ok { r.AuthStrategy = auth diff --git a/validations.go b/validations.go index e8d9f33..ec66a45 100644 --- a/validations.go +++ b/validations.go @@ -32,11 +32,7 @@ const SCHEMA = `{ "required": ["services", "charts"] } }, - "required": ["name", "image_types", "base_paths"], - "oneOf": [ - { "required": ["registry"] }, - { "required": ["url"] } - ] + "required": ["name", "registry", "image_types", "base_paths"], }` func validate() { diff --git a/validations_test.go b/validations_test.go index e5d50d3..d77c08d 100644 --- a/validations_test.go +++ b/validations_test.go @@ -7,7 +7,7 @@ import ( func TestValidateRegistryAgainstSchema(t *testing.T) { validRegistry := Registry{ Name: "example", - Url: "https://example.com", + Registry: "https://example.com", ImageTypes: []string{"snapshots", "releases"}, Default: true, AuthStrategy: "aws_oidc", @@ -28,7 +28,7 @@ func TestValidateRegistryAgainstSchema(t *testing.T) { func TestValidateRegistryAgainstSchemaInvalid(t *testing.T) { invalidRegistry := Registry{ Name: "example", - Url: "https://example.com", + Registry: "https://example.com", ImageTypes: []string{"NOT_VALID", ""}, Default: true, AuthStrategy: "NOT_VALID_STRATEGY", From b59c700c58e701db185cd29353f65779873c9d29 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 17 Apr 2026 13:24:18 +0200 Subject: [PATCH 5/8] fix: update registry field to use 'RegistryHost' instead of 'Registry' in types and tests --- types.go | 4 ++-- validations_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/types.go b/types.go index 43b972c..9f6061f 100644 --- a/types.go +++ b/types.go @@ -21,9 +21,9 @@ func (r *Registry) UnmarshalYAML(unmarshal func(interface{}) error) error { r.Name = name } if reg, ok := aux["registry"].(string); ok { - r.Url = reg + r.RegistryHost = reg } else if url, ok := aux["url"].(string); ok { - r.Url = url + r.RegistryHost = url } if auth, ok := aux["auth_strategy"].(string); ok { r.AuthStrategy = auth diff --git a/validations_test.go b/validations_test.go index d77c08d..cf83be4 100644 --- a/validations_test.go +++ b/validations_test.go @@ -7,7 +7,7 @@ import ( func TestValidateRegistryAgainstSchema(t *testing.T) { validRegistry := Registry{ Name: "example", - Registry: "https://example.com", + RegistryHost: "https://example.com", ImageTypes: []string{"snapshots", "releases"}, Default: true, AuthStrategy: "aws_oidc", @@ -28,7 +28,7 @@ func TestValidateRegistryAgainstSchema(t *testing.T) { func TestValidateRegistryAgainstSchemaInvalid(t *testing.T) { invalidRegistry := Registry{ Name: "example", - Registry: "https://example.com", + RegistryHost: "https://example.com", ImageTypes: []string{"NOT_VALID", ""}, Default: true, AuthStrategy: "NOT_VALID_STRATEGY", From cc5aa0ad2e6a66ebddecfe72024b4fb609038388 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 17 Apr 2026 13:35:22 +0200 Subject: [PATCH 6/8] fix: correct formatting in validation schema definition --- validations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validations.go b/validations.go index ec66a45..7e6dcef 100644 --- a/validations.go +++ b/validations.go @@ -32,7 +32,7 @@ const SCHEMA = `{ "required": ["services", "charts"] } }, - "required": ["name", "registry", "image_types", "base_paths"], + "required": ["name", "registry", "image_types", "base_paths"] }` func validate() { From e784e475a4733ebc8f4c2438e3515133f8bd0f6f Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 17 Apr 2026 13:42:44 +0200 Subject: [PATCH 7/8] fix: update validation schema to remove unnecessary required fields --- validations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validations.go b/validations.go index 7e6dcef..1b354d8 100644 --- a/validations.go +++ b/validations.go @@ -32,7 +32,7 @@ const SCHEMA = `{ "required": ["services", "charts"] } }, - "required": ["name", "registry", "image_types", "base_paths"] + "required": ["name", "registry"] }` func validate() { From ea7491114ed7bed9157b2ff03d5750b724280bff Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Fri, 17 Apr 2026 13:46:36 +0200 Subject: [PATCH 8/8] fix: update validation schema to allow null values for image_types and base_paths --- validations.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validations.go b/validations.go index 1b354d8..1dd501c 100644 --- a/validations.go +++ b/validations.go @@ -16,7 +16,7 @@ const SCHEMA = `{ "registry": { "type": "string" }, "url": { "type": "string" }, "image_types": { - "type": "array", + "type": ["array", "null"], "items": { "type": "string", "enum": ["snapshots", "releases"] } }, "auth_strategy": { @@ -24,7 +24,7 @@ const SCHEMA = `{ "enum": ["aws_oidc", "azure_oidc", "generic", "ghcr", "dockerhub"] }, "base_paths": { - "type": "object", + "type": ["object", "null"], "properties": { "services": { "type": "string" }, "charts": { "type": "string" }