-
Notifications
You must be signed in to change notification settings - Fork 425
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
Add workload cluster upgrades spec #1767
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,19 +92,15 @@ providers: | |
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template.yaml" | ||
targetName: "cluster-template-management.yaml" | ||
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-adoption.yaml" | ||
targetName: "cluster-template-kcp-adoption.yaml" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm assuming that |
||
- sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ipv6.yaml" | ||
targetName: "cluster-template-ipv6.yaml" | ||
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-md-remediation.yaml" | ||
targetName: "cluster-template-md-remediation.yaml" | ||
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-remediation.yaml" | ||
targetName: "cluster-template-kcp-remediation.yaml" | ||
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-scale-in.yaml" | ||
targetName: "cluster-template-kcp-scale-in.yaml" | ||
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-node-drain.yaml" | ||
targetName: "cluster-template-node-drain.yaml" | ||
- sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-upgrades.yaml" | ||
- sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-machine-pool.yaml" | ||
targetName: "cluster-template-machine-pool.yaml" | ||
- sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ipv6.yaml" | ||
targetName: "cluster-template-ipv6.yaml" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah basically |
||
- sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-nvidia-gpu.yaml" | ||
targetName: "cluster-template-nvidia-gpu.yaml" | ||
- sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-private.yaml" | ||
|
@@ -138,18 +134,17 @@ providers: | |
new: "--v=2" | ||
|
||
variables: | ||
KUBERNETES_VERSION: "${KUBERNETES_VERSION:-v1.22.1}" | ||
AKS_KUBERNETES_VERSION: "${KUBERNETES_VERSION:-stable-1.19}" | ||
KUBERNETES_VERSION: "${KUBERNETES_VERSION:=stable-1.22}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❤️ |
||
ETCD_VERSION_UPGRADE_TO: "3.5.0-0" | ||
COREDNS_VERSION_UPGRADE_TO: "v1.8.4" | ||
KUBERNETES_VERSION_UPGRADE_TO: "${KUBERNETES_VERSION_UPGRADE_TO:-v1.22.2}" | ||
KUBERNETES_VERSION_UPGRADE_FROM: "${KUBERNETES_VERSION_UPGRADE_FROM:-v1.22.1}" | ||
KUBERNETES_VERSION_UPGRADE_TO: "${KUBERNETES_VERSION_UPGRADE_TO:=stable-1.22}" | ||
KUBERNETES_VERSION_UPGRADE_FROM: "${KUBERNETES_VERSION_UPGRADE_FROM:-v1.22.1}" # this needs to be 1.22+ to support mixed windows/linux clusters until we update CAPI to v1.0.1. | ||
CNI: "${PWD}/templates/addons/calico.yaml" | ||
REDACT_LOG_SCRIPT: "${PWD}/hack/log/redact.sh" | ||
EXP_AKS: "true" | ||
EXP_MACHINE_POOL: "true" | ||
EXP_CLUSTER_RESOURCE_SET: "true" | ||
CONFORMANCE_CI_ARTIFACTS_KUBERNETES_VERSION: "v1.22.1" | ||
CONFORMANCE_WORKER_MACHINE_COUNT: "2" | ||
CONFORMANCE_CONTROL_PLANE_MACHINE_COUNT: "${CONFORMANCE_CONTROL_PLANE_MACHINE_COUNT:-1}" | ||
CONFORMANCE_IMAGE: "${CONFORMANCE_IMAGE:-}" | ||
|
@@ -164,6 +159,7 @@ variables: | |
INIT_WITH_BINARY: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.3.23/clusterctl-{OS}-{ARCH}" | ||
INIT_WITH_PROVIDERS_CONTRACT: "v1alpha3" | ||
INIT_WITH_KUBERNETES_VERSION: "v1.21.2" | ||
KUBETEST_CONFIGURATION: "./data/kubetest/conformance.yaml" | ||
|
||
intervals: | ||
default/wait-controllers: ["3m", "10s"] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,14 +29,17 @@ import ( | |
"path" | ||
"path/filepath" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
"testing" | ||
"time" | ||
|
||
aadpodv1 "github.com/Azure/aad-pod-identity/pkg/apis/aadpodidentity/v1" | ||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-07-01/compute" | ||
"github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" | ||
"github.com/Azure/go-autorest/autorest/azure/auth" | ||
"github.com/Azure/go-autorest/autorest/to" | ||
"github.com/blang/semver" | ||
. "github.com/onsi/ginkgo" | ||
"github.com/onsi/ginkgo/config" | ||
"github.com/onsi/ginkgo/reporters" | ||
|
@@ -344,6 +347,8 @@ func loadE2EConfig(configPath string) *clusterctl.E2EConfig { | |
config := clusterctl.LoadE2EConfig(context.TODO(), clusterctl.LoadE2EConfigInput{ConfigPath: configPath}) | ||
Expect(config).ToNot(BeNil(), "Failed to load E2E config from %s", configPath) | ||
|
||
resolveKubernetesVersions(config) | ||
|
||
return config | ||
} | ||
|
||
|
@@ -403,10 +408,103 @@ func tearDown(bootstrapClusterProvider bootstrap.ClusterProvider, bootstrapClust | |
} | ||
} | ||
|
||
// resolveKubernetesVersions looks at Kubernetes versions set as variables in the e2e config and sets them to a valid k8s version | ||
// that has an existing capi offer image available. For example, if the version is "stable-1.22", the function will set it to the latest 1.22 version that has a published reference image. | ||
func resolveKubernetesVersions(config *clusterctl.E2EConfig) { | ||
skus := getAllCAPIImageSkus(context.TODO(), os.Getenv(AzureLocation)) | ||
versions := parseImageSkuNames(skus) | ||
|
||
if config.HasVariable(capi_e2e.KubernetesVersion) { | ||
resolveKubernetesVersion(config, versions, capi_e2e.KubernetesVersion) | ||
} | ||
if config.HasVariable(capi_e2e.KubernetesVersionUpgradeFrom) { | ||
resolveKubernetesVersion(config, versions, capi_e2e.KubernetesVersionUpgradeFrom) | ||
} | ||
if config.HasVariable(capi_e2e.KubernetesVersionUpgradeTo) { | ||
resolveKubernetesVersion(config, versions, capi_e2e.KubernetesVersionUpgradeTo) | ||
} | ||
} | ||
|
||
func resolveKubernetesVersion(config *clusterctl.E2EConfig, versions semver.Versions, varName string) { | ||
v := getLatestSkuForMinor(config.GetVariable(varName), versions) | ||
if _, ok := os.LookupEnv(varName); ok { | ||
Expect(os.Setenv(varName, v)).To(Succeed()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we want to mutate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At first I didn't have this (only the config.Variables part below), but it didn't work. Unfortunately that's the only way to modify the config since the capi framework gives precedence to env variables if they are set: https://github.com/kubernetes-sigs/cluster-api/blob/main/test/framework/clusterctl/e2e_config.go#L553 FWIW, this is similar to what CAPI does for CAPD e2e tests https://github.com/kubernetes-sigs/cluster-api/blob/main/scripts/ci-e2e-lib.sh#L56 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh it's a capi constraint. Thanks for the explanation! |
||
} | ||
config.Variables[varName] = v | ||
} | ||
|
||
// getAllCAPIImageSkus returns all skus for the capi offer under the "cncf-upstream" publisher. | ||
func getAllCAPIImageSkus(ctx context.Context, location string) []string { | ||
settings, err := auth.GetSettingsFromEnvironment() | ||
Expect(err).NotTo(HaveOccurred()) | ||
subscriptionID := settings.GetSubscriptionID() | ||
authorizer, err := settings.GetAuthorizer() | ||
Expect(err).NotTo(HaveOccurred()) | ||
imagesClient := compute.NewVirtualMachineImagesClient(subscriptionID) | ||
imagesClient.Authorizer = authorizer | ||
|
||
Byf("Finding image skus for offer %s/%s in %s", capiImagePublisher, capiOfferName, location) | ||
|
||
res, err := imagesClient.ListSkus(ctx, location, capiImagePublisher, capiOfferName) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
var skus []string | ||
if res.Value != nil { | ||
skus = make([]string, len(*res.Value)) | ||
for i, sku := range *res.Value { | ||
// we have to do this to make sure the SKU has existing images | ||
// see https://github.com/Azure/azure-cli/issues/20115. | ||
res, err := imagesClient.List(ctx, location, capiImagePublisher, capiOfferName, *sku.Name, "", nil, "") | ||
Expect(err).NotTo(HaveOccurred()) | ||
if res.Value != nil && len(*res.Value) > 0 { | ||
skus[i] = *sku.Name | ||
} | ||
} | ||
} | ||
return skus | ||
} | ||
|
||
// parseImageSkuNames parses SKU names in format "k8s-1dot17dot2-ubuntu-1804" to extract the Kubernetes version. | ||
// it returns a sorted list of all k8s versions found. | ||
func parseImageSkuNames(skus []string) semver.Versions { | ||
CecileRobertMichon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var capiSku = regexp.MustCompile(`^k8s-(0|[1-9][0-9]*)dot(0|[1-9][0-9]*)dot(0|[1-9][0-9]*)-ubuntu.*$`) | ||
versions := make(semver.Versions, len(skus)) | ||
for i, sku := range skus { | ||
match := capiSku.FindStringSubmatch(sku) | ||
if len(match) != 0 { | ||
versions[i] = semver.MustParse(fmt.Sprintf("%s.%s.%s", match[1], match[2], match[3])) | ||
} | ||
} | ||
return versions | ||
} | ||
|
||
// getLatestSkuForMinor gets the latest available patch version in the provided list of sku versions that corresponds to the provided k8s version. | ||
func getLatestSkuForMinor(version string, skus semver.Versions) string { | ||
isStable, match := validateStableReleaseString(version) | ||
if isStable { | ||
major, err := strconv.ParseUint(match[1], 10, 64) | ||
Expect(err).NotTo(HaveOccurred()) | ||
minor, err := strconv.ParseUint(match[2], 10, 64) | ||
Expect(err).NotTo(HaveOccurred()) | ||
semver.Sort(skus) | ||
for i := len(skus) - 1; i >= 0; i-- { | ||
if skus[i].Major == major && skus[i].Minor == minor { | ||
version = "v" + skus[i].String() | ||
break | ||
} | ||
} | ||
} else { | ||
v, err := semver.ParseTolerant(version) | ||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(skus).To(ContainElement(v), fmt.Sprintf("Provided Kubernetes version %s does not have a corresponding VM image in the capi offer", version)) | ||
} | ||
CecileRobertMichon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return version | ||
} | ||
|
||
// validateStableReleaseString validates the string format that declares "get be the latest stable release for this <Major>.<Minor>" | ||
// it should be called wherever we process a stable version string expression like "stable-1.22" | ||
func validateStableReleaseString(stableVersion string) bool { | ||
func validateStableReleaseString(stableVersion string) (bool, []string) { | ||
stableReleaseFormat := regexp.MustCompile(`^stable-(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$`) | ||
matches := stableReleaseFormat.FindStringSubmatch(stableVersion) | ||
return len(matches) > 0 | ||
return len(matches) > 0, matches | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for changing these to
To(Succeed())
. So much more readable!