forked from vmware-tanzu/sonobuoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
imageversion.go
111 lines (92 loc) · 3.62 KB
/
imageversion.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
Copyright 2018 Heptio Inc.
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 app
import (
"fmt"
"strings"
version "github.com/hashicorp/go-version"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"k8s.io/client-go/discovery"
)
// ConformanceImageVersion represents the version of a conformance image, or "auto" to detect the version
type ConformanceImageVersion string
var (
//ErrImageVersionNoClient is the error returned when we need a client but didn't get on
ErrImageVersionNoClient = errors.New(`can't use nil client with "auto" image version`)
)
const (
// ConformanceImageVersionAuto represents detecting the server's kubernetes version.
ConformanceImageVersionAuto = "auto"
// ConformanceImageVersionLatest represents always using the server's latest version.
ConformanceImageVersionLatest = "latest"
)
// String needed for pflag.Value.
func (c *ConformanceImageVersion) String() string { return string(*c) }
// Type needed for pflag.Value.
func (c *ConformanceImageVersion) Type() string { return "ConformanceImageVersion" }
// Set the ImageVersion to either the string "auto" or a version string
func (c *ConformanceImageVersion) Set(str string) error {
switch str {
case ConformanceImageVersionAuto:
*c = ConformanceImageVersionAuto
case ConformanceImageVersionLatest:
*c = ConformanceImageVersionLatest
default:
version, err := validateVersion(str)
if err != nil {
return err
}
*c = ConformanceImageVersion(version.String())
}
return nil
}
// Get retrieves the preset version if there is one, or queries client if the ConformanceImageVersion is set to `auto`.
// kubernetes.Interface.Discovery() provides ServerVersionInterface.
// don't require the entire kubernetes.Interface to simplify the required test mocks
func (c *ConformanceImageVersion) Get(client discovery.ServerVersionInterface) (string, error) {
if *c == ConformanceImageVersionAuto {
if client == nil {
return "", ErrImageVersionNoClient
}
version, err := client.ServerVersion()
if err != nil {
return "", errors.Wrap(err, "couldn't retrieve server version")
}
parsedVersion, err := validateVersion(version.GitVersion)
if err != nil {
return "", err
}
segments := parsedVersion.Segments()
if len(segments) < 2 {
return "", fmt.Errorf("version %q only has %d segments, need at least 2", version.GitVersion, len(segments))
}
// NOTE: Until the kube-conformance container is pushed upstream we can't
// guarantee alignment with exact versioning see https://github.com/heptio/kube-conformance/issues/25
// for more details
// Use the segments instead of .major and .minor because GKE's .minor is `10+` instead of `10`.
return fmt.Sprintf("v%d.%d", segments[0], segments[1]), nil
}
return string(*c), nil
}
func validateVersion(v string) (*version.Version, error) {
version, err := version.NewVersion(v)
if err == nil {
if version.Metadata() != "" || version.Prerelease() != "" {
logrus.Warningf("Version %v is not a stable version, conformance image may not exist upstream", v)
} else if !strings.HasPrefix(v, "v") {
err = errors.New("version must start with v")
}
}
return version, errors.Wrapf(err, "version %q is invalid", v)
}