KubeOS:sync code from source master branch
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
This commit is contained in:
parent
fbb9b2debd
commit
1d36b74685
479
0001-KubeOS-add-unit-tests-of-containerd-and-docker-modif.patch
Normal file
479
0001-KubeOS-add-unit-tests-of-containerd-and-docker-modif.patch
Normal file
@ -0,0 +1,479 @@
|
||||
From 790d53dc581874575aef1777122856a59bcdbf8b Mon Sep 17 00:00:00 2001
|
||||
From: liyuanr <liyuanrong1@huawei.com>
|
||||
Date: Thu, 3 Aug 2023 22:18:23 +0800
|
||||
Subject: [PATCH 01/17] KubeOS:add unit tests of containerd and docker,modify
|
||||
code for cleancode
|
||||
|
||||
Add unit tests of using containerd or docker to upgrade.
|
||||
Modify code for cleancode and fix issue of ctr images pull
|
||||
|
||||
Signed-off-by: liyuanr <liyuanrong1@huawei.com>
|
||||
---
|
||||
cmd/agent/server/containerd_image.go | 8 +-
|
||||
cmd/agent/server/containerd_image_test.go | 139 ++++++++++++++++++++++
|
||||
cmd/agent/server/docker_image.go | 2 +-
|
||||
cmd/agent/server/docker_image_test.go | 88 ++++++++++++--
|
||||
cmd/agent/server/utils.go | 102 ++++++++--------
|
||||
5 files changed, 272 insertions(+), 67 deletions(-)
|
||||
create mode 100644 cmd/agent/server/containerd_image_test.go
|
||||
|
||||
diff --git a/cmd/agent/server/containerd_image.go b/cmd/agent/server/containerd_image.go
|
||||
index f180fb5..fd61274 100644
|
||||
--- a/cmd/agent/server/containerd_image.go
|
||||
+++ b/cmd/agent/server/containerd_image.go
|
||||
@@ -23,9 +23,7 @@ import (
|
||||
pb "openeuler.org/KubeOS/cmd/agent/api"
|
||||
)
|
||||
|
||||
-var (
|
||||
- defaultNamespace = "k8s.io"
|
||||
-)
|
||||
+const defaultNamespace = "k8s.io"
|
||||
|
||||
type conImageHandler struct{}
|
||||
|
||||
@@ -56,7 +54,7 @@ func (c conImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath prep
|
||||
}
|
||||
} else {
|
||||
containerdCommand = "ctr"
|
||||
- if err := runCommand("ctr", "-n", defaultNamespace, "images", "pull", "--host-dir",
|
||||
+ if err := runCommand("ctr", "-n", defaultNamespace, "images", "pull", "--hosts-dir",
|
||||
"/etc/containerd/certs.d", imageName); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -76,7 +74,7 @@ func (c conImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath prep
|
||||
return "", err
|
||||
}
|
||||
defer checkAndCleanMount(mountPath)
|
||||
- if err := copyFile(neededPath.tarPath, mountPath+"/"+rootfsArchive); err != nil {
|
||||
+ if err := copyFile(neededPath.tarPath, mountPath+"/"+neededPath.rootfsFile); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "", nil
|
||||
diff --git a/cmd/agent/server/containerd_image_test.go b/cmd/agent/server/containerd_image_test.go
|
||||
new file mode 100644
|
||||
index 0000000..d7133c3
|
||||
--- /dev/null
|
||||
+++ b/cmd/agent/server/containerd_image_test.go
|
||||
@@ -0,0 +1,139 @@
|
||||
+/*
|
||||
+ * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
+ * KubeOS is licensed under the Mulan PSL v2.
|
||||
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
+ * You may obtain a copy of Mulan PSL v2 at:
|
||||
+ * http://license.coscl.org.cn/MulanPSL2
|
||||
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||||
+ * PURPOSE.
|
||||
+ * See the Mulan PSL v2 for more details.
|
||||
+ */
|
||||
+
|
||||
+// Package server implements server of os-agent and listener of os-agent server. The server uses gRPC interface.
|
||||
+package server
|
||||
+
|
||||
+import (
|
||||
+ "os"
|
||||
+ "testing"
|
||||
+
|
||||
+ "github.com/agiledragon/gomonkey/v2"
|
||||
+ pb "openeuler.org/KubeOS/cmd/agent/api"
|
||||
+)
|
||||
+
|
||||
+func Test_conImageHandler_downloadImage(t *testing.T) {
|
||||
+ type args struct {
|
||||
+ req *pb.UpdateRequest
|
||||
+ }
|
||||
+ tests := []struct {
|
||||
+ name string
|
||||
+ c conImageHandler
|
||||
+ args args
|
||||
+ want string
|
||||
+ wantErr bool
|
||||
+ }{
|
||||
+
|
||||
+ {
|
||||
+ name: "pullImageError",
|
||||
+ c: conImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{ContainerImage: "testError"},
|
||||
+ },
|
||||
+ want: "",
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "checkSumError",
|
||||
+ c: conImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{ContainerImage: "docker.io/library/hello-world:latest"},
|
||||
+ },
|
||||
+ want: "",
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "normal",
|
||||
+ c: conImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{
|
||||
+ ContainerImage: "docker.io/library/hello-world:latest",
|
||||
+ },
|
||||
+ },
|
||||
+ want: "update-test1/upadte.img",
|
||||
+ wantErr: false,
|
||||
+ },
|
||||
+ }
|
||||
+ patchPrepareEnv := gomonkey.ApplyFunc(prepareEnv, func() (preparePath, error) {
|
||||
+ return preparePath{updatePath: "update-test1/",
|
||||
+ mountPath: "update-test1/mountPath",
|
||||
+ tarPath: "update-test1/mountPath/hello",
|
||||
+ imagePath: "update-test1/upadte.img",
|
||||
+ rootfsFile: "hello"}, nil
|
||||
+ })
|
||||
+ defer patchPrepareEnv.Reset()
|
||||
+ patchCreateOSImage := gomonkey.ApplyFunc(createOSImage, func(neededPath preparePath) (string, error) {
|
||||
+ return "update-test1/upadte.img", nil
|
||||
+ })
|
||||
+ defer patchCreateOSImage.Reset()
|
||||
+
|
||||
+ if err := os.MkdirAll("update-test1/mountPath", os.ModePerm); err != nil {
|
||||
+ t.Errorf("create test dir error = %v", err)
|
||||
+ return
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ c := conImageHandler{}
|
||||
+ if tt.name == "normal" {
|
||||
+ imageDigests, err := getOCIImageDigest("crictl", "docker.io/library/hello-world:latest")
|
||||
+ if err != nil {
|
||||
+ t.Errorf("conImageHandler.getRootfsArchive() get oci image digests error = %v", err)
|
||||
+ }
|
||||
+ tt.args.req.CheckSum = imageDigests
|
||||
+ }
|
||||
+ got, err := c.downloadImage(tt.args.req)
|
||||
+ if (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("conImageHandler.downloadImage() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ return
|
||||
+ }
|
||||
+ if got != tt.want {
|
||||
+ t.Errorf("conImageHandler.downloadImage() = %v, want %v", got, tt.want)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+ defer func() {
|
||||
+ if err := runCommand("crictl", "rmi", "docker.io/library/hello-world:latest"); err != nil {
|
||||
+ t.Errorf("remove kubeos-temp container error = %v", err)
|
||||
+ }
|
||||
+ if err := os.RemoveAll("update-test1"); err != nil {
|
||||
+ t.Errorf("remove update-test error = %v", err)
|
||||
+ }
|
||||
+ }()
|
||||
+}
|
||||
+
|
||||
+func Test_copyFile(t *testing.T) {
|
||||
+ type args struct {
|
||||
+ dstFileName string
|
||||
+ srcFileName string
|
||||
+ }
|
||||
+ tests := []struct {
|
||||
+ name string
|
||||
+ args args
|
||||
+ wantErr bool
|
||||
+ }{
|
||||
+ {
|
||||
+ name: "srcFileNotExist",
|
||||
+ args: args{
|
||||
+ dstFileName: "bbb.txt",
|
||||
+ srcFileName: "aaa.txt",
|
||||
+ },
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ if err := copyFile(tt.args.dstFileName, tt.args.srcFileName); (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("copyFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
diff --git a/cmd/agent/server/docker_image.go b/cmd/agent/server/docker_image.go
|
||||
index 23e596b..0b6ee35 100644
|
||||
--- a/cmd/agent/server/docker_image.go
|
||||
+++ b/cmd/agent/server/docker_image.go
|
||||
@@ -61,7 +61,7 @@ func (d dockerImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath p
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
- if err := runCommand("docker", "cp", containerId+":/"+rootfsArchive, neededPath.updatePath); err != nil {
|
||||
+ if err := runCommand("docker", "cp", containerId+":/"+neededPath.rootfsFile, neededPath.updatePath); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
diff --git a/cmd/agent/server/docker_image_test.go b/cmd/agent/server/docker_image_test.go
|
||||
index 9987939..2dbf337 100644
|
||||
--- a/cmd/agent/server/docker_image_test.go
|
||||
+++ b/cmd/agent/server/docker_image_test.go
|
||||
@@ -17,38 +17,102 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
+ "github.com/agiledragon/gomonkey/v2"
|
||||
pb "openeuler.org/KubeOS/cmd/agent/api"
|
||||
)
|
||||
|
||||
-func TestpullOSImage(t *testing.T) {
|
||||
+func Test_dockerImageHandler_downloadImage(t *testing.T) {
|
||||
type args struct {
|
||||
req *pb.UpdateRequest
|
||||
}
|
||||
- os.Mkdir("/persist", os.ModePerm)
|
||||
tests := []struct {
|
||||
name string
|
||||
+ d dockerImageHandler
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
- {name: "pull image error", args: args{req: &pb.UpdateRequest{
|
||||
- DockerImage: "test",
|
||||
- }}, want: "", wantErr: true},
|
||||
- {name: "normal", args: args{req: &pb.UpdateRequest{
|
||||
- DockerImage: "centos",
|
||||
- }}, want: "/persist/update.img", wantErr: false},
|
||||
+ {
|
||||
+ name: "pullImageError",
|
||||
+ d: dockerImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{ContainerImage: "testError"},
|
||||
+ },
|
||||
+ want: "",
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
+
|
||||
+ {
|
||||
+ name: "checkSumError",
|
||||
+ d: dockerImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{ContainerImage: "hello-world", CheckSum: "aaaaaa"},
|
||||
+ },
|
||||
+ want: "",
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
+
|
||||
+ {
|
||||
+ name: "normal",
|
||||
+ d: dockerImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{ContainerImage: "hello-world"},
|
||||
+ },
|
||||
+ want: "update-test/upadte.img",
|
||||
+ wantErr: false,
|
||||
+ },
|
||||
+ }
|
||||
+ patchPrepareEnv := gomonkey.ApplyFunc(prepareEnv, func() (preparePath, error) {
|
||||
+ return preparePath{updatePath: "update-test/",
|
||||
+ mountPath: "update-test/mountPath",
|
||||
+ tarPath: "update-test/mountPath/hello",
|
||||
+ imagePath: "update-test/upadte.img",
|
||||
+ rootfsFile: "hello"}, nil
|
||||
+ })
|
||||
+ defer patchPrepareEnv.Reset()
|
||||
+
|
||||
+ patchCreateOSImage := gomonkey.ApplyFunc(createOSImage, func(neededPath preparePath) (string, error) {
|
||||
+ return "update-test/upadte.img", nil
|
||||
+ })
|
||||
+ defer patchCreateOSImage.Reset()
|
||||
+
|
||||
+ if err := os.MkdirAll("update-test/mountPath", os.ModePerm); err != nil {
|
||||
+ t.Errorf("create test dir error = %v", err)
|
||||
+ return
|
||||
}
|
||||
+
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
- got, err := pullOSImage(tt.args.req)
|
||||
+ if tt.name == "normal" {
|
||||
+ _, err := runCommandWithOut("docker", "create", "--name", "kubeos-temp", "hello-world")
|
||||
+ if err != nil {
|
||||
+ t.Errorf("Test_dockerImageHandler_getRootfsArchive create container error = %v", err)
|
||||
+ return
|
||||
+ }
|
||||
+ imageDigests, err := getOCIImageDigest("docker", "hello-world")
|
||||
+
|
||||
+ if err != nil {
|
||||
+ t.Errorf("Test_dockerImageHandler_getRootfsArchive get oci image digests error = %v", err)
|
||||
+ }
|
||||
+ tt.args.req.CheckSum = imageDigests
|
||||
+ }
|
||||
+ d := dockerImageHandler{}
|
||||
+ got, err := d.downloadImage(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
- t.Errorf("pullOSImage() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ t.Errorf("dockerImageHandler.downloadImage() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
- t.Errorf("pullOSImage() = %v, want %v", got, tt.want)
|
||||
+ t.Errorf("dockerImageHandler.downloadImage() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
- defer os.RemoveAll("/persist")
|
||||
+ defer func() {
|
||||
+ if err := runCommand("docker", "rmi", "hello-world"); err != nil {
|
||||
+ t.Errorf("remove kubeos-temp container error = %v", err)
|
||||
+ }
|
||||
+ if err := os.RemoveAll("update-test"); err != nil {
|
||||
+ t.Errorf("remove update-test error = %v", err)
|
||||
+ }
|
||||
+ }()
|
||||
}
|
||||
diff --git a/cmd/agent/server/utils.go b/cmd/agent/server/utils.go
|
||||
index c8a72c3..7134d74 100644
|
||||
--- a/cmd/agent/server/utils.go
|
||||
+++ b/cmd/agent/server/utils.go
|
||||
@@ -31,10 +31,7 @@ import (
|
||||
const (
|
||||
needGBSize = 3 // the max size of update files needed
|
||||
// KB is 1024 B
|
||||
- KB = 1024
|
||||
-)
|
||||
-
|
||||
-var (
|
||||
+ KB = 1024
|
||||
rootfsArchive = "os.tar"
|
||||
updateDir = "KubeOS-Update"
|
||||
mountDir = "kubeos-update"
|
||||
@@ -51,6 +48,7 @@ type preparePath struct {
|
||||
mountPath string
|
||||
tarPath string
|
||||
imagePath string
|
||||
+ rootfsFile string
|
||||
}
|
||||
|
||||
func runCommand(name string, args ...string) error {
|
||||
@@ -192,9 +190,10 @@ func prepareEnv() (preparePath, error) {
|
||||
if err := checkDiskSize(needGBSize, PersistDir); err != nil {
|
||||
return preparePath{}, err
|
||||
}
|
||||
+ rootfsFile := rootfsArchive
|
||||
updatePath := splicePath(PersistDir, updateDir)
|
||||
mountPath := splicePath(updatePath, mountDir)
|
||||
- tarPath := splicePath(updatePath, rootfsArchive)
|
||||
+ tarPath := splicePath(updatePath, rootfsFile)
|
||||
imagePath := splicePath(PersistDir, osImageName)
|
||||
|
||||
if err := cleanSpace(updatePath, mountPath, imagePath); err != nil {
|
||||
@@ -208,6 +207,7 @@ func prepareEnv() (preparePath, error) {
|
||||
mountPath: mountPath,
|
||||
tarPath: tarPath,
|
||||
imagePath: imagePath,
|
||||
+ rootfsFile: rootfsFile,
|
||||
}
|
||||
return upgradePath, nil
|
||||
}
|
||||
@@ -284,50 +284,9 @@ func checkFileExist(path string) (bool, error) {
|
||||
}
|
||||
|
||||
func checkOCIImageDigestMatch(containerRuntime string, imageName string, checkSum string) error {
|
||||
- var cmdOutput string
|
||||
- var err error
|
||||
- switch containerRuntime {
|
||||
- case "crictl":
|
||||
- cmdOutput, err = runCommandWithOut("crictl", "inspecti", "--output", "go-template",
|
||||
- "--template", "{{.status.repoDigests}}", imageName)
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- case "docker":
|
||||
- cmdOutput, err = runCommandWithOut("docker", "inspect", "--format", "{{.RepoDigests}}", imageName)
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- case "ctr":
|
||||
- cmdOutput, err = runCommandWithOut("ctr", "-n", "k8s.io", "images", "ls", "name=="+imageName)
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- // after Fields, we get slice like [REF TYPE DIGEST SIZE PLATFORMS LABELS x x x x x x]
|
||||
- // the digest is the position 8 element
|
||||
- imageDigest := strings.Split(strings.Fields(cmdOutput)[8], ":")[1]
|
||||
- if imageDigest != checkSum {
|
||||
- logrus.Errorln("checkSumFailed ", imageDigest, " mismatch to ", checkSum)
|
||||
- return fmt.Errorf("checkSumFailed %s mismatch to %s", imageDigest, checkSum)
|
||||
- }
|
||||
- return nil
|
||||
- default:
|
||||
- logrus.Errorln("containerRuntime ", containerRuntime, " cannot be recognized")
|
||||
- return fmt.Errorf("containerRuntime %s cannot be recognized", containerRuntime)
|
||||
- }
|
||||
- // cmdOutput format is as follows:
|
||||
- // [imageRepository/imageName:imageTag@sha256:digests]
|
||||
- // parse the output and get digest
|
||||
- var imageDigests string
|
||||
- outArray := strings.Split(cmdOutput, "@")
|
||||
- if strings.HasPrefix(outArray[len(outArray)-1], "sha256") {
|
||||
- pasredArray := strings.Split(strings.TrimSuffix(outArray[len(outArray)-1], "]"), ":")
|
||||
- // 2 is the expected length of the array after dividing "imageName:imageTag@sha256:digests" based on ':'
|
||||
- rightLen := 2
|
||||
- if len(pasredArray) == rightLen {
|
||||
- digestIndex := 1 // 1 is the index of digest data in pasredArray
|
||||
- imageDigests = pasredArray[digestIndex]
|
||||
- }
|
||||
+ imageDigests, err := getOCIImageDigest(containerRuntime, imageName)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
}
|
||||
if imageDigests == "" {
|
||||
logrus.Errorln("error when get ", imageName, " digests")
|
||||
@@ -367,3 +326,48 @@ func isValidImageName(image string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+
|
||||
+func getOCIImageDigest(containerRuntime string, imageName string) (string, error) {
|
||||
+ var cmdOutput string
|
||||
+ var err error
|
||||
+ var imageDigests string
|
||||
+ switch containerRuntime {
|
||||
+ case "crictl":
|
||||
+ cmdOutput, err = runCommandWithOut("crictl", "inspecti", "--output", "go-template",
|
||||
+ "--template", "{{.status.repoDigests}}", imageName)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+ case "docker":
|
||||
+ cmdOutput, err = runCommandWithOut("docker", "inspect", "--format", "{{.RepoDigests}}", imageName)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+ case "ctr":
|
||||
+ cmdOutput, err = runCommandWithOut("ctr", "-n", "k8s.io", "images", "ls", "name=="+imageName)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+ // after Fields, we get slice like [REF TYPE DIGEST SIZE PLATFORMS LABELS x x x x x x]
|
||||
+ // the digest is the position 8 element
|
||||
+ imageDigest := strings.Split(strings.Fields(cmdOutput)[8], ":")[1]
|
||||
+ return imageDigest, nil
|
||||
+ default:
|
||||
+ logrus.Errorln("containerRuntime ", containerRuntime, " cannot be recognized")
|
||||
+ return "", fmt.Errorf("containerRuntime %s cannot be recognized", containerRuntime)
|
||||
+ }
|
||||
+ // cmdOutput format is as follows:
|
||||
+ // [imageRepository/imageName:imageTag@sha256:digests]
|
||||
+ // parse the output and get digest
|
||||
+ outArray := strings.Split(cmdOutput, "@")
|
||||
+ if strings.HasPrefix(outArray[len(outArray)-1], "sha256") {
|
||||
+ pasredArray := strings.Split(strings.TrimSuffix(outArray[len(outArray)-1], "]"), ":")
|
||||
+ // 2 is the expected length of the array after dividing "imageName:imageTag@sha256:digests" based on ':'
|
||||
+ rightLen := 2
|
||||
+ if len(pasredArray) == rightLen {
|
||||
+ digestIndex := 1 // 1 is the index of digest data in pasredArray
|
||||
+ imageDigests = pasredArray[digestIndex]
|
||||
+ }
|
||||
+ }
|
||||
+ return imageDigests, nil
|
||||
+}
|
||||
--
|
||||
2.39.0
|
||||
|
||||
346
0002-KubeOS-refactor-assignUpgrade-function.patch
Normal file
346
0002-KubeOS-refactor-assignUpgrade-function.patch
Normal file
@ -0,0 +1,346 @@
|
||||
From 64e36143591c014609fc517bcd6ee0f3ae1087fc Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Thu, 3 Aug 2023 11:01:22 +0800
|
||||
Subject: [PATCH 02/17] KubeOS: refactor assignUpgrade function the
|
||||
assignUpgrade function is refactored for maintainability replace
|
||||
"osinstance-node" to variable
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/operator/controllers/os_controller.go | 73 ++++++-----
|
||||
.../controllers/os_controller_test.go | 121 +++++++++++++++++-
|
||||
cmd/proxy/controllers/os_controller.go | 2 +-
|
||||
cmd/proxy/controllers/os_controller_test.go | 9 ++
|
||||
pkg/values/values.go | 6 +-
|
||||
5 files changed, 176 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/cmd/operator/controllers/os_controller.go b/cmd/operator/controllers/os_controller.go
|
||||
index f86a0b2..620739b 100644
|
||||
--- a/cmd/operator/controllers/os_controller.go
|
||||
+++ b/cmd/operator/controllers/os_controller.go
|
||||
@@ -109,7 +109,7 @@ func (r *OSReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
func (r *OSReconciler) DeleteOSInstance(e event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||
ctx := context.Background()
|
||||
hostname := e.Object.GetName()
|
||||
- labelSelector := labels.SelectorFromSet(labels.Set{"upgrade.openeuler.org/osinstance-node": hostname})
|
||||
+ labelSelector := labels.SelectorFromSet(labels.Set{values.LabelOSinstance: hostname})
|
||||
osInstanceList := &upgradev1.OSInstanceList{}
|
||||
if err := r.List(ctx, osInstanceList, client.MatchingLabelsSelector{Selector: labelSelector}); err != nil {
|
||||
log.Error(err, "unable to list osInstances")
|
||||
@@ -157,12 +157,23 @@ func assignUpgrade(ctx context.Context, r common.ReadStatusWriter, os upgradev1.
|
||||
return false, err
|
||||
}
|
||||
|
||||
- nodes, err := getNodes(ctx, r, limit+1, *requirement, *reqMaster) // one more to see if all node updated
|
||||
+ nodes, err := getNodes(ctx, r, limit+1, *requirement, *reqMaster) // one more to see if all nodes updated
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
- var count = 0
|
||||
+ // Upgrade OS for selected nodes
|
||||
+ count, err := upgradeNodes(ctx, r, &os, nodes, limit)
|
||||
+ if err != nil {
|
||||
+ return false, err
|
||||
+ }
|
||||
+
|
||||
+ return count >= limit, nil
|
||||
+}
|
||||
+
|
||||
+func upgradeNodes(ctx context.Context, r common.ReadStatusWriter, os *upgradev1.OS,
|
||||
+ nodes []corev1.Node, limit int) (int, error) {
|
||||
+ var count int
|
||||
for _, node := range nodes {
|
||||
if count >= limit {
|
||||
break
|
||||
@@ -170,43 +181,45 @@ func assignUpgrade(ctx context.Context, r common.ReadStatusWriter, os upgradev1.
|
||||
osVersionNode := node.Status.NodeInfo.OSImage
|
||||
if os.Spec.OSVersion != osVersionNode {
|
||||
var osInstance upgradev1.OSInstance
|
||||
- if err = r.Get(ctx, types.NamespacedName{Namespace: nameSpace, Name: node.Name}, &osInstance); err != nil {
|
||||
+ if err := r.Get(ctx, types.NamespacedName{Namespace: os.GetObjectMeta().GetNamespace(), Name: node.Name}, &osInstance); err != nil {
|
||||
if err = client.IgnoreNotFound(err); err != nil {
|
||||
log.Error(err, "failed to get osInstance "+node.Name)
|
||||
- return false, err
|
||||
+ return count, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
+ updateNodeAndOSins(ctx, r, os, &node, &osInstance)
|
||||
count++
|
||||
- node.Labels[values.LabelUpgrading] = ""
|
||||
- expUpVersion := os.Spec.UpgradeConfigs.Version
|
||||
- osiUpVersion := osInstance.Spec.UpgradeConfigs.Version
|
||||
- if osiUpVersion != expUpVersion {
|
||||
- osInstance.Spec.UpgradeConfigs = os.Spec.UpgradeConfigs
|
||||
- }
|
||||
- expSysVersion := os.Spec.SysConfigs.Version
|
||||
- osiSysVersion := osInstance.Spec.SysConfigs.Version
|
||||
- if osiSysVersion != expSysVersion {
|
||||
- osInstance.Spec.SysConfigs = os.Spec.SysConfigs
|
||||
- for i, config := range osInstance.Spec.SysConfigs.Configs {
|
||||
- if config.Model == "grub.cmdline.current" {
|
||||
- osInstance.Spec.SysConfigs.Configs[i].Model = "grub.cmdline.next"
|
||||
- }
|
||||
- if config.Model == "grub.cmdline.next" {
|
||||
- osInstance.Spec.SysConfigs.Configs[i].Model = "grub.cmdline.current"
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- osInstance.Spec.NodeStatus = values.NodeStatusUpgrade.String()
|
||||
- if err = r.Update(ctx, &osInstance); err != nil {
|
||||
- log.Error(err, "unable to update", "osInstance", osInstance.Name)
|
||||
+ }
|
||||
+ }
|
||||
+ return count, nil
|
||||
+}
|
||||
+
|
||||
+func updateNodeAndOSins(ctx context.Context, r common.ReadStatusWriter, os *upgradev1.OS,
|
||||
+ node *corev1.Node, osInstance *upgradev1.OSInstance) {
|
||||
+ if osInstance.Spec.UpgradeConfigs.Version != os.Spec.UpgradeConfigs.Version {
|
||||
+ osInstance.Spec.UpgradeConfigs = os.Spec.UpgradeConfigs
|
||||
+ }
|
||||
+ if osInstance.Spec.SysConfigs.Version != os.Spec.SysConfigs.Version {
|
||||
+ osInstance.Spec.SysConfigs = os.Spec.SysConfigs
|
||||
+ // exchange "grub.cmdline.current" and "grub.cmdline.next"
|
||||
+ for i, config := range osInstance.Spec.SysConfigs.Configs {
|
||||
+ if config.Model == "grub.cmdline.current" {
|
||||
+ osInstance.Spec.SysConfigs.Configs[i].Model = "grub.cmdline.next"
|
||||
}
|
||||
- if err = r.Update(ctx, &node); err != nil {
|
||||
- log.Error(err, "unable to label", "node", node.Name)
|
||||
+ if config.Model == "grub.cmdline.next" {
|
||||
+ osInstance.Spec.SysConfigs.Configs[i].Model = "grub.cmdline.current"
|
||||
}
|
||||
}
|
||||
}
|
||||
- return count >= limit, nil
|
||||
+ osInstance.Spec.NodeStatus = values.NodeStatusUpgrade.String()
|
||||
+ if err := r.Update(ctx, osInstance); err != nil {
|
||||
+ log.Error(err, "unable to update", "osInstance", osInstance.Name)
|
||||
+ }
|
||||
+ node.Labels[values.LabelUpgrading] = ""
|
||||
+ if err := r.Update(ctx, node); err != nil {
|
||||
+ log.Error(err, "unable to label", "node", node.Name)
|
||||
+ }
|
||||
}
|
||||
|
||||
func assignConfig(ctx context.Context, r common.ReadStatusWriter, sysConfigs upgradev1.SysConfigs,
|
||||
diff --git a/cmd/operator/controllers/os_controller_test.go b/cmd/operator/controllers/os_controller_test.go
|
||||
index 30a773c..a391005 100644
|
||||
--- a/cmd/operator/controllers/os_controller_test.go
|
||||
+++ b/cmd/operator/controllers/os_controller_test.go
|
||||
@@ -134,6 +134,9 @@ var _ = Describe("OsController", func() {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: node1Name,
|
||||
Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node1Name,
|
||||
+ },
|
||||
},
|
||||
Spec: upgradev1.OSInstanceSpec{
|
||||
SysConfigs: upgradev1.SysConfigs{
|
||||
@@ -189,7 +192,7 @@ var _ = Describe("OsController", func() {
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v1"))
|
||||
|
||||
- time.Sleep(2 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
+ time.Sleep(1 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
osInsCRLookupKey = types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
createdOSIns = &upgradev1.OSInstance{}
|
||||
Eventually(func() bool {
|
||||
@@ -301,7 +304,7 @@ var _ = Describe("OsController", func() {
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v1"))
|
||||
|
||||
- time.Sleep(2 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
+ time.Sleep(1 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
configedOSIns := &upgradev1.OSInstance{}
|
||||
Eventually(func() bool {
|
||||
err := k8sClient.Get(ctx, osInsCRLookupKey, configedOSIns)
|
||||
@@ -388,4 +391,118 @@ var _ = Describe("OsController", func() {
|
||||
})
|
||||
})
|
||||
|
||||
+ Context("When we want to upgrade and do sysconfigs which contain grub.cmd.current and .next", func() {
|
||||
+ It("Should exchange .current and .next", func() {
|
||||
+ ctx := context.Background()
|
||||
+
|
||||
+ // create Node
|
||||
+ node1Name = "test-node-" + uuid.New().String()
|
||||
+ node1 := &v1.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node1Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ "beta.kubernetes.io/os": "linux",
|
||||
+ },
|
||||
+ },
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "v1",
|
||||
+ Kind: "Node",
|
||||
+ },
|
||||
+ Status: v1.NodeStatus{
|
||||
+ NodeInfo: v1.NodeSystemInfo{
|
||||
+ OSImage: "KubeOS v1",
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+ err := k8sClient.Create(ctx, node1)
|
||||
+ Expect(err).ToNot(HaveOccurred())
|
||||
+ existingNode := &v1.Node{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(context.Background(),
|
||||
+ types.NamespacedName{Name: node1Name, Namespace: testNamespace}, existingNode)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+
|
||||
+ // create OSInstance
|
||||
+ OSIns := &upgradev1.OSInstance{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ Kind: "OSInstance",
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node1Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node1Name,
|
||||
+ },
|
||||
+ },
|
||||
+ Spec: upgradev1.OSInstanceSpec{
|
||||
+ SysConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v1",
|
||||
+ Configs: []upgradev1.SysConfig{},
|
||||
+ },
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}},
|
||||
+ },
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
+
|
||||
+ // Check that the corresponding OSIns CR has been created
|
||||
+ osInsCRLookupKey := types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
+ createdOSIns := &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node1Name))
|
||||
+
|
||||
+ // create OS CR
|
||||
+ OS := &upgradev1.OS{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ Kind: "OS",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: OSName,
|
||||
+ Namespace: testNamespace,
|
||||
+ },
|
||||
+ Spec: upgradev1.OSSpec{
|
||||
+ OpsType: "upgrade",
|
||||
+ MaxUnavailable: 3,
|
||||
+ OSVersion: "KubeOS v2",
|
||||
+ FlagSafe: true,
|
||||
+ MTLS: false,
|
||||
+ EvictPodForce: true,
|
||||
+ SysConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v2",
|
||||
+ Configs: []upgradev1.SysConfig{
|
||||
+ {Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}},
|
||||
+ {Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}},
|
||||
+ },
|
||||
+ },
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}},
|
||||
+ },
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OS)).Should(Succeed())
|
||||
+
|
||||
+ // Check that the corresponding OS CR has been created
|
||||
+ osCRLookupKey := types.NamespacedName{Name: OSName, Namespace: testNamespace}
|
||||
+ createdOS := &upgradev1.OS{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osCRLookupKey, createdOS)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v2"))
|
||||
+
|
||||
+ time.Sleep(1 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
+ osInsCRLookupKey = types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
+ createdOSIns = &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns.Spec.SysConfigs.Configs[0]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}}))
|
||||
+ Expect(createdOSIns.Spec.SysConfigs.Configs[1]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}}))
|
||||
+ })
|
||||
+ })
|
||||
})
|
||||
diff --git a/cmd/proxy/controllers/os_controller.go b/cmd/proxy/controllers/os_controller.go
|
||||
index a17afac..b0b17e7 100644
|
||||
--- a/cmd/proxy/controllers/os_controller.go
|
||||
+++ b/cmd/proxy/controllers/os_controller.go
|
||||
@@ -261,7 +261,7 @@ func checkOsiExist(ctx context.Context, r common.ReadStatusWriter, nameSpace str
|
||||
Namespace: nameSpace,
|
||||
Name: nodeName,
|
||||
Labels: map[string]string{
|
||||
- "upgrade.openeuler.org/osinstance-node": nodeName,
|
||||
+ values.LabelOSinstance: nodeName,
|
||||
},
|
||||
},
|
||||
}
|
||||
diff --git a/cmd/proxy/controllers/os_controller_test.go b/cmd/proxy/controllers/os_controller_test.go
|
||||
index ff12f64..e6cd5b7 100644
|
||||
--- a/cmd/proxy/controllers/os_controller_test.go
|
||||
+++ b/cmd/proxy/controllers/os_controller_test.go
|
||||
@@ -110,6 +110,9 @@ var _ = Describe("OsController", func() {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: node1Name,
|
||||
Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node1Name,
|
||||
+ },
|
||||
},
|
||||
Spec: upgradev1.OSInstanceSpec{
|
||||
NodeStatus: values.NodeStatusConfig.String(),
|
||||
@@ -245,6 +248,9 @@ var _ = Describe("OsController", func() {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: node1Name,
|
||||
Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node1Name,
|
||||
+ },
|
||||
},
|
||||
Spec: upgradev1.OSInstanceSpec{
|
||||
NodeStatus: values.NodeStatusUpgrade.String(),
|
||||
@@ -426,6 +432,9 @@ var _ = Describe("OsController", func() {
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOSIns.Spec.NodeStatus).Should(Equal(values.NodeStatusIdle.String()))
|
||||
+ hostname, ok := createdOSIns.ObjectMeta.Labels[values.LabelOSinstance]
|
||||
+ Expect(ok).Should(BeTrue())
|
||||
+ Expect(hostname).Should(Equal(node1Name))
|
||||
})
|
||||
})
|
||||
|
||||
diff --git a/pkg/values/values.go b/pkg/values/values.go
|
||||
index 30261bd..f488ae5 100644
|
||||
--- a/pkg/values/values.go
|
||||
+++ b/pkg/values/values.go
|
||||
@@ -23,8 +23,10 @@ const (
|
||||
// LabelUpgrading is the key of the upgrading label for nodes
|
||||
LabelUpgrading = "upgrade.openeuler.org/upgrading"
|
||||
// LabelMaster is the key of the master-node label for nodes
|
||||
- LabelMaster = "node-role.kubernetes.io/control-plane"
|
||||
- defaultPeriod = 15 * time.Second
|
||||
+ LabelMaster = "node-role.kubernetes.io/control-plane"
|
||||
+ // LabelOSinstance is used to select the osinstance with the nodeName by label
|
||||
+ LabelOSinstance = "upgrade.openeuler.org/osinstance-node"
|
||||
+ defaultPeriod = 15 * time.Second
|
||||
// OsiStatusName is param name of nodeStatus in osInstance
|
||||
OsiStatusName = "nodestatus"
|
||||
// UpgradeConfigName is param name of UpgradeConfig
|
||||
--
|
||||
2.39.0
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
From 470e190db2de92b65e7fa720864823e7245c51e9 Mon Sep 17 00:00:00 2001
|
||||
From: liyuanr <liyuanrong1@huawei.com>
|
||||
Date: Mon, 7 Aug 2023 19:09:18 +0800
|
||||
Subject: [PATCH] KubeOS: fix the hostshell cannot obtain the lib
|
||||
Subject: [PATCH 03/17] KubeOS: fix the hostshell cannot obtain the lib
|
||||
|
||||
Fix the hostshell cannot obtain the lib
|
||||
|
||||
@ -71,5 +71,5 @@ index f6a7293..5fa0838 100644
|
||||
+ return pathEnv
|
||||
+}
|
||||
--
|
||||
2.33.0.windows.2
|
||||
2.39.0
|
||||
|
||||
1413
0004-KubeOS-add-agent-proxy-and-operator-ut.patch
Normal file
1413
0004-KubeOS-add-agent-proxy-and-operator-ut.patch
Normal file
File diff suppressed because it is too large
Load Diff
155
0005-KubeOS-fix-validate-image-name-bug.patch
Normal file
155
0005-KubeOS-fix-validate-image-name-bug.patch
Normal file
@ -0,0 +1,155 @@
|
||||
From 5c5922a922f225a9ebc5f99a5008ddcf182b7da6 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Thu, 10 Aug 2023 17:24:50 +0800
|
||||
Subject: [PATCH 05/17] KubeOS: fix validate image name bug fix the bug that
|
||||
incorrectly granted illegal image names path:tag@sha256
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/utils.go | 2 +-
|
||||
cmd/agent/server/utils_test.go | 109 ++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 109 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cmd/agent/server/utils.go b/cmd/agent/server/utils.go
|
||||
index 7134d74..b42db18 100644
|
||||
--- a/cmd/agent/server/utils.go
|
||||
+++ b/cmd/agent/server/utils.go
|
||||
@@ -316,7 +316,7 @@ func isCommandAvailable(name string) bool {
|
||||
}
|
||||
|
||||
func isValidImageName(image string) error {
|
||||
- pattern := `^((?:[\w.-]+)(?::\d+)?\/)*(?:[\w.-]+)(?::[\w_.-]+)?(?:@sha256:[a-fA-F0-9]+)?$`
|
||||
+ pattern := `^((?:[\w.-]+)(?::\d+)?\/)*(?:[\w.-]+)((?::[\w_.-]+)?|(?:@sha256:[a-fA-F0-9]+)?)$`
|
||||
regEx, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
diff --git a/cmd/agent/server/utils_test.go b/cmd/agent/server/utils_test.go
|
||||
index 89b2c3b..0796bce 100644
|
||||
--- a/cmd/agent/server/utils_test.go
|
||||
+++ b/cmd/agent/server/utils_test.go
|
||||
@@ -56,10 +56,16 @@ func Test_install(t *testing.T) {
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
- {name: "normal", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false},
|
||||
+ {name: "normal uefi", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false},
|
||||
+ {name: "normal legacy", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false},
|
||||
}
|
||||
patchRunCommand := gomonkey.ApplyFuncReturn(runCommand, nil)
|
||||
defer patchRunCommand.Reset()
|
||||
+ patchGetBootMode := gomonkey.ApplyFuncSeq(getBootMode, []gomonkey.OutputCell{
|
||||
+ {Values: gomonkey.Params{"uefi", nil}},
|
||||
+ {Values: gomonkey.Params{"legacy", nil}},
|
||||
+ })
|
||||
+ defer patchGetBootMode.Reset()
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := install(tt.args.imagePath, tt.args.side, tt.args.next); (err != nil) != tt.wantErr {
|
||||
@@ -219,3 +225,104 @@ func createTmpTarFile(tarPath string) (string, error) {
|
||||
}
|
||||
return tempFile.Name(), nil
|
||||
}
|
||||
+
|
||||
+func Test_getBootMode(t *testing.T) {
|
||||
+ tests := []struct {
|
||||
+ name string
|
||||
+ want string
|
||||
+ wantErr bool
|
||||
+ }{
|
||||
+ {
|
||||
+ name: "uefi",
|
||||
+ want: "uefi",
|
||||
+ wantErr: false,
|
||||
+ },
|
||||
+ {
|
||||
+ name: "legacy",
|
||||
+ want: "legacy",
|
||||
+ wantErr: false,
|
||||
+ },
|
||||
+ }
|
||||
+ patchOSStat := gomonkey.ApplyFuncSeq(os.Stat, []gomonkey.OutputCell{
|
||||
+ {Values: gomonkey.Params{nil, nil}},
|
||||
+ {Values: gomonkey.Params{nil, os.ErrNotExist}},
|
||||
+ })
|
||||
+ defer patchOSStat.Reset()
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ got, err := getBootMode()
|
||||
+ if (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("getBootMode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ return
|
||||
+ }
|
||||
+ if got != tt.want {
|
||||
+ t.Errorf("getBootMode() = %v, want %v", got, tt.want)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func Test_isValidImageName(t *testing.T) {
|
||||
+ type args struct {
|
||||
+ image string
|
||||
+ }
|
||||
+ tests := []struct {
|
||||
+ name string
|
||||
+ args args
|
||||
+ wantErr bool
|
||||
+ }{
|
||||
+ {name: "valid", args: args{image: "alpine"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "alpine:latest"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "localhost:1234/test"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "alpine:3.7"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "docker.example.edu/gmr/alpine:3.7"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "docker.example.com:5000/gmr/alpine@sha256:11111111111111111111111111111111"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "registry.dobby.org/dobby/dobby-servers/arthound:2019-08-08"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "registry.dobby.org/dobby/dobby-servers/lerphound:latest"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "registry.dobby.org/dobby/dobby-servers/loophole@sha256:5a156ff125e5a12ac7ff43ee5120fa249cf62248337b6d04abc574c8"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "sosedoff/pgweb@sha256:5a156ff125e5a12ac7ff43ee5120fa249cf62248337b6d04574c8"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "registry.dobby.org/dobby/antique-penguin:release-production"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "dalprodictus/halcon:6.7.5"}, wantErr: false},
|
||||
+ {name: "valid", args: args{image: "antigua/antigua:v31"}, wantErr: false},
|
||||
+ {name: "invalid ;", args: args{image: "alpine;v1.0"}, wantErr: true},
|
||||
+ {name: "invalid tag and digest1", args: args{image: "alpine:latest@sha256:11111111111111111111111111111111"}, wantErr: true},
|
||||
+ {name: "invalid |", args: args{image: "alpine|v1.0"}, wantErr: true},
|
||||
+ {name: "invalid &", args: args{image: "alpine&v1.0"}, wantErr: true},
|
||||
+ {name: "invalid tag and digest2", args: args{image: "sosedoff/pgweb:latest@sha256:5a156ff125e5a12ac7ff43ee5120fa249cf62248337b6d04574c8"}, wantErr: true},
|
||||
+ {name: "invalid tag and digest3", args: args{image: "192.168.122.123:5000/kubeos_uefi-x86_64:euleros_v2_docker-2023-01@sha256:1a1a1a1a1a1a1a1a1a1a1a1a1a1a"}, wantErr: true},
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ if err := isValidImageName(tt.args.image); (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("isValidImageName() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func Test_checkOCIImageDigestMatch(t *testing.T) {
|
||||
+ type args struct {
|
||||
+ containerRuntime string
|
||||
+ imageName string
|
||||
+ checkSum string
|
||||
+ }
|
||||
+ tests := []struct {
|
||||
+ name string
|
||||
+ args args
|
||||
+ wantErr bool
|
||||
+ }{
|
||||
+ {name: "invalid container runtion", args: args{containerRuntime: "dockctl", imageName: "docker.io/library/hello-world:latest", checkSum: "1abf18abf9bf9baa0a4a38d1afad4abf0d7da4544e163186e036c906c09c94fe"}, wantErr: true},
|
||||
+ {name: "nil image digets", args: args{containerRuntime: "crictl", imageName: "docker.io/library/hello-world:latest", checkSum: "1abf18abf9bf9baa0a4a38d1afad4abf0d7da4544e163186e036c906c09c94fe"}, wantErr: true},
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ if tt.name == "nil image digets" {
|
||||
+ patchGetOCIImageDigest := gomonkey.ApplyFuncReturn(getOCIImageDigest, "", nil)
|
||||
+ defer patchGetOCIImageDigest.Reset()
|
||||
+ }
|
||||
+ if err := checkOCIImageDigestMatch(tt.args.containerRuntime, tt.args.imageName, tt.args.checkSum); (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("checkOCIImageDigestMatch() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.39.0
|
||||
|
||||
156
0006-KubeOS-fix-a-bug-that-failed-to-parse-key-with.patch
Normal file
156
0006-KubeOS-fix-a-bug-that-failed-to-parse-key-with.patch
Normal file
@ -0,0 +1,156 @@
|
||||
From 911fbd04ba55a2560e8da8595ff379a742e5fa30 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Thu, 10 Aug 2023 17:47:54 +0800
|
||||
Subject: [PATCH 06/17] KubeOS: fix a bug that failed to parse key with =
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/config.go | 6 ++--
|
||||
cmd/agent/server/config_test.go | 55 +++++++++++++++++++++++++++++----
|
||||
2 files changed, 52 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go
|
||||
index 653f913..bcd9fde 100644
|
||||
--- a/cmd/agent/server/config.go
|
||||
+++ b/cmd/agent/server/config.go
|
||||
@@ -259,7 +259,7 @@ func getAndSetConfigsFromFile(expectConfigs map[string]*agent.KeyInfo, path stri
|
||||
configsWrite = append(configsWrite, line)
|
||||
continue
|
||||
}
|
||||
- configKV := strings.Split(line, "=")
|
||||
+ configKV := strings.SplitN(line, "=", kvPair)
|
||||
if len(configKV) != kvPair {
|
||||
logrus.Errorf("could not parse systctl config %s", line)
|
||||
return nil, fmt.Errorf("could not parse systctl config %s", line)
|
||||
@@ -374,8 +374,8 @@ func handleUpdateKey(config []string, configInfo *agent.KeyInfo, isFound bool) s
|
||||
func handleAddKey(m map[string]*agent.KeyInfo, isOnlyKeyValid bool) []string {
|
||||
var configs []string
|
||||
for key, keyInfo := range m {
|
||||
- if key == "" {
|
||||
- logrus.Warnln("Failed to add nil key")
|
||||
+ if key == "" || strings.Contains(key, "=") {
|
||||
+ logrus.Warnf("Failed to add nil key or key containing =, key: %s", key)
|
||||
continue
|
||||
}
|
||||
if keyInfo.Operation == "delete" {
|
||||
diff --git a/cmd/agent/server/config_test.go b/cmd/agent/server/config_test.go
|
||||
index 2deb15f..ae2a2cf 100644
|
||||
--- a/cmd/agent/server/config_test.go
|
||||
+++ b/cmd/agent/server/config_test.go
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/agiledragon/gomonkey/v2"
|
||||
-
|
||||
agent "openeuler.org/KubeOS/cmd/agent/api"
|
||||
)
|
||||
|
||||
@@ -105,17 +104,27 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "create file", args: args{config: &agent.SysConfig{ConfigPath: persistPath}}, want: []string{comment}, wantErr: false},
|
||||
+ {
|
||||
+ name: "nil path",
|
||||
+ args: args{
|
||||
+ config: &agent.SysConfig{},
|
||||
+ },
|
||||
+ want: []string{},
|
||||
+ wantErr: false,
|
||||
+ },
|
||||
{
|
||||
name: "add configs",
|
||||
args: args{
|
||||
config: &agent.SysConfig{
|
||||
ConfigPath: persistPath,
|
||||
Contents: map[string]*agent.KeyInfo{
|
||||
- "a": {Value: "1"},
|
||||
- "b": {Value: "2"},
|
||||
- "c": {Value: ""},
|
||||
- "": {Value: "4"},
|
||||
- "e": {Value: "5"},
|
||||
+ "a": {Value: "1"},
|
||||
+ "b": {Value: "2"},
|
||||
+ "c": {Value: ""},
|
||||
+ "": {Value: "4"},
|
||||
+ "e": {Value: "5"},
|
||||
+ "y=1": {Value: "26"},
|
||||
+ "z": {Value: "x=1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -123,6 +132,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
"a=1",
|
||||
"b=2",
|
||||
"e=5",
|
||||
+ "z=x=1",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@@ -134,6 +144,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
Contents: map[string]*agent.KeyInfo{
|
||||
"a": {Value: "2"},
|
||||
"b": {Value: ""},
|
||||
+ "z": {Value: "x=2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -141,6 +152,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
"a=2",
|
||||
"b=2",
|
||||
"e=5",
|
||||
+ "z=x=2",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@@ -155,6 +167,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
"c": {Value: "3", Operation: "delete"},
|
||||
"e": {Value: "5", Operation: "remove"},
|
||||
"f": {Value: "6", Operation: "remove"},
|
||||
+ "z": {Value: "x=2", Operation: "delete"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -166,6 +179,8 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
+ patchGetKernelConPath := gomonkey.ApplyFuncReturn(getKernelConPath, persistPath)
|
||||
+ defer patchGetKernelConPath.Reset()
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
k := KerSysctlPersist{}
|
||||
@@ -467,3 +482,31 @@ func Test_getConfigPartition(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
+
|
||||
+func Test_ConfigFactoryTemplate(t *testing.T) {
|
||||
+ type args struct {
|
||||
+ configType string
|
||||
+ config *agent.SysConfig
|
||||
+ }
|
||||
+ tests := []struct {
|
||||
+ name string
|
||||
+ args args
|
||||
+ wantErr bool
|
||||
+ }{
|
||||
+ {
|
||||
+ name: "error",
|
||||
+ args: args{
|
||||
+ configType: "test",
|
||||
+ config: &agent.SysConfig{},
|
||||
+ },
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
+ }
|
||||
+ for _, tt := range tests {
|
||||
+ t.Run(tt.name, func(t *testing.T) {
|
||||
+ if err := ConfigFactoryTemplate(tt.args.configType, tt.args.config); (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("ConfigFactoryTemplate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.39.0
|
||||
|
||||
52
0007-KubeOS-add-warning-log-during-config.patch
Normal file
52
0007-KubeOS-add-warning-log-during-config.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 59473394cca1e227ec579236d71ec54deb79b068 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Thu, 10 Aug 2023 20:49:39 +0800
|
||||
Subject: [PATCH 07/17] KubeOS: add warning log during config add warning log
|
||||
when configuring kv with unknown operation
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/config.go | 4 ++++
|
||||
cmd/agent/server/config_test.go | 4 ++--
|
||||
2 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go
|
||||
index bcd9fde..78dfd01 100644
|
||||
--- a/cmd/agent/server/config.go
|
||||
+++ b/cmd/agent/server/config.go
|
||||
@@ -382,6 +382,10 @@ func handleAddKey(m map[string]*agent.KeyInfo, isOnlyKeyValid bool) []string {
|
||||
logrus.Warnf("Failed to delete inexistent key %s", key)
|
||||
continue
|
||||
}
|
||||
+ if keyInfo.Operation != "" {
|
||||
+ logrus.Warnf("Unknown operation %s, adding key %s with value %s by default",
|
||||
+ keyInfo.Operation, key, keyInfo.Value)
|
||||
+ }
|
||||
k, v := strings.TrimSpace(key), strings.TrimSpace(keyInfo.Value)
|
||||
if keyInfo.Value == "" && isOnlyKeyValid {
|
||||
logrus.Infoln("add configuration ", k)
|
||||
diff --git a/cmd/agent/server/config_test.go b/cmd/agent/server/config_test.go
|
||||
index ae2a2cf..6424885 100644
|
||||
--- a/cmd/agent/server/config_test.go
|
||||
+++ b/cmd/agent/server/config_test.go
|
||||
@@ -122,7 +122,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
"b": {Value: "2"},
|
||||
"c": {Value: ""},
|
||||
"": {Value: "4"},
|
||||
- "e": {Value: "5"},
|
||||
+ "e": {Value: "5", Operation: "xxx"},
|
||||
"y=1": {Value: "26"},
|
||||
"z": {Value: "x=1"},
|
||||
},
|
||||
@@ -144,7 +144,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) {
|
||||
Contents: map[string]*agent.KeyInfo{
|
||||
"a": {Value: "2"},
|
||||
"b": {Value: ""},
|
||||
- "z": {Value: "x=2"},
|
||||
+ "z": {Value: "x=2", Operation: "zzz"},
|
||||
},
|
||||
},
|
||||
},
|
||||
--
|
||||
2.39.0
|
||||
|
||||
26
0008-KubeOS-modify-log-level-and-content.patch
Normal file
26
0008-KubeOS-modify-log-level-and-content.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 38ed69d2ad089d124ee72a4431fcc96ef3d9cf28 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Thu, 10 Aug 2023 21:10:29 +0800
|
||||
Subject: [PATCH 08/17] KubeOS: modify log level and content
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/config.go | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go
|
||||
index 78dfd01..c474f59 100644
|
||||
--- a/cmd/agent/server/config.go
|
||||
+++ b/cmd/agent/server/config.go
|
||||
@@ -57,7 +57,7 @@ func (k KernelSysctl) SetConfig(config *agent.SysConfig) error {
|
||||
}
|
||||
logrus.Infof("Configured kernel.sysctl %s=%s", key, keyInfo.Value)
|
||||
} else {
|
||||
- logrus.Errorf("Failed to parse kernel.sysctl config operation %s value %s", keyInfo.Operation, keyInfo.Value)
|
||||
+ logrus.Warnf("Failed to parse kernel.sysctl key %s value %s operation %s", key, keyInfo.Value, keyInfo.Operation)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
--
|
||||
2.39.0
|
||||
|
||||
151
0009-KubeOS-fix-updating-key-to-kv.patch
Normal file
151
0009-KubeOS-fix-updating-key-to-kv.patch
Normal file
@ -0,0 +1,151 @@
|
||||
From dcfb6e0397e649631ec42dcf51c3e98e914f8269 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Fri, 11 Aug 2023 19:33:56 +0800
|
||||
Subject: [PATCH 09/17] KubeOS: fix updating key to kv
|
||||
|
||||
when configuring kernel boot parameters, it should be able to update
|
||||
key to kv
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/config.go | 37 ++++++++++++++++++++++-----------
|
||||
cmd/agent/server/config_test.go | 15 +++++++------
|
||||
2 files changed, 34 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go
|
||||
index c474f59..20af267 100644
|
||||
--- a/cmd/agent/server/config.go
|
||||
+++ b/cmd/agent/server/config.go
|
||||
@@ -57,7 +57,7 @@ func (k KernelSysctl) SetConfig(config *agent.SysConfig) error {
|
||||
}
|
||||
logrus.Infof("Configured kernel.sysctl %s=%s", key, keyInfo.Value)
|
||||
} else {
|
||||
- logrus.Warnf("Failed to parse kernel.sysctl key %s value %s operation %s", key, keyInfo.Value, keyInfo.Operation)
|
||||
+ logrus.Warnf("Failed to parse kernel.sysctl key: %s value: %s operation: %s", key, keyInfo.Value, keyInfo.Operation)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -317,7 +317,7 @@ func createConfigPath(configPath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
- defer f.Close()
|
||||
+ f.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -335,11 +335,16 @@ func getGrubCfgPath() string {
|
||||
|
||||
// handleDeleteKey deletes key if oldValue==newValue and returns "" string. Otherwier, it returns key=oldValue
|
||||
func handleDeleteKey(config []string, configInfo *agent.KeyInfo) string {
|
||||
- if len(config) == onlyKey {
|
||||
- logrus.Infoln("delete configuration ", config[0])
|
||||
+ key := config[0]
|
||||
+ if len(config) == onlyKey && configInfo.Value == "" {
|
||||
+ logrus.Infoln("delete configuration ", key)
|
||||
return ""
|
||||
+ } else if len(config) == onlyKey && configInfo.Value != "" {
|
||||
+ logrus.Warnf("Failed to delete key %s with inconsistent values "+
|
||||
+ "nil and %s", key, configInfo.Value)
|
||||
+ return key
|
||||
}
|
||||
- key, oldValue := config[0], config[1]
|
||||
+ oldValue := config[1]
|
||||
if oldValue != configInfo.Value {
|
||||
logrus.Warnf("Failed to delete key %s with inconsistent values "+
|
||||
"%s and %s", key, oldValue, configInfo.Value)
|
||||
@@ -351,22 +356,30 @@ func handleDeleteKey(config []string, configInfo *agent.KeyInfo) string {
|
||||
|
||||
// handleUpdateKey updates key if key is found, otherwise it returns old config.
|
||||
func handleUpdateKey(config []string, configInfo *agent.KeyInfo, isFound bool) string {
|
||||
- if len(config) == onlyKey {
|
||||
- return config[0]
|
||||
+ key := config[0]
|
||||
+ if !isFound && len(config) == onlyKey {
|
||||
+ return key
|
||||
}
|
||||
- key, oldValue := config[0], config[1]
|
||||
- if !isFound {
|
||||
- return key + "=" + oldValue
|
||||
+ if !isFound && len(config) == kvPair {
|
||||
+ return key + "=" + config[1]
|
||||
}
|
||||
if configInfo.Operation != "" {
|
||||
logrus.Warnf("Unknown operation %s, updating key %s with value %s by default",
|
||||
configInfo.Operation, key, configInfo.Value)
|
||||
}
|
||||
+ if len(config) == onlyKey && configInfo.Value == "" {
|
||||
+ return key
|
||||
+ }
|
||||
+ newValue := strings.TrimSpace(configInfo.Value)
|
||||
+ if len(config) == onlyKey && configInfo.Value != "" {
|
||||
+ logrus.Infof("update configuration %s=%s", key, newValue)
|
||||
+ return key + "=" + newValue
|
||||
+ }
|
||||
+ oldValue := config[1]
|
||||
if configInfo.Value == "" {
|
||||
logrus.Warnf("Failed to update key %s with null value", key)
|
||||
return key + "=" + oldValue
|
||||
}
|
||||
- newValue := strings.TrimSpace(configInfo.Value)
|
||||
logrus.Infof("update configuration %s=%s", key, newValue)
|
||||
return key + "=" + newValue
|
||||
}
|
||||
@@ -388,7 +401,7 @@ func handleAddKey(m map[string]*agent.KeyInfo, isOnlyKeyValid bool) []string {
|
||||
}
|
||||
k, v := strings.TrimSpace(key), strings.TrimSpace(keyInfo.Value)
|
||||
if keyInfo.Value == "" && isOnlyKeyValid {
|
||||
- logrus.Infoln("add configuration ", k)
|
||||
+ logrus.Infoln("add configuration", k)
|
||||
configs = append(configs, k)
|
||||
} else if keyInfo.Value == "" {
|
||||
logrus.Warnf("Failed to add key %s with null value", k)
|
||||
diff --git a/cmd/agent/server/config_test.go b/cmd/agent/server/config_test.go
|
||||
index 6424885..08daf99 100644
|
||||
--- a/cmd/agent/server/config_test.go
|
||||
+++ b/cmd/agent/server/config_test.go
|
||||
@@ -262,10 +262,11 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
|
||||
"": {Value: "test"}, // warning, skip, failed to add kv with empty key
|
||||
"selinux": {Value: "1", Operation: "delete"}, // failed to delete inconsistent kv
|
||||
"acpi": {Value: "off", Operation: "delete"}, // failed to delete inexistent kv
|
||||
+ "ro": {Value: "1"}, // update key to kv
|
||||
},
|
||||
},
|
||||
},
|
||||
- pattern: `(?m)^\s+linux\s+\/boot\/vmlinuz\s+root=UUID=[0-1]\s+ro\s+rootfstype=ext4\s+nomodeset\s+oops=panic\s+softlockup_panic=0\s+nmi_watchdog=1\s+rd\.shell=0\s+selinux=0\s+crashkernel=256M\s+panic=5\s+(debug\spci=nomis|pci=nomis\sdebug)$`,
|
||||
+ pattern: `(?m)^\s+linux\s+\/boot\/vmlinuz\s+root=UUID=[0-1]\s+ro=1\s+rootfstype=ext4\s+nomodeset\s+oops=panic\s+softlockup_panic=0\s+nmi_watchdog=1\s+rd\.shell=0\s+selinux=0\s+crashkernel=256M\s+panic=5\s+(debug\spci=nomis|pci=nomis\sdebug)$`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
@@ -274,14 +275,15 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
|
||||
args: args{
|
||||
config: &agent.SysConfig{
|
||||
Contents: map[string]*agent.KeyInfo{
|
||||
- "debug": {Operation: "delete"}, // delete key
|
||||
- "pci": {Value: "nomis", Operation: "delete"}, // delete kv
|
||||
- "debugpat": {Value: "", Operation: "add"}, // passed key, operation is invalid, default to add key
|
||||
- "audit": {Value: "1", Operation: "add"}, // passed kv, key is inexistent, operation is invalid, default to add kv
|
||||
+ "debug": {Operation: "delete"}, // delete key
|
||||
+ "pci": {Value: "nomis", Operation: "delete"}, // delete kv
|
||||
+ "debugpat": {Value: "", Operation: "add"}, // passed key, operation is invalid, default to add key
|
||||
+ "audit": {Value: "1", Operation: "add"}, // passed kv, key is inexistent, operation is invalid, default to add kv
|
||||
+ "nomodeset": {Value: "1", Operation: "delete"}, // delete key with inconsistent value
|
||||
},
|
||||
},
|
||||
},
|
||||
- pattern: `(?m)^\s+linux\s+\/boot\/vmlinuz\s+root=UUID=[0-1]\s+ro\s+rootfstype=ext4\s+nomodeset\s+oops=panic\s+softlockup_panic=0\s+nmi_watchdog=1\s+rd\.shell=0\s+selinux=0\s+crashkernel=256M\s+panic=5\s+(debugpat\saudit=1|audit=1\sdebugpat)$`,
|
||||
+ pattern: `(?m)^\s+linux\s+\/boot\/vmlinuz\s+root=UUID=[0-1]\s+ro=1\s+rootfstype=ext4\s+nomodeset\s+oops=panic\s+softlockup_panic=0\s+nmi_watchdog=1\s+rd\.shell=0\s+selinux=0\s+crashkernel=256M\s+panic=5\s+(debugpat\saudit=1|audit=1\sdebugpat)$`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
@@ -300,6 +302,7 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri
|
||||
"": {Value: "test"}, // warning, skip, failed to add kv with empty key
|
||||
"selinux": {Value: "1", Operation: "delete"},
|
||||
"acpi": {Value: "off", Operation: "delete"},
|
||||
+ "ro": {Value: ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
--
|
||||
2.39.0
|
||||
|
||||
37
0010-KubeOS-fix-proxy-requeue-bug.patch
Normal file
37
0010-KubeOS-fix-proxy-requeue-bug.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 657e3e5c9bcc0fac3a079f51842d59a9e6b5e163 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Mon, 14 Aug 2023 09:53:16 +0800
|
||||
Subject: [PATCH 10/17] KubeOS: fix proxy requeue bug
|
||||
|
||||
fix the bug that proxy may work after resuming normal from error status
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/proxy/controllers/os_controller.go | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cmd/proxy/controllers/os_controller.go b/cmd/proxy/controllers/os_controller.go
|
||||
index 09d61c0..30f9839 100644
|
||||
--- a/cmd/proxy/controllers/os_controller.go
|
||||
+++ b/cmd/proxy/controllers/os_controller.go
|
||||
@@ -94,7 +94,7 @@ func (r *OSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re
|
||||
if err = r.refreshNode(ctx, &node, osInstance, osCr.Spec.SysConfigs.Version, values.SysConfigName); err != nil {
|
||||
return values.RequeueNow, err
|
||||
}
|
||||
- return values.RequeueNow, nil
|
||||
+ return values.Requeue, nil
|
||||
}
|
||||
if configOps == values.UpdateConfig {
|
||||
osInstance.Spec.SysConfigs = osCr.Spec.SysConfigs
|
||||
@@ -124,7 +124,7 @@ func (r *OSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re
|
||||
values.UpgradeConfigName); err != nil {
|
||||
return values.RequeueNow, err
|
||||
}
|
||||
- return values.RequeueNow, nil
|
||||
+ return values.Requeue, nil
|
||||
}
|
||||
if err := r.setConfig(ctx, osInstance, values.UpgradeConfigName); err != nil {
|
||||
return values.RequeueNow, err
|
||||
--
|
||||
2.39.0
|
||||
|
||||
665
0011-KubeOS-fix-operator-bug-of-missing-deep-copy.patch
Normal file
665
0011-KubeOS-fix-operator-bug-of-missing-deep-copy.patch
Normal file
@ -0,0 +1,665 @@
|
||||
From a87666e17d729feb67f987fa7038ef83b3fa2e1b Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Mon, 14 Aug 2023 16:46:06 +0800
|
||||
Subject: [PATCH 11/17] KubeOS: fix operator bug of missing deep copy
|
||||
|
||||
Fixed bug where operator didn't perform deep copy
|
||||
add operator ut, testing in multiple nodes env
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/operator/controllers/os_controller.go | 44 +-
|
||||
.../controllers/os_controller_test.go | 378 ++++++++++++++----
|
||||
2 files changed, 330 insertions(+), 92 deletions(-)
|
||||
|
||||
diff --git a/cmd/operator/controllers/os_controller.go b/cmd/operator/controllers/os_controller.go
|
||||
index 620739b..d36f15d 100644
|
||||
--- a/cmd/operator/controllers/os_controller.go
|
||||
+++ b/cmd/operator/controllers/os_controller.go
|
||||
@@ -15,6 +15,8 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
+ "encoding/json"
|
||||
+ "fmt"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -188,7 +190,9 @@ func upgradeNodes(ctx context.Context, r common.ReadStatusWriter, os *upgradev1.
|
||||
}
|
||||
continue
|
||||
}
|
||||
- updateNodeAndOSins(ctx, r, os, &node, &osInstance)
|
||||
+ if err := updateNodeAndOSins(ctx, r, os, &node, &osInstance); err != nil {
|
||||
+ continue
|
||||
+ }
|
||||
count++
|
||||
}
|
||||
}
|
||||
@@ -196,12 +200,16 @@ func upgradeNodes(ctx context.Context, r common.ReadStatusWriter, os *upgradev1.
|
||||
}
|
||||
|
||||
func updateNodeAndOSins(ctx context.Context, r common.ReadStatusWriter, os *upgradev1.OS,
|
||||
- node *corev1.Node, osInstance *upgradev1.OSInstance) {
|
||||
+ node *corev1.Node, osInstance *upgradev1.OSInstance) error {
|
||||
if osInstance.Spec.UpgradeConfigs.Version != os.Spec.UpgradeConfigs.Version {
|
||||
- osInstance.Spec.UpgradeConfigs = os.Spec.UpgradeConfigs
|
||||
+ if err := deepCopySpecConfigs(os, osInstance, values.UpgradeConfigName); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
}
|
||||
if osInstance.Spec.SysConfigs.Version != os.Spec.SysConfigs.Version {
|
||||
- osInstance.Spec.SysConfigs = os.Spec.SysConfigs
|
||||
+ if err := deepCopySpecConfigs(os, osInstance, values.SysConfigName); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
// exchange "grub.cmdline.current" and "grub.cmdline.next"
|
||||
for i, config := range osInstance.Spec.SysConfigs.Configs {
|
||||
if config.Model == "grub.cmdline.current" {
|
||||
@@ -215,11 +223,14 @@ func updateNodeAndOSins(ctx context.Context, r common.ReadStatusWriter, os *upgr
|
||||
osInstance.Spec.NodeStatus = values.NodeStatusUpgrade.String()
|
||||
if err := r.Update(ctx, osInstance); err != nil {
|
||||
log.Error(err, "unable to update", "osInstance", osInstance.Name)
|
||||
+ return err
|
||||
}
|
||||
node.Labels[values.LabelUpgrading] = ""
|
||||
if err := r.Update(ctx, node); err != nil {
|
||||
log.Error(err, "unable to label", "node", node.Name)
|
||||
+ return err
|
||||
}
|
||||
+ return nil
|
||||
}
|
||||
|
||||
func assignConfig(ctx context.Context, r common.ReadStatusWriter, sysConfigs upgradev1.SysConfigs,
|
||||
@@ -307,3 +318,28 @@ func min(a, b int) int {
|
||||
}
|
||||
return b
|
||||
}
|
||||
+
|
||||
+func deepCopySpecConfigs(os *upgradev1.OS, osinstance *upgradev1.OSInstance, configType string) error {
|
||||
+ switch configType {
|
||||
+ case values.UpgradeConfigName:
|
||||
+ data, err := json.Marshal(os.Spec.UpgradeConfigs)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ if err = json.Unmarshal(data, &osinstance.Spec.UpgradeConfigs); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ case values.SysConfigName:
|
||||
+ data, err := json.Marshal(os.Spec.SysConfigs)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ if err = json.Unmarshal(data, &osinstance.Spec.SysConfigs); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ default:
|
||||
+ log.Error(nil, "configType "+configType+" cannot be recognized")
|
||||
+ return fmt.Errorf("configType %s cannot be recognized", configType)
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
diff --git a/cmd/operator/controllers/os_controller_test.go b/cmd/operator/controllers/os_controller_test.go
|
||||
index 98de6d0..e59ce7e 100644
|
||||
--- a/cmd/operator/controllers/os_controller_test.go
|
||||
+++ b/cmd/operator/controllers/os_controller_test.go
|
||||
@@ -17,19 +17,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
- "github.com/agiledragon/gomonkey/v2"
|
||||
"github.com/google/uuid"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
- "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
- "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
- "k8s.io/client-go/kubernetes/scheme"
|
||||
- "k8s.io/client-go/util/workqueue"
|
||||
- "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
- "sigs.k8s.io/controller-runtime/pkg/event"
|
||||
|
||||
upgradev1 "openeuler.org/KubeOS/api/v1alpha1"
|
||||
"openeuler.org/KubeOS/pkg/values"
|
||||
@@ -37,8 +30,7 @@ import (
|
||||
|
||||
var _ = Describe("OsController", func() {
|
||||
const (
|
||||
- OSName = "test-os"
|
||||
-
|
||||
+ OSName = "test-os"
|
||||
timeout = time.Second * 20
|
||||
interval = time.Millisecond * 500
|
||||
)
|
||||
@@ -72,26 +64,33 @@ var _ = Describe("OsController", func() {
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
- desiredTestNamespace := &v1.Namespace{
|
||||
- TypeMeta: metav1.TypeMeta{
|
||||
- APIVersion: "v1",
|
||||
- Kind: "Namespace",
|
||||
- },
|
||||
- ObjectMeta: metav1.ObjectMeta{
|
||||
- Name: testNamespace,
|
||||
- },
|
||||
+ // delete all nodes
|
||||
+ nodeList := &v1.NodeList{}
|
||||
+ err := k8sClient.List(context.Background(), nodeList)
|
||||
+ Expect(err).ToNot(HaveOccurred())
|
||||
+ for _, node := range nodeList.Items {
|
||||
+ k8sClient.Delete(context.Background(), &node)
|
||||
}
|
||||
- // Add any teardown steps that needs to be executed after each test
|
||||
- err := k8sClient.Delete(context.Background(), desiredTestNamespace,
|
||||
- client.PropagationPolicy(metav1.DeletePropagationForeground))
|
||||
+ nodeList = &v1.NodeList{}
|
||||
+ Eventually(func() bool {
|
||||
+ err = k8sClient.List(context.Background(), nodeList)
|
||||
+ if err != nil || len(nodeList.Items) != 0 {
|
||||
+ return false
|
||||
+ }
|
||||
+ return true
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
|
||||
+ // delete all OS CRs
|
||||
+ osList := &upgradev1.OSList{}
|
||||
+ err = k8sClient.List(context.Background(), osList)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
-
|
||||
- existingNamespace := &v1.Namespace{}
|
||||
+ for _, os := range osList.Items {
|
||||
+ k8sClient.Delete(context.Background(), &os)
|
||||
+ }
|
||||
+ osList = &upgradev1.OSList{}
|
||||
Eventually(func() bool {
|
||||
- err := k8sClient.Get(context.Background(), types.NamespacedName{Name: testNamespace},
|
||||
- existingNamespace)
|
||||
- if err != nil && errors.IsNotFound(err) {
|
||||
+ err = k8sClient.List(context.Background(), osList)
|
||||
+ if err != nil || len(osList.Items) != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -102,7 +101,7 @@ var _ = Describe("OsController", func() {
|
||||
It("Should label the osinstance's nodestatus to upgrading", func() {
|
||||
ctx := context.Background()
|
||||
|
||||
- // create Node
|
||||
+ // create Node1
|
||||
node1Name = "test-node-" + uuid.New().String()
|
||||
node1 := &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -131,7 +130,7 @@ var _ = Describe("OsController", func() {
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
|
||||
- // create OSInstance
|
||||
+ // create OSInstance1
|
||||
OSIns := &upgradev1.OSInstance{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "OSInstance",
|
||||
@@ -163,6 +162,67 @@ var _ = Describe("OsController", func() {
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node1Name))
|
||||
|
||||
+ // create Node2
|
||||
+ node2Name := "test-node-" + uuid.New().String()
|
||||
+ node2 := &v1.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node2Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ "beta.kubernetes.io/os": "linux",
|
||||
+ },
|
||||
+ },
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "v1",
|
||||
+ Kind: "Node",
|
||||
+ },
|
||||
+ Status: v1.NodeStatus{
|
||||
+ NodeInfo: v1.NodeSystemInfo{
|
||||
+ OSImage: "KubeOS v2",
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+ err = k8sClient.Create(ctx, node2)
|
||||
+ Expect(err).ToNot(HaveOccurred())
|
||||
+ existingNode = &v1.Node{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(context.Background(),
|
||||
+ types.NamespacedName{Name: node2Name, Namespace: testNamespace}, existingNode)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+
|
||||
+ // create OSInstance2
|
||||
+ OSIns = &upgradev1.OSInstance{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ Kind: "OSInstance",
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node2Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node2Name,
|
||||
+ },
|
||||
+ },
|
||||
+ Spec: upgradev1.OSInstanceSpec{
|
||||
+ SysConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v1",
|
||||
+ Configs: []upgradev1.SysConfig{},
|
||||
+ },
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}, Version: "v1"},
|
||||
+ },
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
+
|
||||
+ // Check that the corresponding OSIns CR has been created
|
||||
+ osInsCRLookupKey2 := types.NamespacedName{Name: node2Name, Namespace: testNamespace}
|
||||
+ createdOSIns = &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey2, createdOSIns)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node2Name))
|
||||
+
|
||||
// create OS CR
|
||||
OS := &upgradev1.OS{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@@ -206,13 +266,20 @@ var _ = Describe("OsController", func() {
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOSIns.Spec.NodeStatus).Should(Equal(values.NodeStatusUpgrade.String()))
|
||||
+
|
||||
+ createdOSIns2 := &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey2, createdOSIns2)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns2.Spec.NodeStatus).Should(Equal(values.NodeStatusUpgrade.String()))
|
||||
})
|
||||
})
|
||||
|
||||
Context("When we want to configure node", func() {
|
||||
It("Should update OSInstance spec and update NodeStatus to config", func() {
|
||||
ctx := context.Background()
|
||||
- // create Node
|
||||
+ // create Node1
|
||||
node1Name = "test-node-" + uuid.New().String()
|
||||
node1 := &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -228,7 +295,7 @@ var _ = Describe("OsController", func() {
|
||||
},
|
||||
Status: v1.NodeStatus{
|
||||
NodeInfo: v1.NodeSystemInfo{
|
||||
- OSImage: "KubeOS v2",
|
||||
+ OSImage: "KubeOS v1",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -241,6 +308,7 @@ var _ = Describe("OsController", func() {
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
|
||||
+ // create OSInstance1
|
||||
OSIns := &upgradev1.OSInstance{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "OSInstance",
|
||||
@@ -249,6 +317,9 @@ var _ = Describe("OsController", func() {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: node1Name,
|
||||
Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node1Name,
|
||||
+ },
|
||||
},
|
||||
Spec: upgradev1.OSInstanceSpec{
|
||||
SysConfigs: upgradev1.SysConfigs{
|
||||
@@ -261,14 +332,76 @@ var _ = Describe("OsController", func() {
|
||||
}
|
||||
Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
|
||||
- osInsCRLookupKey := types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
+ osInsCRLookupKey1 := types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
createdOSIns := &upgradev1.OSInstance{}
|
||||
Eventually(func() bool {
|
||||
- err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns)
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey1, createdOSIns)
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node1Name))
|
||||
|
||||
+ // create Node2
|
||||
+ node2Name := "test-node-" + uuid.New().String()
|
||||
+ node2 := &v1.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node2Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ "beta.kubernetes.io/os": "linux",
|
||||
+ },
|
||||
+ },
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "v1",
|
||||
+ Kind: "Node",
|
||||
+ },
|
||||
+ Status: v1.NodeStatus{
|
||||
+ NodeInfo: v1.NodeSystemInfo{
|
||||
+ OSImage: "KubeOS v1",
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+ err = k8sClient.Create(ctx, node2)
|
||||
+ Expect(err).ToNot(HaveOccurred())
|
||||
+ existingNode = &v1.Node{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(context.Background(),
|
||||
+ types.NamespacedName{Name: node2Name, Namespace: testNamespace}, existingNode)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+
|
||||
+ // create OSInstance2
|
||||
+ OSIns = &upgradev1.OSInstance{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ Kind: "OSInstance",
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node2Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node2Name,
|
||||
+ },
|
||||
+ },
|
||||
+ Spec: upgradev1.OSInstanceSpec{
|
||||
+ SysConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v1",
|
||||
+ Configs: []upgradev1.SysConfig{},
|
||||
+ },
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}, Version: "v1"},
|
||||
+ NodeStatus: values.NodeStatusIdle.String(),
|
||||
+ },
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
+
|
||||
+ // Check that the corresponding OSIns CR has been created
|
||||
+ osInsCRLookupKey2 := types.NamespacedName{Name: node2Name, Namespace: testNamespace}
|
||||
+ createdOSIns = &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey2, createdOSIns)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node2Name))
|
||||
+
|
||||
OS := &upgradev1.OS{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
@@ -311,13 +444,21 @@ var _ = Describe("OsController", func() {
|
||||
Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v1"))
|
||||
|
||||
time.Sleep(1 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
- configedOSIns := &upgradev1.OSInstance{}
|
||||
+ configedOSIns1 := &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey1, configedOSIns1)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(configedOSIns1.Spec.NodeStatus).Should(Equal(values.NodeStatusConfig.String()))
|
||||
+ Expect(configedOSIns1.Spec.SysConfigs.Version).Should(Equal("v2"))
|
||||
+
|
||||
+ configedOSIns2 := &upgradev1.OSInstance{}
|
||||
Eventually(func() bool {
|
||||
- err := k8sClient.Get(ctx, osInsCRLookupKey, configedOSIns)
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey2, configedOSIns2)
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
- Expect(configedOSIns.Spec.NodeStatus).Should(Equal(values.NodeStatusConfig.String()))
|
||||
- Expect(configedOSIns.Spec.SysConfigs.Version).Should(Equal("v2"))
|
||||
+ Expect(configedOSIns2.Spec.NodeStatus).Should(Equal(values.NodeStatusConfig.String()))
|
||||
+ Expect(configedOSIns2.Spec.SysConfigs.Version).Should(Equal("v2"))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -394,6 +535,9 @@ var _ = Describe("OsController", func() {
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
_, ok := existingNode.Labels[values.LabelUpgrading]
|
||||
Expect(ok).Should(Equal(false))
|
||||
+
|
||||
+ createdOS.Spec.OpsType = "test"
|
||||
+ Expect(k8sClient.Update(ctx, createdOS)).Should(Succeed())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -401,7 +545,7 @@ var _ = Describe("OsController", func() {
|
||||
It("Should exchange .current and .next", func() {
|
||||
ctx := context.Background()
|
||||
|
||||
- // create Node
|
||||
+ // create Node1
|
||||
node1Name = "test-node-" + uuid.New().String()
|
||||
node1 := &v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -430,7 +574,7 @@ var _ = Describe("OsController", func() {
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
|
||||
- // create OSInstance
|
||||
+ // create OSInstance1
|
||||
OSIns := &upgradev1.OSInstance{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "OSInstance",
|
||||
@@ -454,14 +598,75 @@ var _ = Describe("OsController", func() {
|
||||
Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
|
||||
// Check that the corresponding OSIns CR has been created
|
||||
- osInsCRLookupKey := types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
+ osInsCRLookupKey1 := types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
createdOSIns := &upgradev1.OSInstance{}
|
||||
Eventually(func() bool {
|
||||
- err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns)
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey1, createdOSIns)
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node1Name))
|
||||
|
||||
+ // create Node2
|
||||
+ node2Name := "test-node-" + uuid.New().String()
|
||||
+ node2 := &v1.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node2Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ "beta.kubernetes.io/os": "linux",
|
||||
+ },
|
||||
+ },
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "v1",
|
||||
+ Kind: "Node",
|
||||
+ },
|
||||
+ Status: v1.NodeStatus{
|
||||
+ NodeInfo: v1.NodeSystemInfo{
|
||||
+ OSImage: "KubeOS v1",
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+ err = k8sClient.Create(ctx, node2)
|
||||
+ Expect(err).ToNot(HaveOccurred())
|
||||
+ existingNode = &v1.Node{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(context.Background(),
|
||||
+ types.NamespacedName{Name: node2Name, Namespace: testNamespace}, existingNode)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+
|
||||
+ // create OSInstance2
|
||||
+ OSIns = &upgradev1.OSInstance{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ Kind: "OSInstance",
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node2Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node2Name,
|
||||
+ },
|
||||
+ },
|
||||
+ Spec: upgradev1.OSInstanceSpec{
|
||||
+ SysConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v1",
|
||||
+ Configs: []upgradev1.SysConfig{},
|
||||
+ },
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}, Version: "v1"},
|
||||
+ },
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
+
|
||||
+ // Check that the corresponding OSIns CR has been created
|
||||
+ osInsCRLookupKey2 := types.NamespacedName{Name: node2Name, Namespace: testNamespace}
|
||||
+ createdOSIns = &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey2, createdOSIns)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node2Name))
|
||||
+
|
||||
// create OS CR
|
||||
OS := &upgradev1.OS{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@@ -486,7 +691,13 @@ var _ = Describe("OsController", func() {
|
||||
{Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}},
|
||||
},
|
||||
},
|
||||
- UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}},
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v2",
|
||||
+ Configs: []upgradev1.SysConfig{
|
||||
+ {Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}},
|
||||
+ {Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}},
|
||||
+ },
|
||||
+ },
|
||||
},
|
||||
}
|
||||
Expect(k8sClient.Create(ctx, OS)).Should(Succeed())
|
||||
@@ -501,75 +712,66 @@ var _ = Describe("OsController", func() {
|
||||
Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v2"))
|
||||
|
||||
time.Sleep(1 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
- osInsCRLookupKey = types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
+ // check node1 osinstance
|
||||
createdOSIns = &upgradev1.OSInstance{}
|
||||
Eventually(func() bool {
|
||||
- err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns)
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey1, createdOSIns)
|
||||
return err == nil
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
Expect(createdOSIns.Spec.SysConfigs.Configs[0]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}}))
|
||||
Expect(createdOSIns.Spec.SysConfigs.Configs[1]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}}))
|
||||
+ Expect(createdOSIns.Spec.UpgradeConfigs.Configs[0]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}}))
|
||||
+ Expect(createdOSIns.Spec.NodeStatus).Should(Equal(values.NodeStatusUpgrade.String()))
|
||||
+
|
||||
+ // check node2 osinstance
|
||||
+ createdOSIns2 := &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey2, createdOSIns2)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns2.Spec.NodeStatus).Should(Equal(values.NodeStatusUpgrade.String()))
|
||||
+ Expect(createdOSIns2.Spec.SysConfigs.Configs[0]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}}))
|
||||
+ Expect(createdOSIns2.Spec.SysConfigs.Configs[1]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}}))
|
||||
+ Expect(createdOSIns2.Spec.UpgradeConfigs.Configs[0]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}}))
|
||||
+
|
||||
+ // check os cr spec
|
||||
+ osCRLookupKey = types.NamespacedName{Name: OSName, Namespace: testNamespace}
|
||||
+ createdOS = &upgradev1.OS{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osCRLookupKey, createdOS)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOS.Spec.SysConfigs.Configs[0]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.current", Contents: []upgradev1.Content{{Key: "a", Value: "1"}}}))
|
||||
+ Expect(createdOS.Spec.SysConfigs.Configs[1]).Should(Equal(upgradev1.SysConfig{Model: "grub.cmdline.next", Contents: []upgradev1.Content{{Key: "b", Value: "2"}}}))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
-func TestOSReconciler_DeleteOSInstance(t *testing.T) {
|
||||
- type fields struct {
|
||||
- Scheme *runtime.Scheme
|
||||
- Client client.Client
|
||||
- }
|
||||
- kClient, _ := client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||
+func Test_deepCopySpecConfigs(t *testing.T) {
|
||||
type args struct {
|
||||
- e event.DeleteEvent
|
||||
- q workqueue.RateLimitingInterface
|
||||
+ os *upgradev1.OS
|
||||
+ osinstance *upgradev1.OSInstance
|
||||
+ configType string
|
||||
}
|
||||
tests := []struct {
|
||||
- name string
|
||||
- fields fields
|
||||
- args args
|
||||
+ name string
|
||||
+ args args
|
||||
+ wantErr bool
|
||||
}{
|
||||
{
|
||||
- name: "delete osinstance",
|
||||
- fields: fields{
|
||||
- Scheme: nil,
|
||||
- Client: kClient,
|
||||
- },
|
||||
+ name: "error",
|
||||
args: args{
|
||||
- e: event.DeleteEvent{
|
||||
- Object: &upgradev1.OSInstance{
|
||||
- ObjectMeta: metav1.ObjectMeta{
|
||||
- Name: "test-node1",
|
||||
- Namespace: "test",
|
||||
- },
|
||||
- },
|
||||
- },
|
||||
- q: nil,
|
||||
- },
|
||||
+ os: &upgradev1.OS{},
|
||||
+ osinstance: &upgradev1.OSInstance{},
|
||||
+ configType: "test"},
|
||||
+ wantErr: true,
|
||||
},
|
||||
}
|
||||
- var patchList *gomonkey.Patches
|
||||
- var patchDelete *gomonkey.Patches
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
- r := &OSReconciler{
|
||||
- Scheme: tt.fields.Scheme,
|
||||
- Client: tt.fields.Client,
|
||||
+ if err := deepCopySpecConfigs(tt.args.os, tt.args.osinstance, tt.args.configType); (err != nil) != tt.wantErr {
|
||||
+ t.Errorf("deepCopySpecConfigs() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
- patchList = gomonkey.ApplyMethodFunc(r.Client, "List", func(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
|
||||
- list.(*upgradev1.OSInstanceList).Items = []upgradev1.OSInstance{
|
||||
- {
|
||||
- ObjectMeta: metav1.ObjectMeta{
|
||||
- Name: "test-node1",
|
||||
- Namespace: "test",
|
||||
- },
|
||||
- },
|
||||
- }
|
||||
- return nil
|
||||
- })
|
||||
- patchDelete = gomonkey.ApplyMethodReturn(r.Client, "Delete", nil)
|
||||
- r.DeleteOSInstance(tt.args.e, tt.args.q)
|
||||
})
|
||||
}
|
||||
- defer patchDelete.Reset()
|
||||
- defer patchList.Reset()
|
||||
}
|
||||
--
|
||||
2.39.0
|
||||
|
||||
191
0012-KubeOS-add-unit-test.patch
Normal file
191
0012-KubeOS-add-unit-test.patch
Normal file
@ -0,0 +1,191 @@
|
||||
From 9bd13d2a1b8b7282d7247caf9ba54f11bb297cd5 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Fri, 11 Aug 2023 20:25:46 +0800
|
||||
Subject: [PATCH 12/17] KubeOS: add unit test
|
||||
|
||||
add containerd_image and disk_image unit test
|
||||
modify make test command for only testing server and controllers
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
Makefile | 2 +-
|
||||
cmd/agent/server/containerd_image_test.go | 10 ++-
|
||||
cmd/agent/server/disk_image_test.go | 83 +++++++++++++++++++----
|
||||
3 files changed, 80 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index b5b6161..eddf9e6 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -133,7 +133,7 @@ kustomize:
|
||||
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)
|
||||
|
||||
ARCH := $(shell uname -m)
|
||||
-TEST_CMD := go test ./... -race -count=1 -timeout=300s -cover -gcflags=all=-l -p 1
|
||||
+TEST_CMD := go test `go list ./cmd/... | grep -E 'server|controllers'` -race -count=1 -timeout=300s -cover -gcflags=all=-l -p 1
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
TEST_CMD := ETCD_UNSUPPORTED_ARCH=arm64 $(TEST_CMD)
|
||||
diff --git a/cmd/agent/server/containerd_image_test.go b/cmd/agent/server/containerd_image_test.go
|
||||
index d7133c3..85347c8 100644
|
||||
--- a/cmd/agent/server/containerd_image_test.go
|
||||
+++ b/cmd/agent/server/containerd_image_test.go
|
||||
@@ -32,7 +32,6 @@ func Test_conImageHandler_downloadImage(t *testing.T) {
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
-
|
||||
{
|
||||
name: "pullImageError",
|
||||
c: conImageHandler{},
|
||||
@@ -62,6 +61,15 @@ func Test_conImageHandler_downloadImage(t *testing.T) {
|
||||
want: "update-test1/upadte.img",
|
||||
wantErr: false,
|
||||
},
|
||||
+ {
|
||||
+ name: "invalid image name",
|
||||
+ c: conImageHandler{},
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{ContainerImage: "nginx;v1"},
|
||||
+ },
|
||||
+ want: "",
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
}
|
||||
patchPrepareEnv := gomonkey.ApplyFunc(prepareEnv, func() (preparePath, error) {
|
||||
return preparePath{updatePath: "update-test1/",
|
||||
diff --git a/cmd/agent/server/disk_image_test.go b/cmd/agent/server/disk_image_test.go
|
||||
index 71c5de7..265b323 100644
|
||||
--- a/cmd/agent/server/disk_image_test.go
|
||||
+++ b/cmd/agent/server/disk_image_test.go
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
+ "fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
@@ -52,36 +53,78 @@ func Test_download(t *testing.T) {
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
- // {name: "errornil", args: args{&pb.UpdateRequest{Certs: &pb.CertsInfo{}}}, want: "", wantErr: true},
|
||||
- // {name: "normal", args: args{&pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/", FlagSafe: true, Certs: &pb.CertsInfo{}}}, want: "/persist/update.img", wantErr: false},
|
||||
- // {name: "errornodir", args: args{&pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/", FlagSafe: true, Certs: &pb.CertsInfo{}}}, want: "", wantErr: true},
|
||||
+ {name: "errornil", args: args{&pb.UpdateRequest{Certs: &pb.CertsInfo{}}}, want: "", wantErr: true},
|
||||
+ {name: "error response", args: args{&pb.UpdateRequest{ImageUrl: "http://www.openeuler.abc", FlagSafe: true, Certs: &pb.CertsInfo{}}}, want: "", wantErr: true},
|
||||
{
|
||||
name: "normal",
|
||||
args: args{
|
||||
req: &pb.UpdateRequest{
|
||||
ImageUrl: "http://www.openeuler.org/zh/",
|
||||
+ FlagSafe: true,
|
||||
+ Certs: &pb.CertsInfo{},
|
||||
},
|
||||
},
|
||||
want: tmpFileForDownload,
|
||||
wantErr: false,
|
||||
},
|
||||
+ {
|
||||
+ name: "disk space not enough",
|
||||
+ args: args{
|
||||
+ req: &pb.UpdateRequest{
|
||||
+ ImageUrl: "http://www.openeuler.org/zh/",
|
||||
+ FlagSafe: true,
|
||||
+ Certs: &pb.CertsInfo{},
|
||||
+ },
|
||||
+ },
|
||||
+ want: "",
|
||||
+ wantErr: true,
|
||||
+ },
|
||||
}
|
||||
- patchStatfs := gomonkey.ApplyFunc(syscall.Statfs, func(path string, stat *syscall.Statfs_t) error {
|
||||
+ var patchStatfs *gomonkey.Patches
|
||||
+ patchStatfs = gomonkey.ApplyFunc(syscall.Statfs, func(path string, stat *syscall.Statfs_t) error {
|
||||
stat.Bfree = 3000
|
||||
stat.Bsize = 4096
|
||||
return nil
|
||||
})
|
||||
defer patchStatfs.Reset()
|
||||
- patchGetImageUrl := gomonkey.ApplyFuncReturn(getImageURL, &http.Response{
|
||||
- StatusCode: http.StatusOK,
|
||||
- ContentLength: 5,
|
||||
- Body: io.NopCloser(strings.NewReader("hello")),
|
||||
- }, nil)
|
||||
+ patchGetImageUrl := gomonkey.ApplyFuncSeq(getImageURL,
|
||||
+ []gomonkey.OutputCell{
|
||||
+ {Values: gomonkey.Params{&http.Response{}, fmt.Errorf("error")}},
|
||||
+ {Values: gomonkey.Params{&http.Response{StatusCode: http.StatusBadRequest, Body: io.NopCloser(strings.NewReader(""))}, nil}},
|
||||
+ {
|
||||
+ Values: gomonkey.Params{
|
||||
+ &http.Response{
|
||||
+ StatusCode: http.StatusOK,
|
||||
+ ContentLength: 5,
|
||||
+ Body: io.NopCloser(strings.NewReader("hello")),
|
||||
+ },
|
||||
+ nil,
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ Values: gomonkey.Params{
|
||||
+ &http.Response{
|
||||
+ StatusCode: http.StatusOK,
|
||||
+ ContentLength: 5,
|
||||
+ Body: io.NopCloser(strings.NewReader("hello")),
|
||||
+ },
|
||||
+ nil,
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ )
|
||||
defer patchGetImageUrl.Reset()
|
||||
patchOSCreate := gomonkey.ApplyFuncReturn(os.Create, tmpFile, nil)
|
||||
defer patchOSCreate.Reset()
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
+ if tt.name == "disk space not enough" {
|
||||
+ patchStatfs = gomonkey.ApplyFunc(syscall.Statfs, func(path string, stat *syscall.Statfs_t) error {
|
||||
+ stat.Bfree = 1
|
||||
+ stat.Bsize = 4096
|
||||
+ return nil
|
||||
+ })
|
||||
+ }
|
||||
got, err := download(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("download() error = %v, wantErr %v", err, tt.wantErr)
|
||||
@@ -160,13 +203,27 @@ func Test_getImageURL(t *testing.T) {
|
||||
MTLS: false,
|
||||
Certs: &pb.CertsInfo{},
|
||||
}}, want: &http.Response{StatusCode: http.StatusOK}, wantErr: false},
|
||||
+ {name: "httpsLoadCertsError", args: args{req: &pb.UpdateRequest{
|
||||
+ ImageUrl: "https://www.openeuler.abc/zh/",
|
||||
+ FlagSafe: true,
|
||||
+ MTLS: false,
|
||||
+ Certs: &pb.CertsInfo{},
|
||||
+ }}, want: &http.Response{}, wantErr: true},
|
||||
+ {name: "httpsMLTSLoadCertsError", args: args{req: &pb.UpdateRequest{
|
||||
+ ImageUrl: "https://www.openeuler.abc/zh/",
|
||||
+ FlagSafe: true,
|
||||
+ MTLS: true,
|
||||
+ Certs: &pb.CertsInfo{},
|
||||
+ }}, want: &http.Response{}, wantErr: true},
|
||||
}
|
||||
- patchLoadClientCerts := gomonkey.ApplyFunc(loadClientCerts, func(caCert, clientCert, clientKey string) (*http.Client, error) {
|
||||
- return &http.Client{}, nil
|
||||
+ patchLoadClientCerts := gomonkey.ApplyFuncSeq(loadClientCerts, []gomonkey.OutputCell{
|
||||
+ {Values: gomonkey.Params{&http.Client{}, nil}},
|
||||
+ {Values: gomonkey.Params{&http.Client{}, fmt.Errorf("error")}},
|
||||
})
|
||||
defer patchLoadClientCerts.Reset()
|
||||
- patchLoadCaCerts := gomonkey.ApplyFunc(loadCaCerts, func(caCert string) (*http.Client, error) {
|
||||
- return &http.Client{}, nil
|
||||
+ patchLoadCaCerts := gomonkey.ApplyFuncSeq(loadCaCerts, []gomonkey.OutputCell{
|
||||
+ {Values: gomonkey.Params{&http.Client{}, nil}},
|
||||
+ {Values: gomonkey.Params{&http.Client{}, fmt.Errorf("error")}},
|
||||
})
|
||||
defer patchLoadCaCerts.Reset()
|
||||
patchGet := gomonkey.ApplyFunc(http.Get, func(url string) (resp *http.Response, err error) {
|
||||
--
|
||||
2.39.0
|
||||
|
||||
126
0013-KubeOS-fix-clean-space-problems.patch
Normal file
126
0013-KubeOS-fix-clean-space-problems.patch
Normal file
@ -0,0 +1,126 @@
|
||||
From 1bc41e7e58e99e23cd8be522cc1c2d30090975d2 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Tue, 15 Aug 2023 16:33:11 +0800
|
||||
Subject: [PATCH 13/17] KubeOS: fix clean space problems
|
||||
|
||||
add clean space function in server
|
||||
change docker rm position in docker_image
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/main.go | 4 +---
|
||||
cmd/agent/server/docker_image.go | 6 +++---
|
||||
cmd/agent/server/server.go | 9 +++++++++
|
||||
cmd/agent/server/utils.go | 27 +++++++++++++--------------
|
||||
4 files changed, 26 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/cmd/agent/main.go b/cmd/agent/main.go
|
||||
index 67c7e2d..7b1ed3d 100644
|
||||
--- a/cmd/agent/main.go
|
||||
+++ b/cmd/agent/main.go
|
||||
@@ -13,8 +13,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
- "fmt"
|
||||
-
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
@@ -24,7 +22,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
- fmt.Println("Version is:", version.Version)
|
||||
+ logrus.Infoln("Version is:", version.Version)
|
||||
l, err := server.NewListener(server.SockDir, server.SockName)
|
||||
if err != nil {
|
||||
logrus.Errorln("listen error" + err.Error())
|
||||
diff --git a/cmd/agent/server/docker_image.go b/cmd/agent/server/docker_image.go
|
||||
index 0b6ee35..16bcea5 100644
|
||||
--- a/cmd/agent/server/docker_image.go
|
||||
+++ b/cmd/agent/server/docker_image.go
|
||||
@@ -61,13 +61,13 @@ func (d dockerImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath p
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
- if err := runCommand("docker", "cp", containerId+":/"+neededPath.rootfsFile, neededPath.updatePath); err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
defer func() {
|
||||
if err := runCommand("docker", "rm", containerId); err != nil {
|
||||
logrus.Errorln("remove kubeos-temp container error", err)
|
||||
}
|
||||
}()
|
||||
+ if err := runCommand("docker", "cp", containerId+":/"+neededPath.rootfsFile, neededPath.updatePath); err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
return neededPath.tarPath, nil
|
||||
}
|
||||
diff --git a/cmd/agent/server/server.go b/cmd/agent/server/server.go
|
||||
index 8ac6ffd..f8cbb41 100644
|
||||
--- a/cmd/agent/server/server.go
|
||||
+++ b/cmd/agent/server/server.go
|
||||
@@ -112,6 +112,15 @@ func (s *Server) update(req *pb.UpdateRequest) error {
|
||||
return fmt.Errorf("image type %s cannot be recognized", action)
|
||||
}
|
||||
imagePath, err := handler.downloadImage(req)
|
||||
+ defer func() {
|
||||
+ if err != nil {
|
||||
+ path := newPreparePath()
|
||||
+ if err := cleanSpace(path.updatePath, path.mountPath, path.imagePath); err != nil {
|
||||
+ logrus.Errorln("clean space error " + err.Error())
|
||||
+ }
|
||||
+ logrus.Infoln("clean space success")
|
||||
+ }
|
||||
+ }()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
diff --git a/cmd/agent/server/utils.go b/cmd/agent/server/utils.go
|
||||
index b42db18..d2d0946 100644
|
||||
--- a/cmd/agent/server/utils.go
|
||||
+++ b/cmd/agent/server/utils.go
|
||||
@@ -190,26 +190,25 @@ func prepareEnv() (preparePath, error) {
|
||||
if err := checkDiskSize(needGBSize, PersistDir); err != nil {
|
||||
return preparePath{}, err
|
||||
}
|
||||
- rootfsFile := rootfsArchive
|
||||
- updatePath := splicePath(PersistDir, updateDir)
|
||||
- mountPath := splicePath(updatePath, mountDir)
|
||||
- tarPath := splicePath(updatePath, rootfsFile)
|
||||
- imagePath := splicePath(PersistDir, osImageName)
|
||||
-
|
||||
- if err := cleanSpace(updatePath, mountPath, imagePath); err != nil {
|
||||
+ upgradePath := newPreparePath()
|
||||
+ if err := cleanSpace(upgradePath.updatePath, upgradePath.mountPath, upgradePath.imagePath); err != nil {
|
||||
return preparePath{}, err
|
||||
}
|
||||
- if err := os.MkdirAll(mountPath, imgPermission); err != nil {
|
||||
+ if err := os.MkdirAll(upgradePath.mountPath, imgPermission); err != nil {
|
||||
return preparePath{}, err
|
||||
}
|
||||
- upgradePath := preparePath{
|
||||
+ return upgradePath, nil
|
||||
+}
|
||||
+
|
||||
+func newPreparePath() preparePath {
|
||||
+ updatePath := splicePath(PersistDir, updateDir)
|
||||
+ return preparePath{
|
||||
updatePath: updatePath,
|
||||
- mountPath: mountPath,
|
||||
- tarPath: tarPath,
|
||||
- imagePath: imagePath,
|
||||
- rootfsFile: rootfsFile,
|
||||
+ mountPath: splicePath(updatePath, mountDir),
|
||||
+ tarPath: splicePath(updatePath, rootfsArchive),
|
||||
+ imagePath: splicePath(PersistDir, osImageName),
|
||||
+ rootfsFile: rootfsArchive,
|
||||
}
|
||||
- return upgradePath, nil
|
||||
}
|
||||
|
||||
func checkDiskSize(needGBSize int, path string) error {
|
||||
--
|
||||
2.39.0
|
||||
|
||||
20
0014-KubeOS-update-version.patch
Normal file
20
0014-KubeOS-update-version.patch
Normal file
@ -0,0 +1,20 @@
|
||||
From 9f0f03251a1bd0449f4e7e7ab5699e4771fbaa56 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Fri, 18 Aug 2023 17:19:53 +0800
|
||||
Subject: [PATCH 15/17] KubeOS: update version
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
VERSION | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/VERSION b/VERSION
|
||||
index 7dea76e..ee90284 100644
|
||||
--- a/VERSION
|
||||
+++ b/VERSION
|
||||
@@ -1 +1 @@
|
||||
-1.0.1
|
||||
+1.0.4
|
||||
--
|
||||
2.39.0
|
||||
|
||||
36
0015-KubeOS-add-line-breaks.patch
Normal file
36
0015-KubeOS-add-line-breaks.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 235a13b34e65b8d4ec4bde59e36247445b0778e8 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Tue, 15 Aug 2023 16:24:25 +0800
|
||||
Subject: [PATCH] KubeOS: add line breaks
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
scripts/admin-container/set-ssh-pub-key.service | 2 +-
|
||||
scripts/admin-container/set-ssh-pub-key.sh | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/scripts/admin-container/set-ssh-pub-key.service b/scripts/admin-container/set-ssh-pub-key.service
|
||||
index cf21406..84dd12d 100644
|
||||
--- a/scripts/admin-container/set-ssh-pub-key.service
|
||||
+++ b/scripts/admin-container/set-ssh-pub-key.service
|
||||
@@ -12,4 +12,4 @@
|
||||
Description="set ssh authorized keys according to the secret which is set by user"
|
||||
|
||||
[Service]
|
||||
-ExecStart="/usr/local/bin/set-ssh-pub-key.sh"
|
||||
\ No newline at end of file
|
||||
+ExecStart="/usr/local/bin/set-ssh-pub-key.sh"
|
||||
diff --git a/scripts/admin-container/set-ssh-pub-key.sh b/scripts/admin-container/set-ssh-pub-key.sh
|
||||
index aa706c2..e91a15d 100755
|
||||
--- a/scripts/admin-container/set-ssh-pub-key.sh
|
||||
+++ b/scripts/admin-container/set-ssh-pub-key.sh
|
||||
@@ -23,4 +23,4 @@ if [ ! -f "$authorized_file" ]; then
|
||||
chmod 600 "$authorized_file"
|
||||
fi
|
||||
|
||||
-echo "$ssh_pub" >> "$authorized_file"
|
||||
\ No newline at end of file
|
||||
+echo "$ssh_pub" >> "$authorized_file"
|
||||
--
|
||||
2.39.0
|
||||
|
||||
46
0016-KubeOS-modify-code-for-clean-code.patch
Normal file
46
0016-KubeOS-modify-code-for-clean-code.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From a01e5ebfd9c314b840eb3a652cda71e33954a403 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Wed, 16 Aug 2023 22:41:44 +0800
|
||||
Subject: [PATCH 16/17] KubeOS: modify code for clean code
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/config.go | 4 ++++
|
||||
cmd/operator/controllers/os_controller.go | 6 +++++-
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go
|
||||
index 20af267..a96370d 100644
|
||||
--- a/cmd/agent/server/config.go
|
||||
+++ b/cmd/agent/server/config.go
|
||||
@@ -317,6 +317,10 @@ func createConfigPath(configPath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+ err = f.Chmod(defaultKernelConPermission)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
f.Close()
|
||||
return nil
|
||||
}
|
||||
diff --git a/cmd/operator/controllers/os_controller.go b/cmd/operator/controllers/os_controller.go
|
||||
index 620739b..e152681 100644
|
||||
--- a/cmd/operator/controllers/os_controller.go
|
||||
+++ b/cmd/operator/controllers/os_controller.go
|
||||
@@ -94,7 +94,11 @@ func Reconcile(ctx context.Context, r common.ReadStatusWriter, req ctrl.Request)
|
||||
func (r *OSReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &upgradev1.OSInstance{}, values.OsiStatusName,
|
||||
func(rawObj client.Object) []string {
|
||||
- osi := rawObj.(*upgradev1.OSInstance)
|
||||
+ osi, ok := rawObj.(*upgradev1.OSInstance)
|
||||
+ if !ok {
|
||||
+ log.Error(nil, "failed to convert to osInstance")
|
||||
+ return []string{}
|
||||
+ }
|
||||
return []string{osi.Spec.NodeStatus}
|
||||
}); err != nil {
|
||||
return err
|
||||
--
|
||||
2.39.0
|
||||
|
||||
176
0017-KubeOS-fix-the-issue-that-osinstance-is-not-updated-.patch
Normal file
176
0017-KubeOS-fix-the-issue-that-osinstance-is-not-updated-.patch
Normal file
@ -0,0 +1,176 @@
|
||||
From 0c0f3c7ef5749b8806511d9e3312f6cacd4cca04 Mon Sep 17 00:00:00 2001
|
||||
From: liyuanr <liyuanrong1@huawei.com>
|
||||
Date: Tue, 15 Aug 2023 12:29:11 +0000
|
||||
Subject: [PATCH 17/17] KubeOS: fix the issue that osinstance is not updated in
|
||||
time during proxy upgrade.
|
||||
|
||||
Fix the problem that osinstance is not updated in time during proxy upgrade,
|
||||
but the node upgrade tag has been added. As a result, the configuration is skipped
|
||||
and the upgrade is directly performed.
|
||||
|
||||
Signed-off-by: liyuanr <liyuanrong1@huawei.com>
|
||||
---
|
||||
cmd/proxy/controllers/os_controller.go | 11 ++
|
||||
cmd/proxy/controllers/os_controller_test.go | 126 ++++++++++++++++++++
|
||||
2 files changed, 137 insertions(+)
|
||||
|
||||
diff --git a/cmd/proxy/controllers/os_controller.go b/cmd/proxy/controllers/os_controller.go
|
||||
index 30f9839..b8d0f80 100644
|
||||
--- a/cmd/proxy/controllers/os_controller.go
|
||||
+++ b/cmd/proxy/controllers/os_controller.go
|
||||
@@ -126,6 +126,17 @@ func (r *OSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re
|
||||
}
|
||||
return values.Requeue, nil
|
||||
}
|
||||
+ if _, ok := node.Labels[values.LabelUpgrading]; ok &&
|
||||
+ osInstance.Spec.NodeStatus == values.NodeStatusIdle.String() {
|
||||
+ log.Info("node has upgrade label, but osInstance.spec.nodestaus idle ",
|
||||
+ "operation:", "refesh node and wait opetaot reassgin")
|
||||
+ if err = r.refreshNode(ctx, &node, osInstance, osCr.Spec.UpgradeConfigs.Version,
|
||||
+ values.UpgradeConfigName); err != nil {
|
||||
+ return values.RequeueNow, err
|
||||
+ }
|
||||
+ return values.Requeue, nil
|
||||
+ }
|
||||
+
|
||||
if err := r.setConfig(ctx, osInstance, values.UpgradeConfigName); err != nil {
|
||||
return values.RequeueNow, err
|
||||
}
|
||||
diff --git a/cmd/proxy/controllers/os_controller_test.go b/cmd/proxy/controllers/os_controller_test.go
|
||||
index d63f176..27cb0cd 100644
|
||||
--- a/cmd/proxy/controllers/os_controller_test.go
|
||||
+++ b/cmd/proxy/controllers/os_controller_test.go
|
||||
@@ -1098,4 +1098,130 @@ var _ = Describe("OsController", func() {
|
||||
Expect(ok).Should(Equal(false))
|
||||
})
|
||||
})
|
||||
+
|
||||
+ Context("When node has upgrade label but osinstance.spec.nodestatus is idle", func() {
|
||||
+ It("Should be able to refresh node and wait operator reassgin upgrade", func() {
|
||||
+ ctx := context.Background()
|
||||
+ By("Creating a worker node")
|
||||
+ node1Name = "test-node-" + uuid.New().String()
|
||||
+ node1 := &v1.Node{
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node1Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ "beta.kubernetes.io/os": "linux",
|
||||
+ values.LabelUpgrading: "",
|
||||
+ },
|
||||
+ },
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "v1",
|
||||
+ Kind: "Node",
|
||||
+ },
|
||||
+ Status: v1.NodeStatus{
|
||||
+ NodeInfo: v1.NodeSystemInfo{
|
||||
+ OSImage: "KubeOS v2",
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+ err := k8sClient.Create(ctx, node1)
|
||||
+ Expect(err).ToNot(HaveOccurred())
|
||||
+ existingNode := &v1.Node{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(context.Background(),
|
||||
+ types.NamespacedName{Name: node1Name, Namespace: testNamespace}, existingNode)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ reconciler.hostName = node1Name
|
||||
+
|
||||
+ By("Creating the corresponding OSInstance")
|
||||
+ OSIns := &upgradev1.OSInstance{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ Kind: "OSInstance",
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: node1Name,
|
||||
+ Namespace: testNamespace,
|
||||
+ Labels: map[string]string{
|
||||
+ values.LabelOSinstance: node1Name,
|
||||
+ },
|
||||
+ },
|
||||
+ Spec: upgradev1.OSInstanceSpec{
|
||||
+ NodeStatus: values.NodeStatusIdle.String(),
|
||||
+ },
|
||||
+ Status: upgradev1.OSInstanceStatus{},
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed())
|
||||
+
|
||||
+ // Check that the corresponding OSIns CR has been created
|
||||
+ osInsCRLookupKey := types.NamespacedName{Name: node1Name, Namespace: testNamespace}
|
||||
+ createdOSIns := &upgradev1.OSInstance{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOSIns.ObjectMeta.Name).Should(Equal(node1Name))
|
||||
+ By("Creating a OS custom resource")
|
||||
+ OS := &upgradev1.OS{
|
||||
+ TypeMeta: metav1.TypeMeta{
|
||||
+ APIVersion: "upgrade.openeuler.org/v1alpha1",
|
||||
+ Kind: "OS",
|
||||
+ },
|
||||
+ ObjectMeta: metav1.ObjectMeta{
|
||||
+ Name: OSName,
|
||||
+ Namespace: testNamespace,
|
||||
+ },
|
||||
+ Spec: upgradev1.OSSpec{
|
||||
+ OpsType: "upgrade",
|
||||
+ MaxUnavailable: 3,
|
||||
+ OSVersion: "KubeOS v2",
|
||||
+ FlagSafe: true,
|
||||
+ MTLS: false,
|
||||
+ EvictPodForce: true,
|
||||
+ SysConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v2",
|
||||
+ Configs: []upgradev1.SysConfig{
|
||||
+ {
|
||||
+ Model: "kernel.sysctl",
|
||||
+ Contents: []upgradev1.Content{
|
||||
+ {Key: "key1", Value: "c"},
|
||||
+ {Key: "key2", Value: "d"},
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ UpgradeConfigs: upgradev1.SysConfigs{
|
||||
+ Version: "v2",
|
||||
+ Configs: []upgradev1.SysConfig{
|
||||
+ {
|
||||
+ Model: "kernel.sysctl",
|
||||
+ Contents: []upgradev1.Content{
|
||||
+ {Key: "key1", Value: "a"},
|
||||
+ {Key: "key2", Value: "b"},
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+ Expect(k8sClient.Create(ctx, OS)).Should(Succeed())
|
||||
+ osCRLookupKey := types.NamespacedName{Name: OSName, Namespace: testNamespace}
|
||||
+ createdOS := &upgradev1.OS{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(ctx, osCRLookupKey, createdOS)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v2"))
|
||||
+
|
||||
+ time.Sleep(2 * time.Second) // sleep a while to make sure Reconcile finished
|
||||
+ existingNode = &v1.Node{}
|
||||
+ Eventually(func() bool {
|
||||
+ err := k8sClient.Get(context.Background(),
|
||||
+ types.NamespacedName{Name: node1Name, Namespace: testNamespace}, existingNode)
|
||||
+ return err == nil
|
||||
+ }, timeout, interval).Should(BeTrue())
|
||||
+ _, ok := existingNode.Labels[values.LabelUpgrading]
|
||||
+ Expect(ok).Should(Equal(false))
|
||||
+ })
|
||||
+ })
|
||||
})
|
||||
--
|
||||
2.39.0
|
||||
|
||||
39
0018-KubeOS-update-config-log-contents.patch
Normal file
39
0018-KubeOS-update-config-log-contents.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 662f68aa131c09154bb91085e4657beaee00d1d6 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Mon, 21 Aug 2023 09:58:45 +0800
|
||||
Subject: [PATCH 1/5] KubeOS: update config log contents
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/agent/server/config.go | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go
|
||||
index a96370d..f186ee6 100644
|
||||
--- a/cmd/agent/server/config.go
|
||||
+++ b/cmd/agent/server/config.go
|
||||
@@ -57,7 +57,7 @@ func (k KernelSysctl) SetConfig(config *agent.SysConfig) error {
|
||||
}
|
||||
logrus.Infof("Configured kernel.sysctl %s=%s", key, keyInfo.Value)
|
||||
} else {
|
||||
- logrus.Warnf("Failed to parse kernel.sysctl key: %s value: %s operation: %s", key, keyInfo.Value, keyInfo.Operation)
|
||||
+ logrus.Warnf("Failed to parse kernel.sysctl, key: %s, value: %s, operation: %s", key, keyInfo.Value, keyInfo.Operation)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -97,7 +97,11 @@ type GrubCmdline struct {
|
||||
|
||||
// SetConfig sets grub.cmdline configuration
|
||||
func (g GrubCmdline) SetConfig(config *agent.SysConfig) error {
|
||||
- logrus.Info("start set grub.cmdline configuration")
|
||||
+ if g.isCurPartition {
|
||||
+ logrus.Info("start set grub.cmdline.current configuration")
|
||||
+ } else {
|
||||
+ logrus.Info("start set grub.cmdline.next configuration")
|
||||
+ }
|
||||
fileExist, err := checkFileExist(getGrubCfgPath())
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to find config path: %v", err)
|
||||
--
|
||||
2.39.0
|
||||
|
||||
1069
0019-KubeOS-add-unit-tests.patch
Normal file
1069
0019-KubeOS-add-unit-tests.patch
Normal file
File diff suppressed because it is too large
Load Diff
86
0020-KubeOS-modify-code-for-clean-code.patch
Normal file
86
0020-KubeOS-modify-code-for-clean-code.patch
Normal file
@ -0,0 +1,86 @@
|
||||
From a9220ad3175c38979a052cd595efd34888d886c6 Mon Sep 17 00:00:00 2001
|
||||
From: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
Date: Thu, 24 Aug 2023 11:00:04 +0800
|
||||
Subject: [PATCH 3/5] KubeOS: modify code for clean code
|
||||
|
||||
add err handler in NewControllerManager
|
||||
|
||||
Signed-off-by: Yuhang Wei <weiyuhang3@huawei.com>
|
||||
---
|
||||
cmd/operator/main.go | 6 +++++-
|
||||
cmd/proxy/main.go | 8 ++++++--
|
||||
pkg/common/common.go | 7 +++----
|
||||
3 files changed, 14 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/cmd/operator/main.go b/cmd/operator/main.go
|
||||
index 17b74e1..8249ad2 100644
|
||||
--- a/cmd/operator/main.go
|
||||
+++ b/cmd/operator/main.go
|
||||
@@ -41,7 +41,11 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
- mgr := common.NewControllerManager(setupLog, scheme)
|
||||
+ mgr, err := common.NewControllerManager(setupLog, scheme)
|
||||
+ if err != nil {
|
||||
+ setupLog.Error(err, "unable to start manager")
|
||||
+ os.Exit(1)
|
||||
+ }
|
||||
|
||||
if err := (&controllers.OSReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go
|
||||
index ce1f58d..3a537d9 100644
|
||||
--- a/cmd/proxy/main.go
|
||||
+++ b/cmd/proxy/main.go
|
||||
@@ -44,10 +44,14 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
- mgr := common.NewControllerManager(setupLog, scheme)
|
||||
+ var err error
|
||||
+ mgr, err := common.NewControllerManager(setupLog, scheme)
|
||||
+ if err != nil {
|
||||
+ setupLog.Error(err, "unable to start manager")
|
||||
+ os.Exit(1)
|
||||
+ }
|
||||
|
||||
reconciler := controllers.NewOSReconciler(mgr)
|
||||
- var err error
|
||||
if reconciler.Connection, err = agentclient.New("unix://" + filepath.Join(server.SockDir, server.SockName)); err != nil {
|
||||
setupLog.Error(err, "Error running proxy")
|
||||
}
|
||||
diff --git a/pkg/common/common.go b/pkg/common/common.go
|
||||
index 4653a61..e888179 100644
|
||||
--- a/pkg/common/common.go
|
||||
+++ b/pkg/common/common.go
|
||||
@@ -15,7 +15,6 @@ package common
|
||||
|
||||
import (
|
||||
"flag"
|
||||
- "os"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -33,7 +32,7 @@ type ReadStatusWriter interface {
|
||||
}
|
||||
|
||||
// NewControllerManager configure and return a manager
|
||||
-func NewControllerManager(setupLog logr.Logger, scheme *runtime.Scheme) manager.Manager {
|
||||
+func NewControllerManager(setupLog logr.Logger, scheme *runtime.Scheme) (manager.Manager, error) {
|
||||
opts := zap.Options{}
|
||||
opts.BindFlags(flag.CommandLine)
|
||||
|
||||
@@ -46,7 +45,7 @@ func NewControllerManager(setupLog logr.Logger, scheme *runtime.Scheme) manager.
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to start manager")
|
||||
- os.Exit(1)
|
||||
+ return nil, err
|
||||
}
|
||||
- return mgr
|
||||
+ return mgr, nil
|
||||
}
|
||||
--
|
||||
2.39.0
|
||||
|
||||
1867
0021-KubeOS-delete-raw-and-docker-image-upgrade.patch
Normal file
1867
0021-KubeOS-delete-raw-and-docker-image-upgrade.patch
Normal file
File diff suppressed because it is too large
Load Diff
1671
0022-KubeOS-delete-scripts-except-admin-container.patch
Normal file
1671
0022-KubeOS-delete-scripts-except-admin-container.patch
Normal file
File diff suppressed because it is too large
Load Diff
31
KubeOS.spec
31
KubeOS.spec
@ -2,11 +2,32 @@
|
||||
|
||||
Name: KubeOS
|
||||
Version: 1.0.4
|
||||
Release: 2
|
||||
Release: 3
|
||||
Summary: O&M platform used to update the whole OS as an entirety
|
||||
License: Mulan PSL v2
|
||||
Source0: https://gitee.com/openeuler/KubeOS/repository/archive/v%{version}.tar.gz
|
||||
Patch1: 0001-KubeOS-fix-the-hostshell-cannot-obtain-the-lib.patch
|
||||
Patch1: 0001-KubeOS-add-unit-tests-of-containerd-and-docker-modif.patch
|
||||
Patch2: 0002-KubeOS-refactor-assignUpgrade-function.patch
|
||||
Patch3: 0003-KubeOS-fix-the-hostshell-cannot-obtain-the-lib.patch
|
||||
Patch4: 0004-KubeOS-add-agent-proxy-and-operator-ut.patch
|
||||
Patch5: 0005-KubeOS-fix-validate-image-name-bug.patch
|
||||
Patch6: 0006-KubeOS-fix-a-bug-that-failed-to-parse-key-with.patch
|
||||
Patch7: 0007-KubeOS-add-warning-log-during-config.patch
|
||||
Patch8: 0008-KubeOS-modify-log-level-and-content.patch
|
||||
Patch9: 0009-KubeOS-fix-updating-key-to-kv.patch
|
||||
Patch10: 0010-KubeOS-fix-proxy-requeue-bug.patch
|
||||
Patch11: 0011-KubeOS-fix-operator-bug-of-missing-deep-copy.patch
|
||||
Patch12: 0012-KubeOS-add-unit-test.patch
|
||||
Patch13: 0013-KubeOS-fix-clean-space-problems.patch
|
||||
Patch14: 0014-KubeOS-update-version.patch
|
||||
Patch15: 0015-KubeOS-add-line-breaks.patch
|
||||
Patch16: 0016-KubeOS-modify-code-for-clean-code.patch
|
||||
Patch17: 0017-KubeOS-fix-the-issue-that-osinstance-is-not-updated-.patch
|
||||
Patch18: 0018-KubeOS-update-config-log-contents.patch
|
||||
Patch19: 0019-KubeOS-add-unit-tests.patch
|
||||
Patch20: 0020-KubeOS-modify-code-for-clean-code.patch
|
||||
Patch21: 0021-KubeOS-delete-raw-and-docker-image-upgrade.patch
|
||||
Patch22: 0022-KubeOS-delete-scripts-except-admin-container.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRequires: make
|
||||
@ -83,6 +104,12 @@ install -p -m 0600 ./scripts/admin-container/set-ssh-pub-key.service %{buildroot
|
||||
rm -rfv %{buildroot}
|
||||
|
||||
%changelog
|
||||
* Thu Aug 24 2023 Yuhang Wei<weiyuhang3@huawei.com> - 1.0.4-3
|
||||
- Type:requirement
|
||||
- CVE:NA
|
||||
- SUG:restart
|
||||
- DESC:sync code from source master branch
|
||||
|
||||
* Mon Aug 07 2023 liyuanrong<liyuanrong1@huawei.com> - 1.0.4-2
|
||||
- Type:requirement
|
||||
- CVE:NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user