fix pre-commit and cleanup
This commit is contained in:
@@ -1,187 +1,187 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
)
|
||||
|
||||
var (
|
||||
// Valid SemVer format (Major.Minor.Patch)
|
||||
semVerPattern = regexp.MustCompile(`^(\d+)\.(\d+)\.(\d+)$`)
|
||||
// Matches tags like "RELEASE.2023-11-20T22-40-07Z"
|
||||
releasePattern = regexp.MustCompile(`^RELEASE\.[0-9]{4}-[0-9]{2}-[0-9]{2}T`)
|
||||
// Matches tags like "x64-1.2.3" and "arm64-1.2.3" followed by a numeric version
|
||||
archPattern = regexp.MustCompile(`^[a-zA-Z0-9]+-[0-9]+\.[0-9]+`)
|
||||
// Matches tags like "latest-2023-12-18"
|
||||
prefixYearMonthDayPattern = regexp.MustCompile(`^[a-zA-Z0-9]+-[0-9]{4}-[0-9]{2}-[0-9]{2}$`)
|
||||
// Matches dates like "2023-11-15" and "2022-04"
|
||||
yearMonthDayPattern = regexp.MustCompile(`^[0-9]{4}-[0-9]{2}(-[0-9]{2})?$`)
|
||||
// Matches tags like "1.2.3.4" "1.2" and "1"
|
||||
incompleteSemVerPattern = regexp.MustCompile(`^[0-9]+(\.[0-9]+)*$`)
|
||||
// Matches tags like "something-abcdefg" (only chars before dash and exactly 7 characters after the dash)
|
||||
shortCommitHashSuffixPattern = regexp.MustCompile(`^[a-zA-Z]+-[a-zA-Z0-9]{7}$`)
|
||||
// Matches tags like "v1.2.3", "V1.2.3, #1.2.3, $1.2.3, etc"
|
||||
leadingSymbolPattern = regexp.MustCompile(`^version|Version|[vV]|^[^a-zA-Z0-9]+`)
|
||||
// Valid SemVer format (Major.Minor.Patch)
|
||||
semVerPattern = regexp.MustCompile(`^(\d+)\.(\d+)\.(\d+)$`)
|
||||
// Matches tags like "RELEASE.2023-11-20T22-40-07Z"
|
||||
releasePattern = regexp.MustCompile(`^RELEASE\.[0-9]{4}-[0-9]{2}-[0-9]{2}T`)
|
||||
// Matches tags like "x64-1.2.3" and "arm64-1.2.3" followed by a numeric version
|
||||
archPattern = regexp.MustCompile(`^[a-zA-Z0-9]+-[0-9]+\.[0-9]+`)
|
||||
// Matches tags like "latest-2023-12-18"
|
||||
prefixYearMonthDayPattern = regexp.MustCompile(`^[a-zA-Z0-9]+-[0-9]{4}-[0-9]{2}-[0-9]{2}$`)
|
||||
// Matches dates like "2023-11-15" and "2022-04"
|
||||
yearMonthDayPattern = regexp.MustCompile(`^[0-9]{4}-[0-9]{2}(-[0-9]{2})?$`)
|
||||
// Matches tags like "1.2.3.4" "1.2" and "1"
|
||||
incompleteSemVerPattern = regexp.MustCompile(`^[0-9]+(\.[0-9]+)*$`)
|
||||
// Matches tags like "something-abcdefg" (only chars before dash and exactly 7 characters after the dash)
|
||||
shortCommitHashSuffixPattern = regexp.MustCompile(`^[a-zA-Z]+-[a-zA-Z0-9]{7}$`)
|
||||
// Matches tags like "v1.2.3", "V1.2.3, #1.2.3, $1.2.3, etc"
|
||||
leadingSymbolPattern = regexp.MustCompile(`^version|Version|[vV]|^[^a-zA-Z0-9]+`)
|
||||
)
|
||||
|
||||
func CleanTag(tag string) (string, error) {
|
||||
tag = strings.TrimSpace(tag)
|
||||
tag = strings.TrimSpace(tag)
|
||||
|
||||
if tag == "" {
|
||||
return "", fmt.Errorf("tag is empty")
|
||||
}
|
||||
if tag == "" {
|
||||
return "", fmt.Errorf("tag is empty")
|
||||
}
|
||||
|
||||
// Do basic cleaning
|
||||
tag = cleanSha(tag)
|
||||
tag = cleanLeadingSymbol(tag)
|
||||
// Do basic cleaning
|
||||
tag = cleanSha(tag)
|
||||
tag = cleanLeadingSymbol(tag)
|
||||
|
||||
// Return early if the tag is already in SemVer format
|
||||
if semVerPattern.MatchString(tag) {
|
||||
return tag, nil
|
||||
}
|
||||
// Return early if the tag is already in SemVer format
|
||||
if semVerPattern.MatchString(tag) {
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case releasePattern.MatchString(tag):
|
||||
tag = cleanRelease(tag)
|
||||
case archPattern.MatchString(tag):
|
||||
tag = cleanArch(tag)
|
||||
case prefixYearMonthDayPattern.MatchString(tag):
|
||||
tag = cleanPrefixYearMonthDay(tag)
|
||||
case yearMonthDayPattern.MatchString(tag):
|
||||
tag = cleanYearMonthDay(tag)
|
||||
case incompleteSemVerPattern.MatchString(tag):
|
||||
tag = cleanIncompleteSemVer(tag)
|
||||
case shortCommitHashSuffixPattern.MatchString(tag):
|
||||
tag = keepShortCommitHashSuffix(tag)
|
||||
case leadingSymbolPattern.MatchString(tag):
|
||||
tag = cleanLeadingSymbol(tag)
|
||||
}
|
||||
switch {
|
||||
case releasePattern.MatchString(tag):
|
||||
tag = cleanRelease(tag)
|
||||
case archPattern.MatchString(tag):
|
||||
tag = cleanArch(tag)
|
||||
case prefixYearMonthDayPattern.MatchString(tag):
|
||||
tag = cleanPrefixYearMonthDay(tag)
|
||||
case yearMonthDayPattern.MatchString(tag):
|
||||
tag = cleanYearMonthDay(tag)
|
||||
case incompleteSemVerPattern.MatchString(tag):
|
||||
tag = cleanIncompleteSemVer(tag)
|
||||
case shortCommitHashSuffixPattern.MatchString(tag):
|
||||
tag = keepShortCommitHashSuffix(tag)
|
||||
case leadingSymbolPattern.MatchString(tag):
|
||||
tag = cleanLeadingSymbol(tag)
|
||||
}
|
||||
|
||||
// If string contains `-` the second part is usually
|
||||
// either a commit hash or things like "debian" or "alpine"
|
||||
// Make sure the first part is some kind of versioning and strip the rest
|
||||
if strings.Contains(tag, "-") {
|
||||
split := strings.Split(tag, "-")
|
||||
switch {
|
||||
case semVerPattern.MatchString(split[0]):
|
||||
tag = split[0]
|
||||
case incompleteSemVerPattern.MatchString(split[0]):
|
||||
tag = split[0]
|
||||
}
|
||||
}
|
||||
// If string contains `-` the second part is usually
|
||||
// either a commit hash or things like "debian" or "alpine"
|
||||
// Make sure the first part is some kind of versioning and strip the rest
|
||||
if strings.Contains(tag, "-") {
|
||||
split := strings.Split(tag, "-")
|
||||
switch {
|
||||
case semVerPattern.MatchString(split[0]):
|
||||
tag = split[0]
|
||||
case incompleteSemVerPattern.MatchString(split[0]):
|
||||
tag = split[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Re-check for incomplete SemVer after cleaning
|
||||
if incompleteSemVerPattern.MatchString(tag) {
|
||||
tag = cleanIncompleteSemVer(tag)
|
||||
}
|
||||
// Re-check for incomplete SemVer after cleaning
|
||||
if incompleteSemVerPattern.MatchString(tag) {
|
||||
tag = cleanIncompleteSemVer(tag)
|
||||
}
|
||||
|
||||
if err := checkValidLabelValue(tag); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := checkValidLabelValue(tag); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !semVerPattern.MatchString(tag) {
|
||||
log.Warn().Msgf("Could not produce a valid SemVer tag for tag [%s]", tag)
|
||||
}
|
||||
if !semVerPattern.MatchString(tag) {
|
||||
log.Warn().Msgf("Could not produce a valid SemVer tag for tag [%s]", tag)
|
||||
}
|
||||
|
||||
// Build and return the updated SemVer string
|
||||
return tag, nil
|
||||
// Build and return the updated SemVer string
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func Clean(tag string) error {
|
||||
|
||||
newTag, err := CleanTag(tag)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msgf("Failed to clean tag [%s]", tag)
|
||||
}
|
||||
newTag, err := CleanTag(tag)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msgf("Failed to clean tag [%s]", tag)
|
||||
}
|
||||
|
||||
log.Info().Msgf("Tag [%s] cleaned to [%s]", tag, newTag)
|
||||
return nil
|
||||
log.Info().Msgf("Tag [%s] cleaned to [%s]", tag, newTag)
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkValidLabelValue(tag string) error {
|
||||
if errs := validation.IsValidLabelValue(tag); len(errs) > 0 {
|
||||
return fmt.Errorf("tag [%s] is not valid for label use. error: %s", tag, (strings.Join(errs, ", ")))
|
||||
}
|
||||
return nil
|
||||
if errs := validation.IsValidLabelValue(tag); len(errs) > 0 {
|
||||
return fmt.Errorf("tag [%s] is not valid for label use. error: %s", tag, (strings.Join(errs, ", ")))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// keepShortCommitHashSuffix keeps the last 7 characters of a tag
|
||||
// eg "something-abcdefg" -> "abcdefg"
|
||||
func keepShortCommitHashSuffix(tag string) string {
|
||||
return strings.Split(tag, "-")[1]
|
||||
return strings.Split(tag, "-")[1]
|
||||
}
|
||||
|
||||
// cleanRelease Transforms release pattern format
|
||||
// eg "RELEASE.2023-11-20T22-40-07Z" -> "2023.11.20"
|
||||
func cleanRelease(tag string) string {
|
||||
tag = strings.Split(tag, ".")[1]
|
||||
tag = strings.Split(tag, "T")[0]
|
||||
tag = strings.ReplaceAll(tag, "-", ".")
|
||||
tag = strings.Split(tag, ".")[1]
|
||||
tag = strings.Split(tag, "T")[0]
|
||||
tag = strings.ReplaceAll(tag, "-", ".")
|
||||
|
||||
return tag
|
||||
return tag
|
||||
}
|
||||
|
||||
// cleanArch removes arch prefixes
|
||||
// eg "x64-1.2.3" -> "1.2.3"
|
||||
func cleanArch(tag string) string {
|
||||
tag = strings.Split(tag, "-")[1]
|
||||
tag = strings.Split(tag, "-")[1]
|
||||
|
||||
return tag
|
||||
return tag
|
||||
}
|
||||
|
||||
// cleanYearMonthDay Transforms date versions
|
||||
// eg "2023-11-15" -> "2023.11.15" and "2022-04" -> "2022.4"
|
||||
func cleanYearMonthDay(tag string) string {
|
||||
tag = strings.ReplaceAll(tag, "-", ".")
|
||||
parts := strings.Split(tag, ".")
|
||||
for idx := range parts {
|
||||
parts[idx] = strings.TrimPrefix(parts[idx], "0")
|
||||
}
|
||||
for len(parts) < 3 {
|
||||
parts = append(parts, "0")
|
||||
}
|
||||
tag = strings.Join(parts, ".")
|
||||
tag = strings.ReplaceAll(tag, "-", ".")
|
||||
parts := strings.Split(tag, ".")
|
||||
for idx := range parts {
|
||||
parts[idx] = strings.TrimPrefix(parts[idx], "0")
|
||||
}
|
||||
for len(parts) < 3 {
|
||||
parts = append(parts, "0")
|
||||
}
|
||||
tag = strings.Join(parts, ".")
|
||||
|
||||
return tag
|
||||
return tag
|
||||
}
|
||||
|
||||
// cleanIncompleteSemVer Transforms incomplete SemVer strings
|
||||
// eg "1.2" -> "1.2.0" and "1" -> "1.0.0"
|
||||
// versions with more parts are left as-is
|
||||
func cleanIncompleteSemVer(tag string) string {
|
||||
parts := strings.Split(tag, ".")
|
||||
switch {
|
||||
case len(parts) == 2:
|
||||
tag = tag + ".0"
|
||||
case len(parts) == 1:
|
||||
tag = tag + ".0.0"
|
||||
}
|
||||
parts := strings.Split(tag, ".")
|
||||
switch {
|
||||
case len(parts) == 2:
|
||||
tag = tag + ".0"
|
||||
case len(parts) == 1:
|
||||
tag = tag + ".0.0"
|
||||
}
|
||||
|
||||
return tag
|
||||
return tag
|
||||
}
|
||||
|
||||
// cleanLeadingSymbol Trims leading 'v' or non-alphanumeric characters
|
||||
// e.g "v1.2.3" -> "1.2.3"
|
||||
func cleanLeadingSymbol(tag string) string {
|
||||
return leadingSymbolPattern.ReplaceAllString(tag, "")
|
||||
return leadingSymbolPattern.ReplaceAllString(tag, "")
|
||||
}
|
||||
|
||||
// cleanSha Strips everything after '@'
|
||||
// e.g "v1.2.3@sha256:abc123" -> "v1.2.3"
|
||||
func cleanSha(tag string) string {
|
||||
return strings.Split(tag, "@")[0]
|
||||
return strings.Split(tag, "@")[0]
|
||||
}
|
||||
|
||||
// cleanPrefixYearMonthDay Transforms date versions with prefix
|
||||
// eg "latest-2023-12-18" -> "2023.12.18"
|
||||
func cleanPrefixYearMonthDay(tag string) string {
|
||||
calVer := strings.Split(tag, "-")[1:]
|
||||
tag = strings.Join(calVer, ".")
|
||||
calVer := strings.Split(tag, "-")[1:]
|
||||
tag = strings.Join(calVer, ".")
|
||||
|
||||
return tag
|
||||
return tag
|
||||
}
|
||||
|
||||
@@ -1,277 +1,277 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type args struct {
|
||||
tag string
|
||||
tag string
|
||||
}
|
||||
type testdata struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}
|
||||
|
||||
func TestCleanTag(t *testing.T) {
|
||||
tests := []testdata{
|
||||
// No match with any pattern tests
|
||||
{
|
||||
name: "Test valid SemVer format",
|
||||
args: args{
|
||||
tag: "1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test pattern that cannot be converted to SemVer",
|
||||
args: args{
|
||||
tag: "latest",
|
||||
},
|
||||
want: "latest",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test empty tag",
|
||||
args: args{
|
||||
tag: "",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test tag with only whitespace",
|
||||
args: args{
|
||||
tag: " ",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test full tag with digest",
|
||||
args: args{
|
||||
tag: "1.2.3@sha256:abc123",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test tag with longer version and `-suffix`",
|
||||
args: args{
|
||||
tag: "1.2.3.4-suffix",
|
||||
},
|
||||
want: "1.2.3.4",
|
||||
},
|
||||
{
|
||||
name: "Test tag with semver and `-suffix`",
|
||||
args: args{
|
||||
tag: "1.2.3-abc12367",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test tag with calver and `-suffix`",
|
||||
args: args{
|
||||
tag: "2023.11.2-abc12367",
|
||||
},
|
||||
want: "2023.11.2",
|
||||
},
|
||||
{
|
||||
name: "Test with invalid label format",
|
||||
args: args{
|
||||
tag: strings.Repeat("a", 300),
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
// cleanSha tests
|
||||
{
|
||||
name: "Test cleanSha",
|
||||
args: args{
|
||||
tag: "1.2.3@sha256:abc123",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
// cleanLeadingSymbol tests
|
||||
{
|
||||
name: "Test cleanLeadingSymbol ($)",
|
||||
args: args{
|
||||
tag: "$1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanLeadingSymbol (v)",
|
||||
args: args{
|
||||
tag: "v1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanLeadingSymbol (version)",
|
||||
args: args{
|
||||
tag: "version-a78f38c1",
|
||||
},
|
||||
want: "a78f38c1",
|
||||
},
|
||||
// keepShortCommitHashSuffix tests
|
||||
{
|
||||
name: "Test keepShortCommitHashSuffix (something-hash)",
|
||||
args: args{
|
||||
tag: "something-abcd123",
|
||||
},
|
||||
want: "abcd123",
|
||||
},
|
||||
{
|
||||
name: "Test keepShortCommitHashSuffix (version-hash)",
|
||||
args: args{
|
||||
tag: "version-abcd123",
|
||||
},
|
||||
want: "abcd123",
|
||||
},
|
||||
// cleanIncompleteSemVer tests
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (2 parts)",
|
||||
args: args{
|
||||
tag: "1.2",
|
||||
},
|
||||
want: "1.2.0",
|
||||
},
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (1 part)",
|
||||
args: args{
|
||||
tag: "1",
|
||||
},
|
||||
want: "1.0.0",
|
||||
},
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (more than 3 parts)",
|
||||
args: args{
|
||||
tag: "1.2.3.4.5",
|
||||
},
|
||||
want: "1.2.3.4.5",
|
||||
},
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (with suffix)",
|
||||
args: args{
|
||||
tag: "2.440-jdk17",
|
||||
},
|
||||
want: "2.440.0",
|
||||
},
|
||||
// cleanYearMonthDay tests
|
||||
{
|
||||
name: "Test cleanYearMonthDay (year-month-day)",
|
||||
args: args{
|
||||
tag: "2023-11-15",
|
||||
},
|
||||
want: "2023.11.15",
|
||||
},
|
||||
{
|
||||
name: "Test cleanYearMonthDay (year-month)",
|
||||
args: args{
|
||||
tag: "2022-04",
|
||||
},
|
||||
want: "2022.4.0",
|
||||
},
|
||||
{
|
||||
name: "Test cleanYearMonthDay (with prefix)",
|
||||
args: args{
|
||||
tag: "latest-2023-12-18",
|
||||
},
|
||||
want: "2023.12.18",
|
||||
},
|
||||
// cleanPrefix tests
|
||||
{
|
||||
name: "Test cleanPrefix (random prefix)",
|
||||
args: args{
|
||||
tag: "abc123-v1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanPrefix (version prefix)",
|
||||
args: args{
|
||||
tag: "version-1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
// cleanArch tests
|
||||
{
|
||||
name: "Test cleanArch",
|
||||
args: args{
|
||||
tag: "x64-1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
// cleanRelease tests
|
||||
{
|
||||
name: "Test cleanRelease",
|
||||
args: args{
|
||||
tag: "RELEASE.2023-11-20T22-40-07Z",
|
||||
},
|
||||
want: "2023.11.20",
|
||||
},
|
||||
// cleanStupidSemVerLike tests
|
||||
{
|
||||
name: "Test cleanStupidSemVerLike",
|
||||
args: args{
|
||||
tag: "v.1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanStupidSemVerLike (2)",
|
||||
args: args{
|
||||
tag: "V.1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
}
|
||||
tests := []testdata{
|
||||
// No match with any pattern tests
|
||||
{
|
||||
name: "Test valid SemVer format",
|
||||
args: args{
|
||||
tag: "1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test pattern that cannot be converted to SemVer",
|
||||
args: args{
|
||||
tag: "latest",
|
||||
},
|
||||
want: "latest",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test empty tag",
|
||||
args: args{
|
||||
tag: "",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test tag with only whitespace",
|
||||
args: args{
|
||||
tag: " ",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test full tag with digest",
|
||||
args: args{
|
||||
tag: "1.2.3@sha256:abc123",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test tag with longer version and `-suffix`",
|
||||
args: args{
|
||||
tag: "1.2.3.4-suffix",
|
||||
},
|
||||
want: "1.2.3.4",
|
||||
},
|
||||
{
|
||||
name: "Test tag with semver and `-suffix`",
|
||||
args: args{
|
||||
tag: "1.2.3-abc12367",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test tag with calver and `-suffix`",
|
||||
args: args{
|
||||
tag: "2023.11.2-abc12367",
|
||||
},
|
||||
want: "2023.11.2",
|
||||
},
|
||||
{
|
||||
name: "Test with invalid label format",
|
||||
args: args{
|
||||
tag: strings.Repeat("a", 300),
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
// cleanSha tests
|
||||
{
|
||||
name: "Test cleanSha",
|
||||
args: args{
|
||||
tag: "1.2.3@sha256:abc123",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
// cleanLeadingSymbol tests
|
||||
{
|
||||
name: "Test cleanLeadingSymbol ($)",
|
||||
args: args{
|
||||
tag: "$1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanLeadingSymbol (v)",
|
||||
args: args{
|
||||
tag: "v1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanLeadingSymbol (version)",
|
||||
args: args{
|
||||
tag: "version-a78f38c1",
|
||||
},
|
||||
want: "a78f38c1",
|
||||
},
|
||||
// keepShortCommitHashSuffix tests
|
||||
{
|
||||
name: "Test keepShortCommitHashSuffix (something-hash)",
|
||||
args: args{
|
||||
tag: "something-abcd123",
|
||||
},
|
||||
want: "abcd123",
|
||||
},
|
||||
{
|
||||
name: "Test keepShortCommitHashSuffix (version-hash)",
|
||||
args: args{
|
||||
tag: "version-abcd123",
|
||||
},
|
||||
want: "abcd123",
|
||||
},
|
||||
// cleanIncompleteSemVer tests
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (2 parts)",
|
||||
args: args{
|
||||
tag: "1.2",
|
||||
},
|
||||
want: "1.2.0",
|
||||
},
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (1 part)",
|
||||
args: args{
|
||||
tag: "1",
|
||||
},
|
||||
want: "1.0.0",
|
||||
},
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (more than 3 parts)",
|
||||
args: args{
|
||||
tag: "1.2.3.4.5",
|
||||
},
|
||||
want: "1.2.3.4.5",
|
||||
},
|
||||
{
|
||||
name: "Test cleanIncompleteSemVer (with suffix)",
|
||||
args: args{
|
||||
tag: "2.440-jdk17",
|
||||
},
|
||||
want: "2.440.0",
|
||||
},
|
||||
// cleanYearMonthDay tests
|
||||
{
|
||||
name: "Test cleanYearMonthDay (year-month-day)",
|
||||
args: args{
|
||||
tag: "2023-11-15",
|
||||
},
|
||||
want: "2023.11.15",
|
||||
},
|
||||
{
|
||||
name: "Test cleanYearMonthDay (year-month)",
|
||||
args: args{
|
||||
tag: "2022-04",
|
||||
},
|
||||
want: "2022.4.0",
|
||||
},
|
||||
{
|
||||
name: "Test cleanYearMonthDay (with prefix)",
|
||||
args: args{
|
||||
tag: "latest-2023-12-18",
|
||||
},
|
||||
want: "2023.12.18",
|
||||
},
|
||||
// cleanPrefix tests
|
||||
{
|
||||
name: "Test cleanPrefix (random prefix)",
|
||||
args: args{
|
||||
tag: "abc123-v1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanPrefix (version prefix)",
|
||||
args: args{
|
||||
tag: "version-1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
// cleanArch tests
|
||||
{
|
||||
name: "Test cleanArch",
|
||||
args: args{
|
||||
tag: "x64-1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
// cleanRelease tests
|
||||
{
|
||||
name: "Test cleanRelease",
|
||||
args: args{
|
||||
tag: "RELEASE.2023-11-20T22-40-07Z",
|
||||
},
|
||||
want: "2023.11.20",
|
||||
},
|
||||
// cleanStupidSemVerLike tests
|
||||
{
|
||||
name: "Test cleanStupidSemVerLike",
|
||||
args: args{
|
||||
tag: "v.1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
{
|
||||
name: "Test cleanStupidSemVerLike (2)",
|
||||
args: args{
|
||||
tag: "V.1.2.3",
|
||||
},
|
||||
want: "1.2.3",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
got, err := CleanTag(tt.args.tag)
|
||||
// If we expected an error, but didn't get one, fail the test
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CleanTag() error = %v, wantErr %t", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("CleanTag() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
got, err := CleanTag(tt.args.tag)
|
||||
// If we expected an error, but didn't get one, fail the test
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("CleanTag() error = %v, wantErr %t", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("CleanTag() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestCheckValidLabelValue(t *testing.T) {
|
||||
tests := []testdata{
|
||||
{
|
||||
name: "Test invalid label format",
|
||||
args: args{
|
||||
tag: "1.2.3@sha256:abc123",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test valid label format",
|
||||
args: args{
|
||||
tag: "1.2.3",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
tests := []testdata{
|
||||
{
|
||||
name: "Test invalid label format",
|
||||
args: args{
|
||||
tag: "1.2.3@sha256:abc123",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test valid label format",
|
||||
args: args{
|
||||
tag: "1.2.3",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
err := checkValidLabelValue(tt.args.tag)
|
||||
// If we expected an error, but didn't get one, fail the test
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("checkValidLabelValue() error = %v, wantErr %t", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
err := checkValidLabelValue(tt.args.tag)
|
||||
// If we expected an error, but didn't get one, fail the test
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("checkValidLabelValue() error = %v, wantErr %t", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,146 +1,146 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/knadh/koanf/parsers/yaml"
|
||||
"github.com/knadh/koanf/providers/file"
|
||||
"github.com/knadh/koanf/v2"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/knadh/koanf/parsers/yaml"
|
||||
"github.com/knadh/koanf/providers/file"
|
||||
"github.com/knadh/koanf/v2"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Images represents the structure of values.yaml.
|
||||
type Images struct {
|
||||
ImagesMap map[string]ImageDetails
|
||||
K *koanf.Koanf
|
||||
ImagesMap map[string]ImageDetails
|
||||
K *koanf.Koanf
|
||||
}
|
||||
|
||||
// ImageDetails represents details for each image.
|
||||
type ImageDetails struct {
|
||||
Repository string `yaml:"repository"`
|
||||
Tag string `yaml:"tag"`
|
||||
Version string
|
||||
Link string
|
||||
// Add other fields as needed
|
||||
Repository string `yaml:"repository"`
|
||||
Tag string `yaml:"tag"`
|
||||
Version string
|
||||
Link string
|
||||
// Add other fields as needed
|
||||
}
|
||||
|
||||
var imageRegex = regexp.MustCompile(`^image|[a-zA-Z0-9]+Image$`)
|
||||
|
||||
func (i *Images) LoadValuesFile(filename string) error {
|
||||
// Initialize koanf instance
|
||||
i.K = koanf.New(".")
|
||||
// Initialize koanf instance
|
||||
i.K = koanf.New(".")
|
||||
|
||||
// Load YAML file using koanf
|
||||
if err := i.K.Load(file.Provider(filename), yaml.Parser()); err != nil {
|
||||
return err
|
||||
}
|
||||
// Load YAML file using koanf
|
||||
if err := i.K.Load(file.Provider(filename), yaml.Parser()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// List only root-level keys that match the criteria
|
||||
keys := getFilteredRootLevelKeys(i.K)
|
||||
i.ImagesMap = make(map[string]ImageDetails)
|
||||
for _, key := range keys {
|
||||
// Extract relevant fields from the loaded configuration
|
||||
var img ImageDetails
|
||||
if err := i.K.Unmarshal(key, &img); err != nil {
|
||||
return err
|
||||
}
|
||||
// List only root-level keys that match the criteria
|
||||
keys := getFilteredRootLevelKeys(i.K)
|
||||
i.ImagesMap = make(map[string]ImageDetails)
|
||||
for _, key := range keys {
|
||||
// Extract relevant fields from the loaded configuration
|
||||
var img ImageDetails
|
||||
if err := i.K.Unmarshal(key, &img); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the Link field based on the repository
|
||||
img.Link = constructLink(img.Repository)
|
||||
// Set the Link field based on the repository
|
||||
img.Link = constructLink(img.Repository)
|
||||
|
||||
// Set the Version field based on the tag
|
||||
version, err := CleanTag(img.Tag)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("❌ Failed to clean tag")
|
||||
}
|
||||
// Set the Version field based on the tag
|
||||
version, err := CleanTag(img.Tag)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("❌ Failed to clean tag")
|
||||
}
|
||||
|
||||
img.Version = version
|
||||
img.Version = version
|
||||
|
||||
// Save the extracted values to the struct
|
||||
i.ImagesMap[key] = img
|
||||
}
|
||||
// Save the extracted values to the struct
|
||||
i.ImagesMap[key] = img
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFilteredRootLevelKeys(k *koanf.Koanf) []string {
|
||||
filteredKeys := []string{}
|
||||
filteredKeys := []string{}
|
||||
|
||||
// k.Raw() returns a map[string]interface{} with all the keys and their values
|
||||
// This means the keys will only be the root-level keys, we can drill into the
|
||||
// values later if we want the nested keys.
|
||||
for key := range k.Raw() {
|
||||
if key == "imageSelector" {
|
||||
log.Error().Msg("❌ Found [imageSelector] in top level keys, this is not supported.")
|
||||
continue
|
||||
}
|
||||
// Filter keys that match the regex
|
||||
if imageRegex.MatchString(key) {
|
||||
filteredKeys = append(filteredKeys, key)
|
||||
}
|
||||
}
|
||||
// k.Raw() returns a map[string]interface{} with all the keys and their values
|
||||
// This means the keys will only be the root-level keys, we can drill into the
|
||||
// values later if we want the nested keys.
|
||||
for key := range k.Raw() {
|
||||
if key == "imageSelector" {
|
||||
log.Error().Msg("❌ Found [imageSelector] in top level keys, this is not supported.")
|
||||
continue
|
||||
}
|
||||
// Filter keys that match the regex
|
||||
if imageRegex.MatchString(key) {
|
||||
filteredKeys = append(filteredKeys, key)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredKeys
|
||||
return filteredKeys
|
||||
}
|
||||
|
||||
// constructLink constructs a link based on the repository using the logic from the main function.
|
||||
func constructLink(repository string) string {
|
||||
prefix := ""
|
||||
prefix := ""
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(repository, "lscr.io/linuxserver/"):
|
||||
prefix = "https://fleet.linuxserver.io/image?name="
|
||||
repository = strings.TrimPrefix(repository, "lscr.io/")
|
||||
case strings.HasPrefix(repository, "tccr.io/tccr/"):
|
||||
prefix = "https://github.com/truecharts/containers/tree/master/apps/"
|
||||
repository = strings.TrimPrefix(repository, "tccr.io/tccr/")
|
||||
case strings.HasPrefix(repository, "mcr.microsoft.com/"):
|
||||
prefix = "https://mcr.microsoft.com/en-us/product/"
|
||||
repository = strings.TrimPrefix(repository, "mcr.microsoft.com/")
|
||||
case strings.HasPrefix(repository, "public.ecr.aws/"):
|
||||
prefix = "https://gallery.ecr.aws/"
|
||||
repository = strings.TrimPrefix(repository, "public.ecr.aws/")
|
||||
case strings.HasPrefix(repository, "ghcr.io/"):
|
||||
prefix = "https://"
|
||||
case strings.HasPrefix(repository, "quay.io/"):
|
||||
prefix = "https://"
|
||||
case strings.HasPrefix(repository, "gcr.io/"):
|
||||
prefix = "https://"
|
||||
case strings.Contains(repository, ".azurecr.io/"):
|
||||
reg := fmt.Sprintf(`%s.azurecr.io/`, strings.Split(repository, ".")[0])
|
||||
prefix = fmt.Sprintf("https://%s", reg)
|
||||
repository = strings.TrimPrefix(repository, reg)
|
||||
case strings.Contains(repository, ".ocir.io/"):
|
||||
prefix = ""
|
||||
default:
|
||||
// Docker Hub or unknown registry
|
||||
prefix = "https://hub.docker.com/r/"
|
||||
repository = strings.TrimPrefix(repository, "docker.io/")
|
||||
repository = strings.TrimPrefix(repository, "index.docker.io/")
|
||||
repository = strings.TrimPrefix(repository, "registry-1.docker.io/")
|
||||
repository = strings.TrimPrefix(repository, "registry.hub.docker.com/")
|
||||
switch {
|
||||
case strings.HasPrefix(repository, "lscr.io/linuxserver/"):
|
||||
prefix = "https://fleet.linuxserver.io/image?name="
|
||||
repository = strings.TrimPrefix(repository, "lscr.io/")
|
||||
case strings.HasPrefix(repository, "tccr.io/tccr/"):
|
||||
prefix = "https://github.com/truecharts/containers/tree/master/apps/"
|
||||
repository = strings.TrimPrefix(repository, "tccr.io/tccr/")
|
||||
case strings.HasPrefix(repository, "mcr.microsoft.com/"):
|
||||
prefix = "https://mcr.microsoft.com/en-us/product/"
|
||||
repository = strings.TrimPrefix(repository, "mcr.microsoft.com/")
|
||||
case strings.HasPrefix(repository, "public.ecr.aws/"):
|
||||
prefix = "https://gallery.ecr.aws/"
|
||||
repository = strings.TrimPrefix(repository, "public.ecr.aws/")
|
||||
case strings.HasPrefix(repository, "ghcr.io/"):
|
||||
prefix = "https://"
|
||||
case strings.HasPrefix(repository, "quay.io/"):
|
||||
prefix = "https://"
|
||||
case strings.HasPrefix(repository, "gcr.io/"):
|
||||
prefix = "https://"
|
||||
case strings.Contains(repository, ".azurecr.io/"):
|
||||
reg := fmt.Sprintf(`%s.azurecr.io/`, strings.Split(repository, ".")[0])
|
||||
prefix = fmt.Sprintf("https://%s", reg)
|
||||
repository = strings.TrimPrefix(repository, reg)
|
||||
case strings.Contains(repository, ".ocir.io/"):
|
||||
prefix = ""
|
||||
default:
|
||||
// Docker Hub or unknown registry
|
||||
prefix = "https://hub.docker.com/r/"
|
||||
repository = strings.TrimPrefix(repository, "docker.io/")
|
||||
repository = strings.TrimPrefix(repository, "index.docker.io/")
|
||||
repository = strings.TrimPrefix(repository, "registry-1.docker.io/")
|
||||
repository = strings.TrimPrefix(repository, "registry.hub.docker.com/")
|
||||
|
||||
// Check for Docker Official Image
|
||||
if strings.Count(repository, "/") == 0 || strings.HasPrefix(repository, "library/") {
|
||||
prefix = "https://hub.docker.com/_/"
|
||||
repository = strings.TrimPrefix(repository, "library/")
|
||||
}
|
||||
// Check for Docker Official Image
|
||||
if strings.Count(repository, "/") == 0 || strings.HasPrefix(repository, "library/") {
|
||||
prefix = "https://hub.docker.com/_/"
|
||||
repository = strings.TrimPrefix(repository, "library/")
|
||||
}
|
||||
|
||||
// Avoid creating a bad link if the image name has more than 1 slash
|
||||
slashes := strings.Count(repository, "/")
|
||||
if slashes > 1 {
|
||||
prefix = ""
|
||||
log.Warn().Msgf("WARNING: Could not determine source repository url for [%s]", repository)
|
||||
}
|
||||
}
|
||||
// Avoid creating a bad link if the image name has more than 1 slash
|
||||
slashes := strings.Count(repository, "/")
|
||||
if slashes > 1 {
|
||||
prefix = ""
|
||||
log.Warn().Msgf("WARNING: Could not determine source repository url for [%s]", repository)
|
||||
}
|
||||
}
|
||||
|
||||
if prefix == "" {
|
||||
log.Warn().Msgf("WARNING: Could not determine source repository url for [%s]", repository)
|
||||
return ""
|
||||
}
|
||||
if prefix == "" {
|
||||
log.Warn().Msgf("WARNING: Could not determine source repository url for [%s]", repository)
|
||||
return ""
|
||||
}
|
||||
|
||||
containerURL := fmt.Sprintf("%s%s", prefix, repository)
|
||||
return containerURL
|
||||
containerURL := fmt.Sprintf("%s%s", prefix, repository)
|
||||
return containerURL
|
||||
}
|
||||
|
||||
@@ -1,171 +1,171 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadValuesFile(t *testing.T) {
|
||||
type TestData struct {
|
||||
name string
|
||||
valuesFile string
|
||||
expected map[string]ImageDetails
|
||||
wantErr bool
|
||||
}
|
||||
testDataPath := "../../testdata/values_yaml"
|
||||
tests := []TestData{
|
||||
{
|
||||
name: "Test malformed file",
|
||||
valuesFile: "malformedValues.yaml",
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test empty file",
|
||||
valuesFile: "emptyValues.yaml",
|
||||
expected: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test single image file",
|
||||
valuesFile: "singleImageValues.yaml",
|
||||
expected: map[string]ImageDetails{
|
||||
"image": {
|
||||
Repository: "nginx",
|
||||
Tag: "1.15.8",
|
||||
Link: "https://hub.docker.com/_/nginx",
|
||||
Version: "1.15.8",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Test multiple image file",
|
||||
valuesFile: "multiImageValues.yaml",
|
||||
expected: map[string]ImageDetails{
|
||||
"image": {
|
||||
Repository: "author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub1Image": {
|
||||
Repository: "docker.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub2Image": {
|
||||
Repository: "index.docker.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub3Image": {
|
||||
Repository: "registry-1.docker.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub4Image": {
|
||||
Repository: "registry.hub.docker.com/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub5Image": {
|
||||
Repository: "image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/_/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub6Image": {
|
||||
Repository: "library/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/_/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"lscrImage": {
|
||||
Repository: "lscr.io/linuxserver/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://fleet.linuxserver.io/image?name=linuxserver/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"tccrImage": {
|
||||
Repository: "tccr.io/tccr/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://github.com/truecharts/containers/tree/master/apps/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"mcrImage": {
|
||||
Repository: "mcr.microsoft.com/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://mcr.microsoft.com/en-us/product/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"ecrImage": {
|
||||
Repository: "public.ecr.aws/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://gallery.ecr.aws/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"ghcrImage": {
|
||||
Repository: "ghcr.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://ghcr.io/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"quayImage": {
|
||||
Repository: "quay.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://quay.io/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"gcrImage": {
|
||||
Repository: "gcr.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://gcr.io/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"azurecrImage": {
|
||||
Repository: "author.azurecr.io/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://author.azurecr.io/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"ocirImage": {
|
||||
Repository: "author.ocir.io/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"unknownImage": {
|
||||
Repository: "unknown.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
type TestData struct {
|
||||
name string
|
||||
valuesFile string
|
||||
expected map[string]ImageDetails
|
||||
wantErr bool
|
||||
}
|
||||
testDataPath := "../../testdata/values_yaml"
|
||||
tests := []TestData{
|
||||
{
|
||||
name: "Test malformed file",
|
||||
valuesFile: "malformedValues.yaml",
|
||||
expected: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Test empty file",
|
||||
valuesFile: "emptyValues.yaml",
|
||||
expected: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test single image file",
|
||||
valuesFile: "singleImageValues.yaml",
|
||||
expected: map[string]ImageDetails{
|
||||
"image": {
|
||||
Repository: "nginx",
|
||||
Tag: "1.15.8",
|
||||
Link: "https://hub.docker.com/_/nginx",
|
||||
Version: "1.15.8",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Test multiple image file",
|
||||
valuesFile: "multiImageValues.yaml",
|
||||
expected: map[string]ImageDetails{
|
||||
"image": {
|
||||
Repository: "author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub1Image": {
|
||||
Repository: "docker.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub2Image": {
|
||||
Repository: "index.docker.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub3Image": {
|
||||
Repository: "registry-1.docker.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub4Image": {
|
||||
Repository: "registry.hub.docker.com/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/r/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub5Image": {
|
||||
Repository: "image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/_/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"dockerHub6Image": {
|
||||
Repository: "library/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://hub.docker.com/_/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"lscrImage": {
|
||||
Repository: "lscr.io/linuxserver/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://fleet.linuxserver.io/image?name=linuxserver/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"tccrImage": {
|
||||
Repository: "tccr.io/tccr/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://github.com/truecharts/containers/tree/master/apps/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"mcrImage": {
|
||||
Repository: "mcr.microsoft.com/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://mcr.microsoft.com/en-us/product/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"ecrImage": {
|
||||
Repository: "public.ecr.aws/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://gallery.ecr.aws/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"ghcrImage": {
|
||||
Repository: "ghcr.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://ghcr.io/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"quayImage": {
|
||||
Repository: "quay.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://quay.io/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"gcrImage": {
|
||||
Repository: "gcr.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://gcr.io/author/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"azurecrImage": {
|
||||
Repository: "author.azurecr.io/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "https://author.azurecr.io/image",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"ocirImage": {
|
||||
Repository: "author.ocir.io/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
"unknownImage": {
|
||||
Repository: "unknown.io/author/image",
|
||||
Tag: "1.0.0",
|
||||
Link: "",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var images Images
|
||||
err := images.LoadValuesFile(fmt.Sprintf("%s/%s", testDataPath, tt.valuesFile))
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("LoadValuesFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var images Images
|
||||
err := images.LoadValuesFile(fmt.Sprintf("%s/%s", testDataPath, tt.valuesFile))
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("LoadValuesFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if tt.expected == nil && len(images.ImagesMap) > 0 {
|
||||
t.Errorf("LoadValuesFile() expected = %+v, got %+v", tt.expected, images.ImagesMap)
|
||||
}
|
||||
if tt.expected == nil && len(images.ImagesMap) > 0 {
|
||||
t.Errorf("LoadValuesFile() expected = %+v, got %+v", tt.expected, images.ImagesMap)
|
||||
}
|
||||
|
||||
if tt.expected != nil {
|
||||
if !reflect.DeepEqual(images.ImagesMap, tt.expected) {
|
||||
t.Errorf("LoadValuesFile() expected = %+v, got %+v", tt.expected, images.ImagesMap)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if tt.expected != nil {
|
||||
if !reflect.DeepEqual(images.ImagesMap, tt.expected) {
|
||||
t.Errorf("LoadValuesFile() expected = %+v, got %+v", tt.expected, images.ImagesMap)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user