Skip to content

Commit

Permalink
add: Support multiple version numbers pattern #11 (#12)
Browse files Browse the repository at this point in the history
add: Support multiple version numbers pattern #11
  • Loading branch information
bitofsky authored Sep 28, 2021
1 parent af1e4b6 commit a9ab1b3
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 97 deletions.
81 changes: 0 additions & 81 deletions remoteRegistry/docker/docker_test.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,10 @@
package docker

import (
"fmt"
"os"
"strings"
"testing"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/joho/godotenv"
)

type testenv struct {
host string
image string
tag string
auth string
username string
password string
}

var privateenv = testenv{}
var ecrenv = testenv{}

func init() {
if err := godotenv.Load("../../.env"); err != nil {
fmt.Printf("error loading .env file - %s", err)
}

privateenv.host = os.Getenv("TEST_DOCKER_PRIVATE_HOST")
privateenv.image = os.Getenv("TEST_DOCKER_PRIVATE_IMAGE")
privateenv.tag = os.Getenv("TEST_DOCKER_PRIVATE_TAG")
privateenv.auth = os.Getenv("TEST_DOCKER_PRIVATE_AUTH")
privateenv.username = os.Getenv("TEST_DOCKER_PRIVATE_USERNAME")
privateenv.password = os.Getenv("TEST_DOCKER_PRIVATE_PASSWORD")

ecrenv.host = os.Getenv("TEST_DOCKER_ECR_HOST")
ecrenv.image = os.Getenv("TEST_DOCKER_ECR_IMAGE")
ecrenv.tag = os.Getenv("TEST_DOCKER_ECR_TAG")
}

func TestGetImageStringAsterisk(t *testing.T) {
r := NewRemoteRegistry()

Expand All @@ -50,50 +16,3 @@ func TestGetImageStringAsterisk(t *testing.T) {
t.Logf("success: %s", s)
}
}

func TestGetImageFromPrivateRegistry(t *testing.T) {
if os.Getenv("TEST_DOCKER_PRIVATE_SKIP") != "" {
t.Log("skipping test")
return
}

r := NewRemoteRegistry()

if privateenv.auth != "" {
r.WithImageAuthMap(map[string]authn.Authenticator{
privateenv.host: NewPrivateAuthenticatorWithAuth(privateenv.host, privateenv.auth),
})
} else if privateenv.username != "" && privateenv.password != "" {
r.WithImageAuthMap(map[string]authn.Authenticator{
privateenv.host: NewPrivateAuthenticator(privateenv.host, privateenv.username, privateenv.password),
})
} else {
t.Fatalf("env not set")
}

if s, err := r.GetImageString(privateenv.host+"/"+privateenv.image, privateenv.tag, "linux/amd64"); err != nil {
t.Fatalf("err: %v", err)
} else {
t.Logf("success: %s", s)
}
}

func TestGetImageFromECR(t *testing.T) {

if os.Getenv("TEST_DOCKER_ECR_SKIP") != "" {
t.Log("skipping test")
return
}

r := NewRemoteRegistry()

if ecrenv.host == "" || ecrenv.image == "" || ecrenv.tag == "" {
t.Fatalf("env not set")
}

if s, err := r.GetImageString(ecrenv.host+"/"+ecrenv.image, ecrenv.tag, "linux/amd64"); err != nil {
t.Fatalf("err: %v, %+v", err, ecrenv)
} else {
t.Logf("success: %s", s)
}
}
47 changes: 47 additions & 0 deletions remoteRegistry/docker/ecr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package docker

import (
"fmt"
"os"
"testing"

"github.com/joho/godotenv"
)

type testEcrEnv struct {
host string
image string
tag string
}

var ecrenv = testEcrEnv{}

func init() {
if err := godotenv.Load("../../.env"); err != nil {
fmt.Printf("error loading .env file - %s", err)
}

ecrenv.host = os.Getenv("TEST_DOCKER_ECR_HOST")
ecrenv.image = os.Getenv("TEST_DOCKER_ECR_IMAGE")
ecrenv.tag = os.Getenv("TEST_DOCKER_ECR_TAG")
}

func TestGetImageFromECR(t *testing.T) {

if os.Getenv("TEST_DOCKER_ECR_SKIP") != "" {
t.Log("skipping test")
return
}

r := NewRemoteRegistry()

if ecrenv.host == "" || ecrenv.image == "" || ecrenv.tag == "" {
t.Fatalf("env not set")
}

if s, err := r.GetImageString(ecrenv.host+"/"+ecrenv.image, ecrenv.tag, "linux/amd64"); err != nil {
t.Fatalf("err: %v, %+v", err, ecrenv)
} else {
t.Logf("success: %s", s)
}
}
61 changes: 61 additions & 0 deletions remoteRegistry/docker/private_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package docker

import (
"fmt"
"os"
"testing"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/joho/godotenv"
)

type testPrivateEnv struct {
host string
image string
tag string
auth string
username string
password string
}

var privateenv = testPrivateEnv{}

func init() {
if err := godotenv.Load("../../.env"); err != nil {
fmt.Printf("error loading .env file - %s", err)
}

privateenv.host = os.Getenv("TEST_DOCKER_PRIVATE_HOST")
privateenv.image = os.Getenv("TEST_DOCKER_PRIVATE_IMAGE")
privateenv.tag = os.Getenv("TEST_DOCKER_PRIVATE_TAG")
privateenv.auth = os.Getenv("TEST_DOCKER_PRIVATE_AUTH")
privateenv.username = os.Getenv("TEST_DOCKER_PRIVATE_USERNAME")
privateenv.password = os.Getenv("TEST_DOCKER_PRIVATE_PASSWORD")
}

