Skip to content

Commit

Permalink
Merge pull request kubernetes-sigs#9265 from Nordix/resolve-releases/…
Browse files Browse the repository at this point in the history
…adil

✨ Resolve release markers
  • Loading branch information
k8s-ci-robot authored Dec 13, 2023
2 parents 24ef14f + c3bdf69 commit 36e9aba
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 127 deletions.
82 changes: 30 additions & 52 deletions cmd/clusterctl/client/repository/repository_github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"

Expand All @@ -33,6 +31,7 @@ import (
"sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test"
"sigs.k8s.io/cluster-api/internal/goproxy"
goproxytest "sigs.k8s.io/cluster-api/internal/goproxy/test"
)

func Test_gitHubRepository_GetVersions(t *testing.T) {
Expand All @@ -44,7 +43,7 @@ func Test_gitHubRepository_GetVersions(t *testing.T) {

// Setup an handler for returning 5 fake releases.
mux.HandleFunc("/repos/o/r1/releases", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `[`)
fmt.Fprint(w, `{"id":1, "tag_name": "v0.4.0"},`)
fmt.Fprint(w, `{"id":2, "tag_name": "v0.4.1"},`)
Expand All @@ -53,12 +52,13 @@ func Test_gitHubRepository_GetVersions(t *testing.T) {
fmt.Fprint(w, `]`)
})

clientGoproxy, muxGoproxy, teardownGoproxy := newFakeGoproxy()
scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := goproxy.NewClient(scheme, host)
defer teardownGoproxy()

// Setup a handler for returning 4 fake releases.
muxGoproxy.HandleFunc("/github.com/o/r2/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v0.5.0\n")
fmt.Fprint(w, "v0.4.0\n")
fmt.Fprint(w, "v0.3.2\n")
Expand All @@ -67,16 +67,16 @@ func Test_gitHubRepository_GetVersions(t *testing.T) {

// Setup a handler for returning 3 different major fake releases.
muxGoproxy.HandleFunc("/github.com/o/r3/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v1.0.0\n")
fmt.Fprint(w, "v0.1.0\n")
})
muxGoproxy.HandleFunc("/github.com/o/r3/v2/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v2.0.0\n")
})
muxGoproxy.HandleFunc("/github.com/o/r3/v3/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v3.0.0\n")
})

Expand Down Expand Up @@ -271,13 +271,13 @@ func Test_githubRepository_getFile(t *testing.T) {

// Setup a handler for returning a fake release.
mux.HandleFunc("/repos/o/r/releases/tags/v0.4.1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":13, "tag_name": "v0.4.1", "assets": [{"id": 1, "name": "file.yaml"}] }`)
})

// Setup a handler for returning a fake release asset.
mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=file.yaml")
fmt.Fprint(w, "content")
Expand Down Expand Up @@ -345,7 +345,7 @@ func Test_gitHubRepository_getVersions(t *testing.T) {
// Each response contains a link to the next page (if available) which
// is parsed by the handler to navigate through all pages
mux.HandleFunc("/repos/o/r1/releases", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
page := r.URL.Query().Get("page")
switch page {
case "", "1":
Expand Down Expand Up @@ -424,24 +424,26 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {

// Setup a handler for returning a fake release.
mux.HandleFunc("/repos/o/r1/releases/tags/v0.5.0", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":13, "tag_name": "v0.5.0", "assets": [{"id": 1, "name": "metadata.yaml"}] }`)
})

// Setup a handler for returning a fake release metadata file.
mux.HandleFunc("/repos/o/r1/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=metadata.yaml")
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")
})

clientGoproxy, muxGoproxy, teardownGoproxy := newFakeGoproxy()
scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := goproxy.NewClient(scheme, host)

defer teardownGoproxy()

// Setup a handler for returning 4 fake releases.
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v0.5.0\n")
fmt.Fprint(w, "v0.4.0\n")
fmt.Fprint(w, "v0.3.2\n")
Expand All @@ -450,7 +452,7 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {

// setup an handler for returning 4 fake releases but no actual tagged release
muxGoproxy.HandleFunc("/github.com/o/r2/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v0.5.0\n")
fmt.Fprint(w, "v0.4.0\n")
fmt.Fprint(w, "v0.3.2\n")
Expand Down Expand Up @@ -528,32 +530,33 @@ func Test_gitHubRepository_getLatestContractRelease(t *testing.T) {
func Test_gitHubRepository_getLatestRelease(t *testing.T) {
retryableOperationInterval = 200 * time.Millisecond
retryableOperationTimeout = 1 * time.Second
clientGoproxy, muxGoproxy, teardownGoproxy := newFakeGoproxy()
scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := goproxy.NewClient(scheme, host)
defer teardownGoproxy()

// Setup a handler for returning 4 fake releases.
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v0.4.1\n")
fmt.Fprint(w, "v0.4.2\n")
fmt.Fprint(w, "v0.4.3-alpha\n") // prerelease
fmt.Fprint(w, "foo\n") // no semantic version tag
})
// And also expose a release for them
muxGoproxy.HandleFunc("/api.github.com/repos/o/r1/releases/tags/v0.4.2", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "{}\n")
})

