github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/upgrade/version.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package upgrade 15 16 import ( 17 "encoding/json" 18 19 "github.com/pingcap/tiflow/dm/common" 20 "github.com/pingcap/tiflow/dm/pkg/etcdutil" 21 "github.com/pingcap/tiflow/dm/pkg/terror" 22 "github.com/pingcap/tiflow/pkg/version" 23 clientv3 "go.etcd.io/etcd/client/v3" 24 ) 25 26 const ( 27 // The current internal version number of the DM cluster used when upgrading from an older version. 28 // NOTE: +1 when a new incompatible version is introduced, so it's different from the release version. 29 // NOTE: it's the version of the cluster (= the version of DM-master leader now), other component versions are not recorded yet. 30 currentInternalNo uint64 = 4 31 // The minimum internal version number of the DM cluster used when importing from v1.0.x. 32 minInternalNo uint64 = 0 33 ) 34 35 var ( 36 // CurrentVersion represents the current version of the cluster. 37 CurrentVersion = NewVersion(currentInternalNo, version.ReleaseVersion) 38 // MinVersion represents the minimum version of the cluster. 39 // this version only be set after finished importing from v1.0.x, but has not upgraded to the current version. 40 MinVersion = NewVersion(minInternalNo, "min-ver") 41 ) 42 43 // Version represents the version of the DM cluster used when upgrading from an older version. 44 type Version struct { 45 InternalNo uint64 `json:"internal-no"` // internal version number 46 ReleaseVer string `json:"release-ver"` // release version, like `v2.0.0`, human readable 47 } 48 49 // NewVersion creates a new instance of Version. 50 func NewVersion(internalNo uint64, releaseVer string) Version { 51 return Version{ 52 InternalNo: internalNo, 53 ReleaseVer: releaseVer, 54 } 55 } 56 57 // Compare compares the version with another version. 58 // NOTE: we only compare `InternalNo` now. 59 func (v Version) Compare(other Version) int { 60 if v.InternalNo < other.InternalNo { 61 return -1 62 } else if v.InternalNo > other.InternalNo { 63 return 1 64 } 65 return 0 66 } 67 68 // NotSet returns whether the version is not set. 69 func (v Version) NotSet() bool { 70 return v.InternalNo == 0 && v.ReleaseVer == "" 71 } 72 73 // String implements Stringer interface. 74 func (v Version) String() string { 75 s, _ := v.toJSON() 76 return s 77 } 78 79 // toJSON returns the string of JSON represent. 80 func (v Version) toJSON() (string, error) { 81 data, err := json.Marshal(v) 82 if err != nil { 83 return "", err 84 } 85 return string(data), nil 86 } 87 88 // versionFromJSON constructs version from its JSON represent. 89 func versionFromJSON(s string) (v Version, err error) { 90 err = json.Unmarshal([]byte(s), &v) 91 return 92 } 93 94 // PutVersion puts the version into etcd. 95 func PutVersion(cli *clientv3.Client, ver Version) (int64, error) { 96 value, err := ver.toJSON() 97 if err != nil { 98 return 0, err 99 } 100 op := clientv3.OpPut(common.ClusterVersionKey, value) 101 _, rev, err := etcdutil.DoTxnWithRepeatable(cli, etcdutil.ThenOpFunc(op)) 102 return rev, err 103 } 104 105 // GetVersion gets the version from etcd. 106 func GetVersion(cli *clientv3.Client) (Version, int64, error) { 107 txnResp, rev, err := etcdutil.DoTxnWithRepeatable(cli, etcdutil.ThenOpFunc(clientv3.OpGet(common.ClusterVersionKey))) 108 if err != nil { 109 return Version{}, 0, err 110 } 111 verResp := txnResp.Responses[0].GetResponseRange() 112 if verResp.Count == 0 { 113 return Version{}, rev, nil 114 } else if verResp.Count > 1 { 115 // this should not happen 116 return Version{}, rev, terror.ErrUpgradeVersionEtcdFail.Generatef("too many versions (%d) exist", verResp.Count) 117 } 118 119 ver, err := versionFromJSON(string(verResp.Kvs[0].Value)) 120 if err != nil { 121 return Version{}, rev, err 122 } 123 return ver, rev, nil 124 }