Skip to content

Commit

Permalink
fix: add unit tests for move
Browse files Browse the repository at this point in the history
  • Loading branch information
mvanholsteijn committed Feb 15, 2023
1 parent d1fd509 commit 54f54e8
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 25 deletions.
38 changes: 28 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@
# Usage

```
fromage list [--verbose] [--format=FORMAT] [--no-header] [--only-references] [--branch=BRANCH ...] URL
fromage list [--verbose] [--format=FORMAT] [--no-header] [--only-references] [--branch=BRANCH ...] URL
fromage check [--verbose] [--format=FORMAT] [--no-header] [--only-references] [--branch=BRANCH ...] [--pin=LEVEL] URL
fromage bump [--verbose] [--dry-run] [--pin=LEVEL] --branch=BRANCH URL
fromage bump [--verbose] [--dry-run] [--pin=LEVEL] [--latest] --branch=BRANCH URL
fromage move [--verbose] [--dry-run] --from=FROM_REPOSITORY --to=TO_REPOSITORY --branch=BRANCH URL
```
# Options

# Options
```
Options:
--branch=BRANCH to inspect, defaults to all branches.
--format=FORMAT to print: text, json or yaml [default: text].
--no-header do not print header if output type is text.
--only-references output only container image references.
--pin=LEVEL pins the MAJOR or MINOR version level
--latest bump to the latest version available
--branch=BRANCH to inspect, defaults to all branches.
--format=FORMAT to print: text, json or yaml [default: text].
--no-header do not print header if output type is text.
--only-references output only container image references.
--pin=LEVEL pins the MAJOR or MINOR version level
--latest bump to the latest version available
--from=FROM_REPOSITORY from repository context
--to=TO_REPOSITORY to repository context
```

# Description
Expand Down Expand Up @@ -72,5 +75,20 @@ remote repository reference, the change will also be pushed.

