Skip to content

Commit 7c11298

Browse files
authored
Merge pull request #4923 from ykakarap/clusterctl-latest-releaseseries
🐛 clusterctl: use newest release series of same contract
2 parents 4e2b971 + 96dc88a commit 7c11298

File tree

3 files changed

+98
-11
lines changed

3 files changed

+98
-11
lines changed

cmd/clusterctl/api/v1alpha3/metadata_type.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package v1alpha3
1818

1919
import (
20+
"github.com/blang/semver"
2021
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2122
"k8s.io/apimachinery/pkg/util/version"
2223
)
@@ -46,6 +47,12 @@ type ReleaseSeries struct {
4647
Contract string `json:"contract,omitempty"`
4748
}
4849

50+
func (rs ReleaseSeries) newer(release ReleaseSeries) bool {
51+
v := semver.Version{Major: uint64(rs.Major), Minor: uint64(rs.Minor)}
52+
ver := semver.Version{Major: uint64(release.Major), Minor: uint64(release.Minor)}
53+
return v.GTE(ver)
54+
}
55+
4956
func init() {
5057
SchemeBuilder.Register(&Metadata{})
5158
}
@@ -62,12 +69,21 @@ func (m *Metadata) GetReleaseSeriesForVersion(version *version.Version) *Release
6269
}
6370

6471
// GetReleaseSeriesForContract returns the release series for a given API Version, e.g. `v1alpha4`.
72+
// If more than one release series use the same contract then the latest newer release series is
73+
// returned.
6574
func (m *Metadata) GetReleaseSeriesForContract(contract string) *ReleaseSeries {
75+
var rs ReleaseSeries
76+
var found bool
6677
for _, releaseSeries := range m.ReleaseSeries {
6778
if contract == releaseSeries.Contract {
68-
return &releaseSeries
79+
found = true
80+
if releaseSeries.newer(rs) {
81+
rs = releaseSeries
82+
}
6983
}
7084
}
71-
72-
return nil
85+
if !found {
86+
return nil
87+
}
88+
return &rs
7389
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package v1alpha3
17+
18+
import (
19+
"testing"
20+
21+
. "github.com/onsi/gomega"
22+
)
23+
24+
func TestGetReleaseSeriesForContract(t *testing.T) {
25+
rsSinglePerContract := []ReleaseSeries{
26+
{Major: 0, Minor: 4, Contract: "v1alpha4"},
27+
{Major: 0, Minor: 3, Contract: "v1alpha3"},
28+
}
29+
30+
rsMultiplePerContract := []ReleaseSeries{
31+
{Major: 0, Minor: 4, Contract: "v1alpha4"},
32+
{Major: 0, Minor: 5, Contract: "v1alpha4"},
33+
{Major: 0, Minor: 3, Contract: "v1alpha3"},
34+
}
35+
36+
tests := []struct {
37+
name string
38+
contract string
39+
releaseSeries []ReleaseSeries
40+
expectedReleaseSeries *ReleaseSeries
41+
}{
42+
{
43+
name: "Should get the release series with matching contract",
44+
contract: "v1alpha4",
45+
releaseSeries: rsSinglePerContract,
46+
expectedReleaseSeries: &rsMultiplePerContract[0],
47+
},
48+
{
49+
name: "Should get the newest release series with matching contract",
50+
contract: "v1alpha4",
51+
releaseSeries: rsMultiplePerContract,
52+
expectedReleaseSeries: &rsMultiplePerContract[1],
53+
},
54+
{
55+
name: "Should return nil if no release series with matching contract is found",
56+
contract: "v1alpha5",
57+
releaseSeries: rsMultiplePerContract,
58+
expectedReleaseSeries: nil,
59+
},
60+
}
61+
62+
for _, test := range tests {
63+
t.Run(test.name, func(t *testing.T) {
64+
g := NewWithT(t)
65+
66+
m := &Metadata{ReleaseSeries: test.releaseSeries}
67+
g.Expect(m.GetReleaseSeriesForContract(test.contract)).To(Equal(test.expectedReleaseSeries))
68+
})
69+
}
70+
}

cmd/clusterctl/client/repository/repository_github_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,24 +291,25 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {
291291
mux.HandleFunc("/repos/o/r1/releases", func(w http.ResponseWriter, r *http.Request) {
292292
testMethod(t, r, "GET")
293293
fmt.Fprint(w, `[`)
294-
fmt.Fprint(w, `{"id":1, "tag_name": "v0.4.0", "assets": [{"id": 1, "name": "metadata.yaml"}]},`)
295-
fmt.Fprint(w, `{"id":2, "tag_name": "v0.3.2", "assets": [{"id": 1, "name": "metadata.yaml"}]},`)
296-
fmt.Fprint(w, `{"id":3, "tag_name": "v0.3.1", "assets": [{"id": 1, "name": "metadata.yaml"}]}`)
294+
fmt.Fprint(w, `{"id":1, "tag_name": "v0.5.0", "assets": [{"id": 1, "name": "metadata.yaml"}]},`)
295+
fmt.Fprint(w, `{"id":2, "tag_name": "v0.4.0", "assets": [{"id": 1, "name": "metadata.yaml"}]},`)
296+
fmt.Fprint(w, `{"id":3, "tag_name": "v0.3.2", "assets": [{"id": 1, "name": "metadata.yaml"}]},`)
297+
fmt.Fprint(w, `{"id":4, "tag_name": "v0.3.1", "assets": [{"id": 1, "name": "metadata.yaml"}]}`)
297298
fmt.Fprint(w, `]`)
298299
})
299300

300301
// test.NewFakeGitHub and handler for returning a fake release
301-
mux.HandleFunc("/repos/o/r1/releases/tags/v0.4.0", func(w http.ResponseWriter, r *http.Request) {
302+
mux.HandleFunc("/repos/o/r1/releases/tags/v0.5.0", func(w http.ResponseWriter, r *http.Request) {
302303
testMethod(t, r, "GET")
303-
fmt.Fprint(w, `{"id":13, "tag_name": "v0.4.0", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
304+
fmt.Fprint(w, `{"id":13, "tag_name": "v0.5.0", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
304305
})
305306

306307
// test.NewFakeGitHub an handler for returning a fake release metadata file
307308
mux.HandleFunc("/repos/o/r1/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
308309
testMethod(t, r, "GET")
309310
w.Header().Set("Content-Type", "application/octet-stream")
310311
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
311-
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
312+
fmt.Fprint(w, "apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3\nreleaseSeries:\n - major: 0\n minor: 4\n contract: v1alpha4\n - major: 0\n minor: 5\n contract: v1alpha4\n - major: 0\n minor: 3\n contract: v1alpha3\n")
312313
})
313314

314315
configVariablesClient := test.NewFakeVariableClient()
@@ -329,7 +330,7 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {
329330
providerConfig: config.NewProvider("test", "https://github.com/o/r1/releases/latest/path", clusterctlv1.CoreProviderType),
330331
},
331332
contract: "v1alpha4",
332-
want: "v0.4.0",
333+
want: "v0.5.0",
333334
wantErr: false,
334335
},
335336
{
@@ -346,7 +347,7 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {
346347
field: field{
347348
providerConfig: config.NewProvider("test", "https://github.com/o/r1/releases/latest/path", clusterctlv1.CoreProviderType),
348349
},
349-
want: "v0.4.0",
350+
want: "v0.5.0",
350351
contract: "foo",
351352
wantErr: false,
352353
},

0 commit comments

Comments
 (0)