// Setup a handler for returning no releases.
muxGoproxy.HandleFunc("/github.com/o/r2/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
// no releases
})

// Setup a handler for returning fake prereleases only.
muxGoproxy.HandleFunc("/github.com/o/r3/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v0.1.0-alpha.0\n")
fmt.Fprint(w, "v0.1.0-alpha.1\n")
fmt.Fprint(w, "v0.1.0-alpha.2\n")
Expand Down Expand Up @@ -621,12 +624,13 @@ func Test_gitHubRepository_getLatestRelease(t *testing.T) {
func Test_gitHubRepository_getLatestPatchRelease(t *testing.T) {
retryableOperationInterval = 200 * time.Millisecond
retryableOperationTimeout = 1 * time.Second
clientGoproxy, muxGoproxy, teardownGoproxy := newFakeGoproxy()
scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := goproxy.NewClient(scheme, host)
defer teardownGoproxy()

// Setup a handler for returning 4 fake releases.
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v0.4.0\n")
fmt.Fprint(w, "v0.3.2\n")
fmt.Fprint(w, "v1.3.2\n")
Expand Down Expand Up @@ -712,7 +716,7 @@ func Test_gitHubRepository_getReleaseByTag(t *testing.T) {

// Setup a handler for returning a fake release.
mux.HandleFunc("/repos/o/r/releases/tags/foo", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, `{"id":13, "tag_name": "v0.4.1"}`)
})

Expand Down Expand Up @@ -783,14 +787,14 @@ func Test_gitHubRepository_downloadFilesFromRelease(t *testing.T) {

// Setup a handler for returning a fake release asset.
mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=file.yaml")
fmt.Fprint(w, "content")
})
// Setup a handler which redirects to a different location.
mux.HandleFunc("/repos/o/r-with-redirect/releases/assets/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
http.Redirect(w, r, "/api-v3/repos/o/r/releases/assets/1", http.StatusFound)
})

Expand Down Expand Up @@ -903,35 +907,9 @@ func Test_gitHubRepository_downloadFilesFromRelease(t *testing.T) {
}
}

func testMethod(t *testing.T, r *http.Request, want string) {
t.Helper()

if got := r.Method; got != want {
t.Errorf("Request method: %v, want %v", got, want)
}
}

// resetCaches is called repeatedly throughout tests to help avoid cross-test pollution.
func resetCaches() {
cacheVersions = map[string][]string{}
cacheReleases = map[string]*github.RepositoryRelease{}
cacheFiles = map[string][]byte{}
}

// newFakeGoproxy sets up a test HTTP server along with a github.Client that is
// configured to talk to that test server. Tests should register handlers on
// mux which provide mock responses for the API method being tested.
func newFakeGoproxy() (client *goproxy.Client, mux *http.ServeMux, teardown func()) {
// mux is the HTTP request multiplexer used with the test server.
mux = http.NewServeMux()

apiHandler := http.NewServeMux()
apiHandler.Handle("/", mux)

// server is a test HTTP server used to provide mock API responses.
server := httptest.NewServer(apiHandler)

// client is the GitHub client being tested and is configured to use test server.
url, _ := url.Parse(server.URL + "/")
return goproxy.NewClient(url.Scheme, url.Host), mux, server.Close
}
3 changes: 2 additions & 1 deletion cmd/clusterctl/client/repository/repository_gitlab_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
"sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test"
goproxytest "sigs.k8s.io/cluster-api/internal/goproxy/test"
)

