...

Source file src/k8s.io/kubernetes/cluster/images/etcd/migrate/versions.go

Documentation: k8s.io/kubernetes/cluster/images/etcd/migrate

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/blang/semver/v4"
    24  )
    25  
    26  // EtcdVersion specifies an etcd server binaries SemVer.
    27  type EtcdVersion struct {
    28  	semver.Version
    29  }
    30  
    31  // ParseEtcdVersion parses a SemVer string to an EtcdVersion.
    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  // MustParseEtcdVersion parses a SemVer string to an EtcdVersion and panics if the parse fails.
    41  func MustParseEtcdVersion(s string) *EtcdVersion {
    42  	return &EtcdVersion{semver.MustParse(s)}
    43  }
    44  
    45  // String returns the version in SemVer string format.
    46  func (v *EtcdVersion) String() string {
    47  	return v.Version.String()
    48  }
    49  
    50  // Equals returns true if the versions are exactly equal.
    51  func (v *EtcdVersion) Equals(o *EtcdVersion) bool {
    52  	return v.Version.Equals(o.Version)
    53  }
    54  
    55  // MajorMinorEquals returns true if the major and minor parts of the versions are equal;
    56  // if only patch versions differ, this returns true.
    57  func (v *EtcdVersion) MajorMinorEquals(o *EtcdVersion) bool {
    58  	return v.Major == o.Major && v.Minor == o.Minor
    59  }
    60  
    61  // EtcdStorageVersion identifies the storage version of an etcd data directory.
    62  type EtcdStorageVersion int
    63  
    64  const (
    65  	storageUnknown EtcdStorageVersion = iota
    66  	storageEtcd2
    67  	storageEtcd3
    68  )
    69  
    70  // ParseEtcdStorageVersion parses an etcd storage version string to an EtcdStorageVersion.
    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  // MustParseEtcdStorageVersion parses an etcd storage version string to an EtcdStorageVersion and
    83  // panics if the parse fails.
    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  // String returns the text representation of the EtcdStorageVersion, 'etcd2' or 'etcd3'.
    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  // EtcdVersionPair is composed of an etcd version and storage version.
   105  type EtcdVersionPair struct {
   106  	version        *EtcdVersion
   107  	storageVersion EtcdStorageVersion
   108  }
   109  
   110  // ParseEtcdVersionPair parses a "<version>/<storage-version>" string to an EtcdVersionPair.
   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  // String returns "<version>/<storage-version>" string of the EtcdVersionPair.
   128  func (vp *EtcdVersionPair) String() string {
   129  	return fmt.Sprintf("%s/%s", vp.version, vp.storageVersion)
   130  }
   131  
   132  // Equals returns true if both the versions and storage versions are exactly equal.
   133  func (vp *EtcdVersionPair) Equals(o *EtcdVersionPair) bool {
   134  	return vp.version.Equals(o.version) && vp.storageVersion == o.storageVersion
   135  }
   136  
   137  // SupportedVersions provides a list of etcd versions that are "supported" for some purpose.
   138  // The list must be sorted from lowest semantic version to high.
   139  type SupportedVersions []*EtcdVersion
   140  
   141  // NextVersion returns the next supported version after the given current version, or nil if no
   142  // next version exists.
   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  // NextVersionPair returns the next supported version after the given current version and infers
   154  // the storage version from the major version part of the next version.
   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  // ParseSupportedVersions parses a list of etcd versions.
   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