Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Resolve release markers #9265

Merged
merged 1 commit into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading