mirror all released versions, fix stupid bug in version.Lt and add tests

This commit is contained in:
Jim Minter 2020-04-18 09:57:35 -05:00
Родитель 2282510ed5
Коммит 07fc29a151
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 0730CBDA10D1A2D3
4 изменённых файлов: 160 добавлений и 37 удалений

Просмотреть файл

@ -14,7 +14,6 @@ import (
"github.com/sirupsen/logrus"
pkgmirror "github.com/Azure/ARO-RP/pkg/mirror"
"github.com/Azure/ARO-RP/pkg/util/version"
)
func getAuth(key string) (*types.DockerAuthConfig, error) {
@ -59,28 +58,11 @@ func mirror(ctx context.Context, log *logrus.Entry) error {
}
log.Print("reading Cincinnati graph")
releases, err := pkgmirror.AddFromGraph("stable", pkgmirror.Version{4, 3})
releases, err := pkgmirror.AddFromGraph(pkgmirror.NewVersion(4, 3), pkgmirror.NewVersion(4, 4))
if err != nil {
return err
}
// ensure we mirror the version at which we are creating clusters, even if
// it isn't in the Cincinnati graph yet
var found bool
for _, release := range releases {
if release.Version == version.OpenShiftVersion {
found = true
break
}
}
if !found {
releases = append(releases, pkgmirror.Node{
Version: version.OpenShiftVersion,
Payload: version.OpenShiftPullSpec,
})
}
var errorOccurred bool
for _, release := range releases {
log.Printf("mirroring release %s", release.Version)

Просмотреть файл

@ -6,8 +6,8 @@ package mirror
import (
"encoding/json"
"fmt"
"mime"
"net/http"
"net/url"
)
type Node struct {
@ -16,18 +16,14 @@ type Node struct {
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
func AddFromGraph(channel string, min Version) ([]Node, error) {
req, err := http.NewRequest(http.MethodGet, "https://api.openshift.com/api/upgrades_info/v1/graph", nil)
// AddFromGraph adds all nodes whose version is of the form x.y.z (no suffix)
// and lies in the range [min, max)
func AddFromGraph(min, max *Version) ([]Node, error) {
req, err := http.NewRequest(http.MethodGet, "https://openshift-release.svc.ci.openshift.org/graph", nil)
if err != nil {
return nil, err
}
req.URL.RawQuery = url.Values{
"channel": []string{fmt.Sprintf("%s-%d.%d", channel, min[0], min[1])},
}.Encode()
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
@ -38,7 +34,12 @@ func AddFromGraph(channel string, min Version) ([]Node, error) {
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/json" {
mediaType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
if err != nil {
return nil, err
}
if mediaType != "application/vnd.redhat.cincinnati.graph+json" {
return nil, fmt.Errorf("unexpected content type %q", resp.Header.Get("Content-Type"))
}
@ -54,12 +55,14 @@ func AddFromGraph(channel string, min Version) ([]Node, error) {
releases := make([]Node, 0, len(g.Nodes))
for _, node := range g.Nodes {
version, err := newVersion(node.Version)
version, err := ParseVersion(node.Version)
if err != nil {
return nil, err
}
if version.Lt(min) {
if version.Lt(min) ||
!version.Lt(max) ||
version.Suffix != "" {
continue
}

Просмотреть файл

@ -5,15 +5,56 @@ package mirror
import (
"fmt"
"regexp"
"strconv"
)
type Version [3]byte
var rxVersion = regexp.MustCompile(`^(\d+)\.(\d+)\.(\d+)(.*)`)
func newVersion(vsn string) (v Version, err error) {
_, err = fmt.Sscanf(vsn, "%d.%d.%d", &v[0], &v[1], &v[2])
return
type Version struct {
V [3]byte
Suffix string
}
func (v Version) Lt(w Version) bool {
return v[0] < w[0] || v[1] < w[1] || v[2] < w[2]
func NewVersion(vs ...byte) *Version {
v := &Version{}
copy(v.V[:], vs)
return v
}
func ParseVersion(vsn string) (*Version, error) {
m := rxVersion.FindStringSubmatch(vsn)
if m == nil {
return nil, fmt.Errorf("could not parse version %q", vsn)
}
v := &Version{
Suffix: m[4],
}
for i := 0; i < 3; i++ {
b, err := strconv.ParseUint(m[i+1], 10, 8)
if err != nil {
return nil, err
}
v.V[i] = byte(b)
}
return v, nil
}
func (v *Version) Lt(w *Version) bool {
for i := 0; i < 3; i++ {
switch {
case v.V[i] < w.V[i]:
return true
case v.V[i] > w.V[i]:
return false
}
}
return false
}

Просмотреть файл

@ -0,0 +1,97 @@
package mirror
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"reflect"
"strconv"
"testing"
)
func TestNewVersion(t *testing.T) {
for i, tt := range []struct {
vs []byte
want *Version
}{
{
vs: []byte{1, 2},
want: &Version{V: [3]byte{1, 2}},
},
{
want: &Version{},
},
{
vs: []byte{1, 2, 3, 4},
want: &Version{V: [3]byte{1, 2, 3}},
},
} {
t.Run(strconv.Itoa(i), func(t *testing.T) {
got := NewVersion(tt.vs...)
if !reflect.DeepEqual(got, tt.want) {
t.Error(got)
}
})
}
}
func TestParseVersion(t *testing.T) {
for _, tt := range []struct {
vsn string
want *Version
wantErr string
}{
{
vsn: "4.3.0-0.nightly-2020-04-17-062811",
want: &Version{V: [3]byte{4, 3}, Suffix: "-0.nightly-2020-04-17-062811"},
},
{
vsn: "40.30.10",
want: &Version{V: [3]byte{40, 30, 10}},
},
{
vsn: "bad",
wantErr: `could not parse version "bad"`,
},
} {
t.Run(tt.vsn, func(t *testing.T) {
got, err := ParseVersion(tt.vsn)
if err != nil && err.Error() != tt.wantErr ||
err == nil && tt.wantErr != "" {
t.Error(err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Error(got)
}
})
}
}
func TestLt(t *testing.T) {
for i, tt := range []struct {
a *Version
b *Version
want bool
}{
{
a: NewVersion(4, 1),
b: NewVersion(4, 3),
want: true,
},
{
a: NewVersion(4, 4),
b: NewVersion(4, 3, 1),
},
{
a: NewVersion(4, 4),
b: NewVersion(4, 4),
},
} {
t.Run(strconv.Itoa(i), func(t *testing.T) {
got := tt.a.Lt(tt.b)
if got != tt.want {
t.Error(got)
}
})
}
}