func Test_gitLabRepository_newGitLabRepository(t *testing.T) {
Expand Down Expand Up @@ -152,7 +153,7 @@ func Test_gitLabRepository_getFile(t *testing.T) {
providerConfig := config.NewProvider("test", providerURL, clusterctlv1.CoreProviderType)

mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
if r.URL.RawPath == "/api/v4/projects/group%2Fproject/packages/generic/my-package/v0.4.1/file.yaml" {
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment; filename=file.yaml")
Expand Down
39 changes: 7 additions & 32 deletions internal/goproxy/goproxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,39 @@ import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"

"github.com/blang/semver/v4"
. "github.com/onsi/gomega"

goproxytest "sigs.k8s.io/cluster-api/internal/goproxy/test"
)

func TestClient_GetVersions(t *testing.T) {
retryableOperationInterval = 200 * time.Millisecond
retryableOperationTimeout = 1 * time.Second

clientGoproxy, muxGoproxy, teardownGoproxy := NewFakeGoproxy()
scheme, host, muxGoproxy, teardownGoproxy := goproxytest.NewFakeGoproxy()
clientGoproxy := NewClient(scheme, host)
defer teardownGoproxy()

// setup an handler for returning 2 fake releases
muxGoproxy.HandleFunc("/github.com/o/r1/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v1.1.0\n")
fmt.Fprint(w, "v0.2.0\n")
})

// setup an handler for returning 2 fake releases for v1
muxGoproxy.HandleFunc("/github.com/o/r2/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v1.1.0\n")
fmt.Fprint(w, "v0.2.0\n")
})
// setup an handler for returning 2 fake releases for v2
muxGoproxy.HandleFunc("/github.com/o/r2/v2/@v/list", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
goproxytest.HTTPTestMethod(t, r, "GET")
fmt.Fprint(w, "v2.0.1\n")
fmt.Fprint(w, "v2.0.0\n")
})
Expand Down Expand Up @@ -182,29 +183,3 @@ func Test_GetGoproxyHost(t *testing.T) {
})
}
}

// NewFakeGoproxy sets up a test HTTP server along with a github.Client that is
// configured to talk to that test server. Tests should register handlers on
// mux which provide mock responses for the API method being tested.
func NewFakeGoproxy() (client *Client, mux *http.ServeMux, teardown func()) {
// mux is the HTTP request multiplexer used with the test server.
mux = http.NewServeMux()

apiHandler := http.NewServeMux()
apiHandler.Handle("/", mux)

// server is a test HTTP server used to provide mock API responses.
server := httptest.NewServer(apiHandler)

// client is the GitHub client being tested and is configured to use test server.
url, _ := url.Parse(server.URL + "/")
return NewClient(url.Scheme, url.Host), mux, server.Close
}

func testMethod(t *testing.T, r *http.Request, want string) {
t.Helper()

if got := r.Method; got != want {
t.Errorf("Request method: %v, want %v", got, want)
}
}
52 changes: 52 additions & 0 deletions internal/goproxy/test/test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package test contains test util functions for goproxy.
package test

import (
"net/http"
"net/http/httptest"
"net/url"
"testing"
)

// NewFakeGoproxy sets up a test HTTP server along with a github.Client that is
// configured to talk to that test server. Tests should register handlers on
// mux which provide mock responses for the API method being tested.
func NewFakeGoproxy() (scheme string, host string, mux *http.ServeMux, teardown func()) {
// mux is the HTTP request multiplexer used with the test server.
mux = http.NewServeMux()

apiHandler := http.NewServeMux()
apiHandler.Handle("/", mux)

// server is a test HTTP server used to provide mock API responses.
server := httptest.NewServer(apiHandler)

// client is the GitHub client being tested and is configured to use test server.
url, _ := url.Parse(server.URL + "/")
return url.Scheme, url.Host, mux, server.Close
}

// HTTPTestMethod reports error http.Request does not return want string.
func HTTPTestMethod(t *testing.T, r *http.Request, want string) {
t.Helper()

if got := r.Method; got != want {
t.Errorf("Request method: %v, want %v", got, want)
}
}
1 change: 1 addition & 0 deletions test/e2e/clusterctl_upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func ClusterctlUpgradeSpec(ctx context.Context, inputGetter func() ClusterctlUpg

clusterctlBinaryURLTemplate := input.InitWithBinary
if clusterctlBinaryURLTemplate == "" {
Expect(input.E2EConfig.ResolveReleases(ctx)).To(Succeed(), "Failed to resolve release markers in e2e test config file")
Expect(input.E2EConfig.Variables).To(HaveKey(initWithBinaryVariableName), "Invalid argument. %s variable must be defined when calling %s spec", initWithBinaryVariableName, specName)
Expect(input.E2EConfig.Variables[initWithBinaryVariableName]).ToNot(BeEmpty(), "Invalid argument. %s variable can't be empty when calling %s spec", initWithBinaryVariableName, specName)
clusterctlBinaryURLTemplate = input.E2EConfig.GetVariable(initWithBinaryVariableName)
Expand Down
Loading

0 comments on commit 36e9aba

Please sign in to comment.