feat: check if need to upgrade image

Signed-off-by: yuyicai <yuyicai@hotmail.com>
This commit is contained in:
yuyicai
2025-03-09 16:01:56 +08:00
parent a16c1ef007
commit a682dfbc2c
3 changed files with 224 additions and 18 deletions

View File

@@ -90,6 +90,9 @@ const (
// hosts entry key word
HostsKeyWord = "# Add by KubeVPN"
GHCR_IMAGE_REGISTRY = "ghcr.io"
DOCKER_IMAGE_REGISTRY = "docker.io"
)
var (

View File

@@ -866,8 +866,8 @@ func (c *ConnectOptions) upgradeDeploy(ctx context.Context) error {
return nil
}
isNewer, _ := newer(clientImg, serverImg)
if deploy.Status.ReadyReplicas > 0 && !isNewer {
isNeedUpgrade, _ := newer(config.Version, clientImg, serverImg)
if deploy.Status.ReadyReplicas > 0 && !isNeedUpgrade {
return nil
}
@@ -973,7 +973,7 @@ func (c *ConnectOptions) upgradeDeploy(ctx context.Context) error {
return nil
}
func newer(clientImgStr, serverImgStr string) (bool, error) {
func newer(clientCliVersionStr, clientImgStr, serverImgStr string) (bool, error) {
clientImg, err := reference.ParseNormalizedNamed(clientImgStr)
if err != nil {
return false, err
@@ -982,27 +982,55 @@ func newer(clientImgStr, serverImgStr string) (bool, error) {
if err != nil {
return false, err
}
if reference.Domain(clientImg) != reference.Domain(serverImg) {
return false, nil
}
serverTag, ok := serverImg.(reference.NamedTagged)
if !ok {
return false, fmt.Errorf("can not convert server image")
}
serverVersion, err := goversion.NewVersion(serverTag.Tag())
if err != nil {
return false, err
}
clientTag, ok := clientImg.(reference.NamedTagged)
clientImgTag, ok := clientImg.(reference.NamedTagged)
if !ok {
return false, fmt.Errorf("can not convert client image")
}
clientVersion, err := goversion.NewVersion(clientTag.Tag())
// 1. if client image version is same as client cli version, does not need to upgrade
// kubevpn connect --image=ghcr.io/kubenetworks/kubevpn:v2.3.0 or --kubevpnconfig
// the kubevpn version is v2.3.1
if clientImgTag.Tag() != clientCliVersionStr {
// TODO: is it necessary to exit the process?
log.Warnf("\033[33mCurrent kubevpn cli version is %s, please use the same version of kubevpn image on flag \"--image\" or \"--kubevpnconfig\"\033[0m", clientCliVersionStr)
return false, nil
}
serverImgTag, ok := serverImg.(reference.NamedTagged)
if !ok {
return false, fmt.Errorf("can not convert server image")
}
// 2. if server image version is same as client cli version, does not need to upgrade
if serverImgTag.Tag() == clientCliVersionStr {
return false, nil
}
// 3. check custom server image registry
// if custom server image domain is not same as config.GHCR_IMAGE_REGISTRY
// and not same as config.DOCKER_IMAGE_REGISTRY
// and not same as client images(may be used --image)
// does not need to upgrade
serverImgDomain := reference.Domain(serverImg)
clientImgDomain := reference.Domain(clientImg)
if serverImgDomain != config.GHCR_IMAGE_REGISTRY && serverImgDomain != config.DOCKER_IMAGE_REGISTRY && serverImgDomain != clientImgDomain {
newImageStr := fmt.Sprintf("%s:%s", serverImg.Name(), clientCliVersionStr)
log.Warnf("\033[33mCurrent kubevpn cli version is %s, please manually upgrade 'kubevpn-traffic-manager' control plane pod container image to %s\033[0m", clientCliVersionStr, newImageStr)
return false, nil
}
serverImgVersion, err := goversion.NewVersion(serverImgTag.Tag())
if err != nil {
return false, err
}
return clientVersion.GreaterThan(serverVersion), nil
clientImgVersion, err := goversion.NewVersion(clientImgTag.Tag())
if err != nil {
return false, err
}
// 4. check client image version is greater than server image version
return clientImgVersion.GreaterThan(serverImgVersion), nil
}
func (c *ConnectOptions) Equal(a *ConnectOptions) bool {

View File

@@ -149,3 +149,178 @@ func TestRemoveCIDRsContainingIPs(t *testing.T) {
})
}
}
func Test_newer(t *testing.T) {
type args struct {
clientVersionStr string
clientImgStr string
serverImgStr string
}
tests := []struct {
name string
args args
want bool
wantErr bool
}{
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: naison/kubevpn:v1.0.0
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) newer than server(naison/kubevpn:v1.0.0)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "naison/kubevpn:v1.0.0",
},
want: true,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: docker.io/naison/kubevpn:v1.0.0
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) newer than server(docker.io/naison/kubevpn:v1.0.0)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "docker.io/naison/kubevpn:v1.0.0",
},
want: true,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: naison/kubevpn:v1.2.1
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) same as server(naison/kubevpn:v1.2.1)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "naison/kubevpn:v1.2.1",
},
want: false,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: docker.io/naison/kubevpn:v1.2.1
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) same as server(docker.io/naison/kubevpn:v1.2.1)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "docker.io/naison/kubevpn:v1.2.1",
},
want: false,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: docker.io/naison/kubevpn:v1.3.1
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) older as server(docker.io/naison/kubevpn:v1.3.1)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "docker.io/naison/kubevpn:v1.3.1",
},
want: false,
wantErr: false,
},
// client version: v1.3.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1 (not same as client version, --image=xxx)
// server image: ghcr.io/kubenetworks/kubevpn:v1.2.1
{
name: "Valid case - client cli version(v1.3.1) not same as client image(ghcr.io/kubenetworks/kubevpn:v1.2.1)",
args: args{
clientVersionStr: "v1.3.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
},
want: false,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: ghcr.io/kubenetworks/kubevpn:v1.0.1
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) newer than server(ghcr.io/kubenetworks/kubevpn:v1.0.1)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "ghcr.io/kubenetworks/kubevpn:v1.0.1",
},
want: true,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: ghcr.io/kubenetworks/kubevpn:v1.2.1
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) same as server(ghcr.io/kubenetworks/kubevpn:v1.2.1)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
},
want: false,
wantErr: false,
},
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: ghcr.io/kubenetworks/kubevpn:v1.3.1
{
name: "Valid case - client(ghcr.io/kubenetworks/kubevpn:v1.2.1) older as server(ghcr.io/kubenetworks/kubevpn:v1.3.1)",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "ghcr.io/kubenetworks/kubevpn:v1.3.1",
},
want: false,
wantErr: false,
},
// custom server image registry, but client image is not same as client version, does not upgrade
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: mykubevpn.io/kubenetworks/kubevpn:v1.1.1
{
name: "custom server image registry, but client image is not same as client version, does not upgrade",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "ghcr.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "mykubevpn.io/kubenetworks/kubevpn:v1.1.1",
},
want: false,
wantErr: false,
},
// custom server image registry, client image is same as client version, upgrade
// client version: v1.2.1
// client image: ghcr.io/kubenetworks/kubevpn:v1.2.1
// server image: mykubevpn.io/kubenetworks/kubevpn:v1.1.1
{
name: "custom server image registry, client image is same as client version, upgrade",
args: args{
clientVersionStr: "v1.2.1",
clientImgStr: "mykubevpn.io/kubenetworks/kubevpn:v1.2.1",
serverImgStr: "mykubevpn.io/kubenetworks/kubevpn:v1.1.1",
},
want: true,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := newer(tt.args.clientVersionStr, tt.args.clientImgStr, tt.args.serverImgStr)
if (err != nil) != tt.wantErr {
t.Errorf("newer() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("newer() got = %v, want %v", got, tt.want)
}
})
}
}