func TestGetImageFromPrivateRegistry(t *testing.T) {
if os.Getenv("TEST_DOCKER_PRIVATE_SKIP") != "" {
t.Log("skipping test")
return
}

r := NewRemoteRegistry()

if privateenv.auth != "" {
r.WithImageAuthMap(map[string]authn.Authenticator{
privateenv.host: NewPrivateAuthenticatorWithAuth(privateenv.host, privateenv.auth),
})
} else if privateenv.username != "" && privateenv.password != "" {
r.WithImageAuthMap(map[string]authn.Authenticator{
privateenv.host: NewPrivateAuthenticator(privateenv.host, privateenv.username, privateenv.password),
})
} else {
t.Fatalf("env not set")
}

if s, err := r.GetImageString(privateenv.host+"/"+privateenv.image, privateenv.tag, "linux/amd64"); err != nil {
t.Fatalf("err: %v", err)
} else {
t.Logf("success: %s", s)
}
}
47 changes: 31 additions & 16 deletions util/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,53 @@ import (

var ErrNotFound = errors.New("not found")

// GetHighestVersionWithFilter versions는 version 목록이다.
// filter는 *(asterisk)를 숫자(\d+)로 대입하는 regexp로 변환된다.
// 예를 들어, filter가 "1.2.*"이면, 1.2.3이나 1.2.4라는 버전을 찾는다.
// 그리고 그 중 *의 위치에 해당하는 숫자가 가장 큰 버전을 반환한다.
// *은 여럿일 수 있으며 왼쪽에서 오른쪽으로 동일 위치에서 더 큰 버전을 찾는다.
// 예를 들어, filter가 "1.*.*"이면, 1.1.5와 1.2.0 중 1.2.0을 반환한다.
func GetHighestVersionWithFilter(versions []string, filter string) (string, error) {
targetTag := ""
targetVer := int64(0)
highestTag := ""
highestNumbers := []int64{}
regexString := fmt.Sprintf("^%s$", strings.Replace(regexp.QuoteMeta(filter), `\*`, `(\d+)`, -1))
patt, err := regexp.Compile(regexString)

patt, err := regexp.Compile(fmt.Sprintf("^%s$", strings.Replace(regexp.QuoteMeta(filter), "\\*", "(\\d+)", 1)))
if nil != err {
return "", err
}

for _, v := range versions {
// fmt.Println(v)
matches := patt.FindStringSubmatch(v)
for _, tag := range versions {
matches := patt.FindStringSubmatch(tag)

if len(matches) == 0 {
if tag == "" || len(matches) < 2 {
continue
}

ver, err := strconv.ParseInt(matches[1], 10, 64)
if nil != err {
continue
numbers := []int64{}

for idx, match := range matches {
if idx == 0 { // 첫번째 매치는 무시한다.
continue
}
if number, err := strconv.ParseInt(match, 10, 64); err != nil {
return "", err
} else {
numbers = append(numbers, number)
}
}

if targetVer > ver {
continue
for idx, number := range numbers { // 각 자릿수를 비교해 더 큰 값이 발견되면 교체
if idx >= len(highestNumbers) || highestNumbers[idx] <= number {
highestTag, highestNumbers = tag, numbers
break
}
}

targetTag, targetVer = v, ver
}

if targetTag == "" {
if highestTag == "" {
return "", ErrNotFound
}

return targetTag, nil
return highestTag, nil
}
39 changes: 39 additions & 0 deletions util/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package util

import (
"testing"
)

var versions []string = []string{"v1.0.0", "v1.0.1", "v1.0.2", "v1.0.9", "v1.0.10", "v1.0.11", "v2.0.99", "v2.0.9", "v3.1.999", "v3.1.998", "v4.0.999", "v4.1.0", "v5.0.0", "v6.0.0", "v6.0.1.0"}

func TestGetHighestVersionWithFilter(t *testing.T) {
if highestVersion, _ := GetHighestVersionWithFilter(versions, "v1.0.*"); highestVersion != "v1.0.11" {
t.Errorf("Expected: v1.0.11, Got: %s", highestVersion)
}

if highestVersion, _ := GetHighestVersionWithFilter(versions, "v2.0.*"); highestVersion != "v2.0.99" {
t.Errorf("Expected: v2.0.99, Got: %s", highestVersion)
}

if highestVersion, _ := GetHighestVersionWithFilter(versions, "v3.1.*"); highestVersion != "v3.1.999" {
t.Errorf("Expected: v3.1.999, Got: %s", highestVersion)
}
}

func TestGetHighestVersionWithFilterSingleVersion(t *testing.T) {
if highestVersion, _ := GetHighestVersionWithFilter(versions, "v5.*.*"); highestVersion != "v5.0.0" {
t.Errorf("Expected: v5.0.0, Got: %s", highestVersion)
}
}

func TestGetHighestVersionWithFilterMultipleAsterisk(t *testing.T) {
if highestVersion, _ := GetHighestVersionWithFilter(versions, "v4.*.*"); highestVersion != "v4.1.0" {
t.Errorf("Expected: v4.1.0, Got: %s", highestVersion)
}
}

func TestGetHighestVersionWithFilterAsteriskNotMatch(t *testing.T) {
if highestVersion, _ := GetHighestVersionWithFilter(versions, "v6.*.*"); highestVersion != "v6.0.0" {
t.Errorf("Expected: v6.0.0, Got: %s", highestVersion)
}
}

0 comments on commit a9ab1b3

Please sign in to comment.