...
1
16
17 package main
18
19 import (
20 "fmt"
21 "strings"
22
23 "github.com/blang/semver/v4"
24 )
25
26
27 type EtcdVersion struct {
28 semver.Version
29 }
30
31
32 func ParseEtcdVersion(s string) (*EtcdVersion, error) {
33 v, err := semver.Make(s)
34 if err != nil {
35 return nil, err
36 }
37 return &EtcdVersion{v}, nil
38 }
39
40
41 func MustParseEtcdVersion(s string) *EtcdVersion {
42 return &EtcdVersion{semver.MustParse(s)}
43 }
44
45
46 func (v *EtcdVersion) String() string {
47 return v.Version.String()
48 }
49
50
51 func (v *EtcdVersion) Equals(o *EtcdVersion) bool {
52 return v.Version.Equals(o.Version)
53 }
54
55
56
57 func (v *EtcdVersion) MajorMinorEquals(o *EtcdVersion) bool {
58 return v.Major == o.Major && v.Minor == o.Minor
59 }
60
61
62 type EtcdStorageVersion int
63
64 const (
65 storageUnknown EtcdStorageVersion = iota
66 storageEtcd2
67 storageEtcd3
68 )
69
70
71 func ParseEtcdStorageVersion(s string) (EtcdStorageVersion, error) {
72 switch s {
73 case "etcd2":
74 return storageEtcd2, nil
75 case "etcd3":
76 return storageEtcd3, nil
77 default:
78 return storageUnknown, fmt.Errorf("unrecognized storage version: %s", s)
79 }
80 }
81
82
83
84 func MustParseEtcdStorageVersion(s string) EtcdStorageVersion {
85 version, err := ParseEtcdStorageVersion(s)
86 if err != nil {
87 panic(err)
88 }
89 return version
90 }
91
92
93 func (v EtcdStorageVersion) String() string {
94 switch v {
95 case storageEtcd2:
96 return "etcd2"
97 case storageEtcd3:
98 return "etcd3"
99 default:
100 panic(fmt.Sprintf("enum value %d missing from EtcdStorageVersion String() function", v))
101 }
102 }
103
104
105 type EtcdVersionPair struct {
106 version *EtcdVersion
107 storageVersion EtcdStorageVersion
108 }
109
110
111 func ParseEtcdVersionPair(s string) (*EtcdVersionPair, error) {
112 parts := strings.Split(s, "/")
113 if len(parts) != 2 {
114 return nil, fmt.Errorf("malformed version file, expected <major>.<minor>.<patch>/<storage> but got %s", s)
115 }
116 version, err := ParseEtcdVersion(parts[0])
117 if err != nil {
118 return nil, err
119 }
120 storageVersion, err := ParseEtcdStorageVersion(parts[1])
121 if err != nil {
122 return nil, err
123 }
124 return &EtcdVersionPair{version, storageVersion}, nil
125 }
126
127
128 func (vp *EtcdVersionPair) String() string {
129 return fmt.Sprintf("%s/%s", vp.version, vp.storageVersion)
130 }
131
132
133 func (vp *EtcdVersionPair) Equals(o *EtcdVersionPair) bool {
134 return vp.version.Equals(o.version) && vp.storageVersion == o.storageVersion
135 }
136
137
138
139 type SupportedVersions []*EtcdVersion
140
141
142
143 func (sv SupportedVersions) NextVersion(current *EtcdVersion) *EtcdVersion {
144 var nextVersion *EtcdVersion
145 for i, supportedVersion := range sv {
146 if current.MajorMinorEquals(supportedVersion) && len(sv) > i+1 {
147 nextVersion = sv[i+1]
148 }
149 }
150 return nextVersion
151 }
152
153
154
155 func (sv SupportedVersions) NextVersionPair(current *EtcdVersionPair) *EtcdVersionPair {
156 nextVersion := sv.NextVersion(current.version)
157 if nextVersion == nil {
158 return nil
159 }
160 storageVersion := storageEtcd3
161 if nextVersion.Major == 2 {
162 storageVersion = storageEtcd2
163 }
164 return &EtcdVersionPair{version: nextVersion, storageVersion: storageVersion}
165 }
166
167
168 func ParseSupportedVersions(list []string) (SupportedVersions, error) {
169 var err error
170 versions := make(SupportedVersions, len(list))
171 for i, v := range list {
172 versions[i], err = ParseEtcdVersion(strings.TrimSpace(v))
173 if err != nil {
174 return nil, err
175 }
176 }
177 return versions, nil
178 }
179
View as plain text