talos
74 строки · 1.7 Кб
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5package kubernetes
6
7import (
8"context"
9"errors"
10"fmt"
11"strings"
12
13"github.com/blang/semver/v4"
14metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15)
16
17// DetectLowestVersion returns lowest Kubernetes components versions in the cluster.
18//
19//nolint:gocyclo
20func DetectLowestVersion(ctx context.Context, cluster UpgradeProvider, options UpgradeOptions) (string, error) {
21k8sClient, err := cluster.K8sHelper(ctx)
22if err != nil {
23return "", fmt.Errorf("error building kubernetes client: %w", err)
24}
25
26apps := map[string]struct{}{
27"kube-apiserver": {},
28"kube-controller-manager": {},
29"kube-proxy": {},
30"kube-scheduler": {},
31}
32
33pods, err := k8sClient.CoreV1().Pods("kube-system").List(ctx, metav1.ListOptions{})
34if err != nil {
35return "", err
36}
37
38var version *semver.Version
39
40for _, pod := range pods.Items {
41app := pod.GetObjectMeta().GetLabels()["k8s-app"]
42if _, ok := apps[app]; !ok {
43continue
44}
45
46for _, container := range pod.Spec.Containers {
47if container.Name != app {
48continue
49}
50
51idx := strings.LastIndex(container.Image, ":")
52if idx == -1 {
53continue
54}
55
56v, err := semver.ParseTolerant(strings.TrimLeft(container.Image[idx+1:], "v"))
57if err != nil {
58options.Log("failed to parse %s container version %s", app, err)
59
60continue
61}
62
63if version == nil || v.LT(*version) {
64version = &v
65}
66}
67}
68
69if version == nil {
70return "", errors.New("failed to detect lowest Kubernetes version")
71}
72
73return version.String(), nil
74}
75