Read more at [How to keep your Dockerfile container image references up-to-date](https://binx.io/blog/2021/01/30/how-to-keep-your-dockerfile-container-image-references-up-to-date/)

## moving container registry

If you need to move your container registry images from for instance docker hub to AWS Public ECR registry, type:

```
$ fromage move --verbose --from index.docker.io/library --to public.aws.ecr/docker/library --branch master [email protected]:binxio/kritis.git
2023/02/15 16:02:43 INFO: updating reference ubuntu:trusty to public.aws.ecr/docker/library/ubuntu:trusty in vendor/golang.org/x/net/http2/Dockerfile
2023/02/15 16:02:43 INFO: updating reference golang:1.13 to public.aws.ecr/docker/library/golang:1.13 in deploy/Dockerfile
2023/02/15 16:02:43 INFO: updating reference golang:1.13 to public.aws.ecr/docker/library/golang:1.13 in helm-hooks/Dockerfile
2023/02/15 16:02:43 INFO: updating reference golang:1.13 to public.aws.ecr/docker/library/golang:1.13 in helm-hooks/Dockerfile
2023/02/15 16:02:43 INFO: moved references from index.docker.io/library to public.aws.ecr/docker/library
2023/02/15 16:02:43 INFO: changes committed with 1234ef
2023/02/15 16:02:43 INFO: pushing changes to [email protected]:binxio/kritis.git
```

# Caveats
- The bump will update all container references it finds in all files
45 changes: 30 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,42 +251,57 @@ func BumpReferences(f *Fromage) error {

return nil
}
func MoveImageReferences(f *Fromage) error {
updated := false

content, err := ReadFile(f.workTree, f.dockerfile)
if err != nil {
return err
}

func moveImageReferences(content []byte, filename string, verbose bool, from, to string) ([]byte, bool, error) {
updated := false
refs := ExtractFromStatements(content)
for _, refString := range refs {
ref, err := name.ParseReference(refString)
fullRef := ref.Name()

if err != nil {
log.Fatalf("failed to parse %s into a reference, %v", refString, err)
return nil, false, err
}

if !strings.HasPrefix(fullRef, f.From) && len(fullRef) > len(f.From) {
if !strings.HasPrefix(fullRef, from) && len(fullRef) > len(from) {
continue
}

if delimiter := fullRef[len(f.From)]; delimiter != ':' && delimiter != '/' {
if delimiter := fullRef[len(from)]; delimiter != ':' && delimiter != '/' && delimiter != '@' {
continue
}

newRefString := f.To + fullRef[len(f.From):]
newRefString := to + fullRef[len(from):]
if to == "index.docker.io/library" {
newRefString = fullRef[len(from)+1:]
}
newRef, err := name.ParseReference(newRefString)
if err != nil {
log.Fatalf("failed to parse %s into a reference, %v", newRefString, err)
return nil, false, err
}

if !RepositoryExists(newRef, verbose) {
return nil, false, fmt.Errorf("ERROR: %s is not a valid image reference", newRef)
}

content, updated = UpdateFromStatements(content, ref, newRef, f.dockerfile, f.Verbose)
if updated {
f.updated = true
ok := false
if content, ok = UpdateFromStatements(content, ref, newRef, filename, verbose); ok {
updated = true
}
}
return content, updated, nil
}

func MoveImageReferences(f *Fromage) error {
content, err := ReadFile(f.workTree, f.dockerfile)
if err != nil {
return err
}

content, f.updated, err = moveImageReferences(content, f.dockerfile, f.Verbose, f.From, f.To)
if err != nil {
log.Fatalf("%s", err)
}

if f.updated {
if !f.DryRun {
Expand Down
76 changes: 76 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package main

import (
"reflect"
"testing"
)

func Test_moveImageReferences(t *testing.T) {
type args struct {
content []byte
filename string
verbose bool
from string
to string
}
tests := []struct {
name string
args args
want []byte
want1 bool
wantErr bool
}{
{
"simple",
args{[]byte(`FROM python:3.7`),
"Dockerfile",
true,
"index.docker.io/library",
"public.ecr.aws/docker/library",
},
[]byte(`FROM public.ecr.aws/docker/library/python:3.7`),
true,
false,
},
{
"and back again",
args{[]byte(`FROM public.ecr.aws/docker/library/python:3.7`),
"Dockerfile",
true,
"public.ecr.aws/docker/library",
"index.docker.io/library",
},
[]byte(`FROM python:3.7`),
true,
false,
},

{
"error",
args{[]byte(`FROM python:3.7`),
"Dockerfile",
true,
"index.docker.io/library",
"public.ecr.aws/dorker/library",
},
nil,
false,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1, err := moveImageReferences(tt.args.content, tt.args.filename, tt.args.verbose, tt.args.from, tt.args.to)
if (err != nil) != tt.wantErr {
t.Errorf("moveImageReferences() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("moveImageReferences() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("moveImageReferences() got1 = %v, want %v", got1, tt.want1)
}
})
}
}
24 changes: 24 additions & 0 deletions repository_exists.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
"log"
)

var cache = map[string]bool{}

func RepositoryExists(reference name.Reference, verbose bool) bool {
name := reference.Context().String()
if result, ok := cache[name]; ok {
return result
}
_, err := crane.Head(reference.Name())
// _, err := crane.ListTags(reference.Context().String())
if err != nil && verbose {
log.Printf("DEBUG: no manifest found for %s, %s", name, err)
}

cache[name] = err == nil
return err == nil
}
1 change: 1 addition & 0 deletions tag/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var (
tagCategoryCache = map[string]TagCategories{}
gitDescribeSuffixRegExp = regexp.MustCompile(`(?m)^-((?P<order>[0-9]+)-g)?(?P<sha>[0-9a-f]{6,})(?P<dirty>-dirty)?$`)
gitDescribeOrderSubExprIndex = findStringIndex(gitDescribeSuffixRegExp.SubexpNames(), "order")
tagListCache = map[string][]string{}
)

func findStringIndex(a []string, item string) int {
Expand Down

0 comments on commit 54f54e8

Please sign in to comment.