Skip to content

Commit

Permalink
Resolve release markers
Browse files Browse the repository at this point in the history
  • Loading branch information
adilGhaffarDev committed Aug 25, 2023
1 parent 46412f0 commit c79a6ae
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 24 deletions.
1 change: 1 addition & 0 deletions test/e2e/cluster_upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func ClusterUpgradeConformanceSpec(ctx context.Context, inputGetter func() Clust
Expect(ctx).NotTo(BeNil(), "ctx is required for %s spec", specName)
input = inputGetter()
Expect(input.E2EConfig).ToNot(BeNil(), "Invalid argument. input.E2EConfig can't be nil when calling %s spec", specName)
Expect(input.E2EConfig.ResolveReleases()).To(Succeed(), "Failed to resolve release markers in e2e test config file")
Expect(input.ClusterctlConfigPath).To(BeAnExistingFile(), "Invalid argument. input.ClusterctlConfigPath must be an existing file when calling %s spec", specName)
Expect(input.BootstrapClusterProxy).ToNot(BeNil(), "Invalid argument. input.BootstrapClusterProxy can't be nil when calling %s spec", specName)
Expect(os.MkdirAll(input.ArtifactFolder, 0750)).To(Succeed(), "Invalid argument. input.ArtifactFolder can't be created for %s spec", specName)
Expand Down
48 changes: 24 additions & 24 deletions test/e2e/config/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,26 @@ providers:
- name: cluster-api
type: CoreProvider
versions:
- name: v1.0.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.5/core-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.0}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.0}/core-components.yaml"
type: "url"
contract: v1beta1
replacements:
- old: --metrics-addr=127.0.0.1:8080
new: --metrics-addr=:8080
files:
- sourcePath: "../data/shared/v1.0/metadata.yaml"
- name: v1.4.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.4.5/core-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.4}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.4}/core-components.yaml"
type: "url"
contract: v1beta1
replacements:
- old: --metrics-addr=127.0.0.1:8080
new: --metrics-addr=:8080
files:
- sourcePath: "../data/shared/v1.4/metadata.yaml"
- name: v1.5.0 # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.0/core-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.5}" # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.5}/core-components.yaml"
type: "url"
contract: v1beta1
replacements:
Expand All @@ -73,26 +73,26 @@ providers:
- name: kubeadm
type: BootstrapProvider
versions:
- name: v1.0.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.5/bootstrap-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.0}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.0}/bootstrap-components.yaml"
type: "url"
contract: v1beta1
replacements:
- old: --metrics-addr=127.0.0.1:8080
new: --metrics-addr=:8080
files:
- sourcePath: "../data/shared/v1.0/metadata.yaml"
- name: v1.4.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.4.5/bootstrap-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.4}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.4}/bootstrap-components.yaml"
type: "url"
contract: v1beta1
replacements:
- old: --metrics-addr=127.0.0.1:8080
new: --metrics-addr=:8080
files:
- sourcePath: "../data/shared/v1.4/metadata.yaml"
- name: v1.5.0 # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.0/bootstrap-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.5}" # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.5}/bootstrap-components.yaml"
type: "url"
contract: v1beta1
replacements:
Expand All @@ -111,26 +111,26 @@ providers:
- name: kubeadm
type: ControlPlaneProvider
versions:
- name: v1.0.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.5/control-plane-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.0}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.0}/control-plane-components.yaml"
type: "url"
contract: v1beta1
replacements:
- old: --metrics-addr=127.0.0.1:8080
new: --metrics-addr=:8080
files:
- sourcePath: "../data/shared/v1.0/metadata.yaml"
- name: v1.4.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.4.5/control-plane-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.4}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.4}/control-plane-components.yaml"
type: "url"
contract: v1beta1
replacements:
- old: --metrics-addr=127.0.0.1:8080
new: --metrics-addr=:8080
files:
- sourcePath: "../data/shared/v1.4/metadata.yaml"
- name: v1.5.0 # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.0/control-plane-components.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.5}" # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.5}/control-plane-components.yaml"
type: "url"
contract: v1beta1
replacements:
Expand All @@ -149,8 +149,8 @@ providers:
- name: docker
type: InfrastructureProvider
versions:
- name: v1.0.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.5/infrastructure-components-development.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.0}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.0}/infrastructure-components-development.yaml"
type: "url"
contract: v1beta1
replacements:
Expand All @@ -159,8 +159,8 @@ providers:
files:
- sourcePath: "../data/shared/v1.0/metadata.yaml"
- sourcePath: "../data/infrastructure-docker/v1.0/cluster-template.yaml"
- name: v1.4.5 # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.4.5/infrastructure-components-development.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.4}" # supported release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.4}/infrastructure-components-development.yaml"
type: "url"
contract: v1beta1
replacements:
Expand All @@ -171,8 +171,8 @@ providers:
- sourcePath: "../data/infrastructure-docker/v1.4/cluster-template.yaml"
- sourcePath: "../data/infrastructure-docker/v1.4/cluster-template-topology.yaml"
- sourcePath: "../data/infrastructure-docker/v1.4/clusterclass-quick-start.yaml"
- name: v1.5.0 # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.5.0/infrastructure-components-development.yaml"
- name: "{go://sigs.k8s.io/cluster-api@v1.5}" # latest published release in the v1beta1 series; this is used for v1beta1 --> main clusterctl upgrades test only.
value: "https://github.com/kubernetes-sigs/cluster-api/releases/download/{go://sigs.k8s.io/cluster-api@v1.5}/infrastructure-components-development.yaml"
type: "url"
contract: v1beta1
replacements:
Expand Down
101 changes: 101 additions & 0 deletions test/framework/clusterctl/e2e_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ package clusterctl
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
Expand All @@ -29,6 +32,7 @@ import (
"strings"
"time"

"github.com/blang/semver/v4"
. "github.com/onsi/gomega"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/version"
Expand Down Expand Up @@ -57,6 +61,7 @@ func LoadE2EConfig(_ context.Context, input LoadE2EConfigInput) *E2EConfig {
config := &E2EConfig{}
Expect(yaml.Unmarshal(configData, config)).To(Succeed(), "Failed to convert the e2e test config file to yaml")

Expect(config.ResolveReleases()).To(Succeed(), "Failed to resolve release markers in e2e test config file")
config.Defaults()
config.AbsPaths(filepath.Dir(input.ConfigPath))

Expand Down Expand Up @@ -245,6 +250,102 @@ type Files struct {
TargetName string `json:"targetName,omitempty"`
}

// ResolveReleases converts release markers to release version.
func (c *E2EConfig) ResolveReleases() error {
for i := range c.Providers {
provider := &c.Providers[i]
for j := range provider.Versions {
version := &provider.Versions[j]
if version.Type == "url" {
releaseMarker := strings.TrimLeft(strings.TrimRight(version.Name, "}"), "{")
if !strings.EqualFold(version.Name, releaseMarker) {
ver, err := resolveReleaseMarker(releaseMarker)
if err != nil {
return fmt.Errorf("failed resolving release path %s with error: %v", version.Name, err)
}
ver = "v" + ver
version.Value = strings.Replace(version.Value, version.Name, ver, 1)
version.Name = ver
}
}
}
}
return nil
}

// resolveReleaseMarker resolves releaseMarker string to verion string e.g.
// - Resolves "{go://sigs.k8s.io/cluster-api@v1.0}" to stable minor release of v.1.0.
// - Resolves "{go://sigs.k8s.io/cluster-api@latest-v1.0}" to latest minor release of v.1.0 including rc and pre releases.
func resolveReleaseMarker(releaseMarker string) (string, error) {
parts := strings.Split(releaseMarker, ":")
if len(parts) < 1 {
return "", errors.Errorf("Invalid release url")
}

host := parts[0]
gomoduleParts := strings.Split(parts[1], "@")
if len(gomoduleParts) < 2 {
return "", errors.Errorf("Invalid release url, go module or version missing")
}
gomodule := gomoduleParts[0]
version := strings.ReplaceAll(gomoduleParts[1], "v", "")
includePrereleases := false
parsedVersion := strings.Split(version, "-")
if len(parsedVersion) > 0 {
if len(parsedVersion) > 1 {
version = parsedVersion[1]
if parsedVersion[0] == "latest" {
includePrereleases = true
}
}
} else {
return "", errors.Errorf("Invalid release url")
}

minSemVersion := semver.MustParse(version + ".0")
maxSemVersion := minSemVersion
maxSemVersion.Minor++

if host == "go" {
host = "proxy.golang.org"
}
rawURL := url.URL{
Scheme: "https",
Host: host,
Path: path.Join(gomodule, "@v", "/list"),
}

resp, err := http.Get(rawURL.String()) //nolint:noctx // NB: as we're just implementing an external interface we won't be able to get a context here.
if err != nil {
return "", err
}
defer resp.Body.Close()

out, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}

parsedTags := semver.Versions{}
for _, line := range strings.Split(string(out), "\n") {
if strings.HasPrefix(line, "v") {
parsedTags = append(parsedTags, semver.MustParse(strings.TrimPrefix(line, "v")))
}
}
sort.Sort(parsedTags)

var picked semver.Version
for i, tag := range parsedTags {
if !includePrereleases && len(tag.Pre) > 0 {
continue
}
if tag.LT(maxSemVersion) && tag.Minor <= minSemVersion.Minor {
picked = parsedTags[i]
}
}
return picked.String(), nil
}

// Defaults assigns default values to the object. More specifically:
// - ManagementClusterName gets a default name if empty.
// - Providers version gets type KustomizeSource if not otherwise specified.
Expand Down

0 comments on commit c79a6ae

Please sign in to comment.