diff --git a/0001-KubeOS-add-unit-tests-of-containerd-and-docker-modif.patch b/0001-KubeOS-add-unit-tests-of-containerd-and-docker-modif.patch deleted file mode 100644 index 3b1f0491bc3d15c4d44e061c005fe344f5f187e5..0000000000000000000000000000000000000000 --- a/0001-KubeOS-add-unit-tests-of-containerd-and-docker-modif.patch +++ /dev/null @@ -1,479 +0,0 @@ -From 790d53dc581874575aef1777122856a59bcdbf8b Mon Sep 17 00:00:00 2001 -From: liyuanr -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 ---- - 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 - diff --git a/0001-build-rust-os-agent-remove-useless-dependency.patch b/0001-build-rust-os-agent-remove-useless-dependency.patch new file mode 100644 index 0000000000000000000000000000000000000000..c6270b09a1bb632570c12c0b63408dce3dccc1fd --- /dev/null +++ b/0001-build-rust-os-agent-remove-useless-dependency.patch @@ -0,0 +1,56 @@ +From 6e62adfa80c33d9b1fc4445487cc15e721db07bc Mon Sep 17 00:00:00 2001 +From: Yuhang Wei +Date: Wed, 10 Jan 2024 15:53:26 +0800 +Subject: [PATCH] build(rust os-agent): remove useless dependency + +Signed-off-by: Yuhang Wei +--- + KubeOS-Rust/Cargo.lock | 11 ----------- + KubeOS-Rust/manager/Cargo.toml | 2 +- + 2 files changed, 1 insertion(+), 12 deletions(-) + +diff --git a/KubeOS-Rust/Cargo.lock b/KubeOS-Rust/Cargo.lock +index 4b7fc12..2087339 100644 +--- a/KubeOS-Rust/Cargo.lock ++++ b/KubeOS-Rust/Cargo.lock +@@ -199,16 +199,6 @@ dependencies = [ + "serde_json", + ] + +-[[package]] +-name = "colored" +-version = "2.1.0" +-source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +-dependencies = [ +- "lazy_static", +- "windows-sys", +-] +- + [[package]] + name = "core-foundation" + version = "0.9.3" +@@ -1209,7 +1199,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" + checksum = "80f9fece9bd97ab74339fe19f4bcaf52b76dcc18e5364c7977c1838f76b38de9" + dependencies = [ + "assert-json-diff", +- "colored", + "httparse", + "lazy_static", + "log", +diff --git a/KubeOS-Rust/manager/Cargo.toml b/KubeOS-Rust/manager/Cargo.toml +index 40672cc..9431fba 100644 +--- a/KubeOS-Rust/manager/Cargo.toml ++++ b/KubeOS-Rust/manager/Cargo.toml +@@ -8,7 +8,7 @@ version = "0.1.0" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dev-dependencies] + mockall = { version = "=0.11.3" } +-mockito = { version = "0.31.1" } ++mockito = { version = "0.31.1", default-features = false } + predicates = { version = "=2.0.1" } + tempfile = { version = "3.6.0" } + +-- +2.34.1 + diff --git a/0002-KubeOS-refactor-assignUpgrade-function.patch b/0002-KubeOS-refactor-assignUpgrade-function.patch deleted file mode 100644 index aa76b8713cf9bebc64340b715de15901d1403e92..0000000000000000000000000000000000000000 --- a/0002-KubeOS-refactor-assignUpgrade-function.patch +++ /dev/null @@ -1,346 +0,0 @@ -From 64e36143591c014609fc517bcd6ee0f3ae1087fc Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0003-KubeOS-fix-the-hostshell-cannot-obtain-the-lib.patch b/0003-KubeOS-fix-the-hostshell-cannot-obtain-the-lib.patch deleted file mode 100644 index bf46e8bbbd0a01ca797fae5e3f7ff8d485a55dcd..0000000000000000000000000000000000000000 --- a/0003-KubeOS-fix-the-hostshell-cannot-obtain-the-lib.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 470e190db2de92b65e7fa720864823e7245c51e9 Mon Sep 17 00:00:00 2001 -From: liyuanr -Date: Mon, 7 Aug 2023 19:09:18 +0800 -Subject: [PATCH 03/17] KubeOS: fix the hostshell cannot obtain the lib - -Fix the hostshell cannot obtain the lib - -Signed-off-by: liyuanr ---- - cmd/admin-container/main.go | 40 +++++++++++++++++++++++++------------ - 1 file changed, 27 insertions(+), 13 deletions(-) - -diff --git a/cmd/admin-container/main.go b/cmd/admin-container/main.go -index f6a7293..5fa0838 100644 ---- a/cmd/admin-container/main.go -+++ b/cmd/admin-container/main.go -@@ -22,28 +22,42 @@ import ( - "github.com/sirupsen/logrus" - ) - -+const ( -+ bashPath = "/usr/bin/bash" -+ usrBin = "/usr/bin" -+ usrSbin = "/usr/sbin" -+ localBin = "/usr/local/bin" -+ localSbin = "/usr/local/sbin" -+ usrLib = "/usr/lib" -+ usrLib64 = "/usr/lib64" -+ lib = "/lib" -+ lib64 = "/lib64" -+ envPathPrefix = "PATH=$PATH:" -+ envLdLibrarPathPrefix = "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:" -+) -+ - func main() { - EUID := os.Geteuid() - rootEUID := 0 // 0 indicates that the process has the permission of the root user. - if EUID != rootEUID { - logrus.Error("please use root to run hostshell") -- return -+ - } - PPID := os.Getppid() - rootFsPath := "/proc/" + strconv.Itoa(PPID) + "/root" -- bashPath := "/usr/bin/bash" -- usrBin := "/usr/bin" -- usrSbin := "/usr/sbin" -- localBin := "/usr/local/bin" -- localSbin := "/usr/local/sbin" -- paths := []string{usrBin, usrSbin, localBin, localSbin} -- for i, p := range paths { -- paths[i] = rootFsPath + p -- } -- path := "PATH=$PATH:" + strings.Join(paths, ":") -- lib := "LD_LIBRARY_PATH=/lib:/lib64:/usr/lib:/usr/lib64:$LD_LIBRARY_PATH" -+ path := concatenateEnvPath(rootFsPath, envPathPrefix, []string{usrBin, usrSbin, localBin, localSbin}) -+ libPath := concatenateEnvPath(rootFsPath, envLdLibrarPathPrefix, []string{usrLib, usrLib64, lib, lib64}) - if err := syscall.Exec("/usr/bin/nsenter", []string{"nsenter", "-t", "1", "-a", -- "env", "-i", path, lib, rootFsPath + bashPath}, os.Environ()); err != nil { -+ "env", "-i", path, libPath, rootFsPath + bashPath}, os.Environ()); err != nil { - logrus.Error("nsenter excute error", err) - } - } -+ -+func concatenateEnvPath(prefix string, envVarPrefix string, paths []string) string { -+ for i, p := range paths { -+ paths[i] = prefix + p -+ } -+ pathLine := envVarPrefix + strings.Join(paths, ":") -+ pathEnv := os.ExpandEnv(pathLine) -+ return pathEnv -+} --- -2.39.0 - diff --git a/0004-KubeOS-add-agent-proxy-and-operator-ut.patch b/0004-KubeOS-add-agent-proxy-and-operator-ut.patch deleted file mode 100644 index 87d9cdf53caeeb40d1f7ae636e52d43e86b41f6d..0000000000000000000000000000000000000000 --- a/0004-KubeOS-add-agent-proxy-and-operator-ut.patch +++ /dev/null @@ -1,1413 +0,0 @@ -From 923529f49a9f4a8d9678e087735459ea875ac5d6 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Fri, 4 Aug 2023 10:17:24 +0800 -Subject: [PATCH 04/17] KubeOS: add agent, proxy and operator ut add - disk_image, server, config, proxy and operator unit testing fix the bug that - agent allows configuring kv with nil key - -Signed-off-by: Yuhang Wei ---- - Makefile | 4 +- - cmd/agent/server/config.go | 4 + - cmd/agent/server/config_test.go | 130 +++++++-- - cmd/agent/server/disk_image.go | 8 +- - cmd/agent/server/disk_image_test.go | 262 ++++++++++++------ - cmd/agent/server/server.go | 4 + - cmd/agent/server/server_test.go | 86 +++++- - cmd/agent/server/utils_test.go | 146 +++++++++- - .../controllers/os_controller_test.go | 67 +++++ - cmd/operator/controllers/suite_test.go | 2 +- - cmd/proxy/controllers/os_controller.go | 6 + - cmd/proxy/controllers/os_controller_test.go | 153 +++++++++- - cmd/proxy/controllers/suite_test.go | 2 +- - 13 files changed, 748 insertions(+), 126 deletions(-) - -diff --git a/Makefile b/Makefile -index fbabda6..b5b6161 100644 ---- a/Makefile -+++ b/Makefile -@@ -133,14 +133,14 @@ 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 -+TEST_CMD := go test ./... -race -count=1 -timeout=300s -cover -gcflags=all=-l -p 1 - - ifeq ($(ARCH), aarch64) - TEST_CMD := ETCD_UNSUPPORTED_ARCH=arm64 $(TEST_CMD) - endif - - .PHONY: test --test: manifests fmt vet envtest ## Run tests. -+test: fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" $(TEST_CMD) - - .PHONY: envtest -diff --git a/cmd/agent/server/config.go b/cmd/agent/server/config.go -index e7110f8..653f913 100644 ---- a/cmd/agent/server/config.go -+++ b/cmd/agent/server/config.go -@@ -374,6 +374,10 @@ 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") -+ continue -+ } - if keyInfo.Operation == "delete" { - logrus.Warnf("Failed to delete inexistent key %s", key) - continue -diff --git a/cmd/agent/server/config_test.go b/cmd/agent/server/config_test.go -index 903af87..2deb15f 100644 ---- a/cmd/agent/server/config_test.go -+++ b/cmd/agent/server/config_test.go -@@ -67,6 +67,15 @@ func TestKernelSysctl_SetConfig(t *testing.T) { - }, - }}, - }, -+ { -+ name: "nil value", -+ k: KernelSysctl{}, -+ args: args{config: &agent.SysConfig{ -+ Contents: map[string]*agent.KeyInfo{ -+ "d": {Value: ""}, -+ }, -+ }}, -+ }, - } - tmpDir := t.TempDir() - patchGetProcPath := gomonkey.ApplyFuncReturn(getDefaultProcPath, tmpDir+"/") -@@ -84,6 +93,7 @@ func TestKernelSysctl_SetConfig(t *testing.T) { - func TestKerSysctlPersist_SetConfig(t *testing.T) { - tmpDir := t.TempDir() - persistPath := tmpDir + "/test-persist.conf" -+ comment := `# This file is managed by KubeOS for unit testing.` - type args struct { - config *agent.SysConfig - } -@@ -94,6 +104,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) { - want []string - wantErr bool - }{ -+ {name: "create file", args: args{config: &agent.SysConfig{ConfigPath: persistPath}}, want: []string{comment}, wantErr: false}, - { - name: "add configs", - args: args{ -@@ -103,12 +114,15 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) { - "a": {Value: "1"}, - "b": {Value: "2"}, - "c": {Value: ""}, -+ "": {Value: "4"}, -+ "e": {Value: "5"}, - }, - }, - }, - want: []string{ - "a=1", - "b=2", -+ "e=5", - }, - wantErr: false, - }, -@@ -126,6 +140,7 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) { - want: []string{ - "a=2", - "b=2", -+ "e=5", - }, - wantErr: false, - }, -@@ -137,11 +152,16 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) { - Contents: map[string]*agent.KeyInfo{ - "a": {Value: "1", Operation: "delete"}, - "b": {Value: "2", Operation: "delete"}, -+ "c": {Value: "3", Operation: "delete"}, -+ "e": {Value: "5", Operation: "remove"}, -+ "f": {Value: "6", Operation: "remove"}, - }, - }, - }, - want: []string{ - "a=2", -+ "e=5", -+ "f=6", - }, - wantErr: false, - }, -@@ -152,14 +172,21 @@ func TestKerSysctlPersist_SetConfig(t *testing.T) { - if err := k.SetConfig(tt.args.config); (err != nil) != tt.wantErr { - t.Errorf("KerSysctlPersist.SetConfig() error = %v, wantErr %v", err, tt.wantErr) - } -+ if tt.name == "create file" { -+ if err := os.WriteFile(persistPath, []byte(comment), 0644); err != nil { -+ t.Fatalf("failed to write file %s", persistPath) -+ } -+ } - data, err := os.ReadFile(persistPath) - if err != nil { - t.Errorf("failed to read file %s", persistPath) - } - lines := strings.Split(string(data), "\n") -- // remove the last empty line -- lines = lines[:len(lines)-1] -- sort.Strings(lines) -+ if tt.name != "create file" { -+ // remove the comment and the last empty line -+ lines = lines[1 : len(lines)-1] -+ sort.Strings(lines) -+ } - if !reflect.DeepEqual(lines, tt.want) { - t.Errorf("KerSysctlPersist file contents not equal, expect: %v, get: %v", tt.want, lines) - } -@@ -210,17 +237,36 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri - args: args{ - config: &agent.SysConfig{ - Contents: map[string]*agent.KeyInfo{ -- "panic": {Value: "5"}, // update existent kv -- "quiet": {Value: "", Operation: "delete"}, // delete existent key -- "oops": {Value: ""}, // update existent kv with null value -- "selinux": {Value: "1", Operation: "delete"}, // failed to delete inconsistent kv -- "acpi": {Value: "off", Operation: "delete"}, // failed to delete inexistent kv -- "debug": {}, // add key -- "pci": {Value: "nomis"}, // add kv -+ "debug": {}, // add key -+ "pci": {Value: "nomis"}, // add kv -+ "quiet": {Value: "", Operation: "delete"}, // delete existent key -+ "panic": {Value: "5"}, // update existent kv -+ "nomodeset": {Operation: "update"}, // invalid operation, default to update existent key -+ "softlockup_panic": {Value: "0", Operation: "update"}, // invalid operation, default to update existent kv -+ "oops": {Value: ""}, // warning, skip, update existent kv with null value -+ "": {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 - }, - }, - }, -- 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=1\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\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, -+ }, -+ { -+ name: "delete and invalid operation", -+ g: GrubCmdline{isCurPartition: true}, -+ 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 -+ }, -+ }, -+ }, -+ 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)$`, - wantErr: false, - }, - { -@@ -229,23 +275,27 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri - args: args{ - config: &agent.SysConfig{ - Contents: map[string]*agent.KeyInfo{ -- "panic": {Value: "4"}, -- "quiet": {Value: "", Operation: "delete"}, -- "oops": {Value: ""}, // update existent kv with null value -- "selinux": {Value: "1", Operation: "delete"}, -- "acpi": {Value: "off", Operation: "delete"}, -- "debug": {}, -- "pci": {Value: "nomis"}, -+ "debug": {}, -+ "pci": {Value: "nomis"}, -+ "quiet": {Value: "", Operation: "delete"}, -+ "panic": {Value: "4"}, -+ "nomodeset": {Operation: "update"}, // invalid operation, default to update existent key -+ "softlockup_panic": {Value: "0", Operation: "update"}, // invalid operation, default to update existent kv -+ "oops": {Value: ""}, // update existent kv with null value -+ "": {Value: "test"}, // warning, skip, failed to add kv with empty key -+ "selinux": {Value: "1", Operation: "delete"}, -+ "acpi": {Value: "off", Operation: "delete"}, - }, - }, - }, -- 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=1\s+nmi_watchdog=1\s+rd\.shell=0\s+selinux=0\s+crashkernel=256M\s+panic=4\s+(debug\spci=nomis|pci=nomis\sdebug)$`, -+ 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=4\s+(debug\spci=nomis|pci=nomis\sdebug)$`, - wantErr: false, - }, - } - patchGetGrubPath := gomonkey.ApplyFuncReturn(getGrubCfgPath, grubCfgPath) - defer patchGetGrubPath.Reset() - patchGetConfigPartition := gomonkey.ApplyFuncSeq(getConfigPartition, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{false, nil}}, - {Values: gomonkey.Params{false, nil}}, - {Values: gomonkey.Params{true, nil}}, - }) -@@ -375,3 +425,45 @@ func Test_getGrubCfgPath(t *testing.T) { - }) - } - } -+ -+func Test_getConfigPartition(t *testing.T) { -+ type args struct { -+ isCurPartition bool -+ } -+ tests := []struct { -+ name string -+ args args -+ want bool -+ wantErr bool -+ }{ -+ { -+ name: "get current partition", -+ args: args{isCurPartition: true}, -+ want: false, -+ wantErr: false, -+ }, -+ { -+ name: "get next partition", -+ args: args{isCurPartition: false}, -+ want: true, -+ wantErr: false, -+ }, -+ } -+ patchRootfsDisks := gomonkey.ApplyFuncReturn(getRootfsDisks, "/dev/sda2", "/dev/sda3", nil) -+ defer patchRootfsDisks.Reset() -+ // assume now is partition A, want to swiching to partition B -+ patchGetNextPartition := gomonkey.ApplyFuncReturn(getNextPart, "/dev/sda3", "B", nil) -+ defer patchGetNextPartition.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := getConfigPartition(tt.args.isCurPartition) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("getConfigPartition() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("getConfigPartition() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -diff --git a/cmd/agent/server/disk_image.go b/cmd/agent/server/disk_image.go -index c89003b..8bd6bf6 100644 ---- a/cmd/agent/server/disk_image.go -+++ b/cmd/agent/server/disk_image.go -@@ -153,7 +153,7 @@ func loadCaCerts(caCert string) (*http.Client, error) { - if err != nil { - return &http.Client{}, err - } -- ca, err := ioutil.ReadFile(certPath + caCert) -+ ca, err := ioutil.ReadFile(getCertPath() + caCert) - if err != nil { - return &http.Client{}, fmt.Errorf("read the ca certificate error %s", err) - } -@@ -173,7 +173,7 @@ func loadClientCerts(caCert, clientCert, clientKey string) (*http.Client, error) - if err != nil { - return &http.Client{}, err - } -- ca, err := ioutil.ReadFile(certPath + caCert) -+ ca, err := ioutil.ReadFile(getCertPath() + caCert) - if err != nil { - return &http.Client{}, err - } -@@ -186,7 +186,7 @@ func loadClientCerts(caCert, clientCert, clientKey string) (*http.Client, error) - if err != nil { - return &http.Client{}, err - } -- cliCrt, err := tls.LoadX509KeyPair(certPath+clientCert, certPath+clientKey) -+ cliCrt, err := tls.LoadX509KeyPair(getCertPath()+clientCert, getCertPath()+clientKey) - if err != nil { - return &http.Client{}, err - } -@@ -206,7 +206,7 @@ func certExist(certFile string) error { - if certFile == "" { - return fmt.Errorf("please provide the certificate") - } -- _, err := os.Stat(certPath + certFile) -+ _, err := os.Stat(getCertPath() + certFile) - if err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("certificate is not exist %s ", err) -diff --git a/cmd/agent/server/disk_image_test.go b/cmd/agent/server/disk_image_test.go -index 3c82113..71c5de7 100644 ---- a/cmd/agent/server/disk_image_test.go -+++ b/cmd/agent/server/disk_image_test.go -@@ -14,19 +14,35 @@ - package server - - import ( -- "crypto/tls" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/sha256" - "crypto/x509" -+ "crypto/x509/pkix" -+ "encoding/hex" -+ "encoding/pem" -+ "io" -+ "math/big" - "net/http" - "os" - "reflect" -+ "strings" -+ "syscall" - "testing" -+ "time" - - "github.com/agiledragon/gomonkey/v2" -- - pb "openeuler.org/KubeOS/cmd/agent/api" - ) - --func Testdownload(t *testing.T) { -+func Test_download(t *testing.T) { -+ tmpDir := t.TempDir() -+ tmpFileForDownload := tmpDir + "/tmpFileForDownload" -+ tmpFile, err := os.Create(tmpFileForDownload) -+ if err != nil { -+ t.Errorf("open file error: %v", err) -+ } -+ defer tmpFile.Close() - type args struct { - req *pb.UpdateRequest - } -@@ -36,14 +52,35 @@ func Testdownload(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: "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: "normal", -+ args: args{ -+ req: &pb.UpdateRequest{ -+ ImageUrl: "http://www.openeuler.org/zh/", -+ }, -+ }, -+ want: tmpFileForDownload, -+ wantErr: false, -+ }, - } -+ 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) -+ defer patchGetImageUrl.Reset() -+ patchOSCreate := gomonkey.ApplyFuncReturn(os.Create, tmpFile, nil) -+ defer patchOSCreate.Reset() - for _, tt := range tests { -- if tt.name == "normal" { -- os.Mkdir("/persist", os.ModePerm) -- } - t.Run(tt.name, func(t *testing.T) { - got, err := download(tt.args.req) - if (err != nil) != tt.wantErr { -@@ -54,47 +91,42 @@ func Testdownload(t *testing.T) { - t.Errorf("download() got = %v, want %v", got, tt.want) - } - }) -- if tt.name == "normal" { -- os.RemoveAll("/persist") -- } - } - } - --func TestcheckSumMatch(t *testing.T) { -+func Test_checkSumMatch(t *testing.T) { -+ tmpDir := t.TempDir() -+ tmpFileForCheckSum := tmpDir + "/tmpFileForCheckSum" -+ err := os.WriteFile(tmpFileForCheckSum, []byte("hello"), 0644) -+ if err != nil { -+ t.Errorf("open file error: %v", err) -+ } - type args struct { - filePath string - checkSum string - } -- ff, _ := os.Create("aa.txt") -- ff.Chmod(os.ModePerm) - tests := []struct { - name string - args args - wantErr bool - }{ -- {name: "error", args: args{filePath: "aaa", checkSum: "aaa"}, wantErr: true}, -- {name: "errordir", args: args{filePath: "/aaa", checkSum: "/aaa"}, wantErr: true}, -- {name: "errortxt", args: args{filePath: "aa.txt", checkSum: "aa.txt"}, wantErr: true}, -+ { -+ name: "normal", -+ args: args{filePath: tmpFileForCheckSum, checkSum: calculateChecksum("hello")}, -+ wantErr: false, -+ }, -+ {name: "error", args: args{filePath: tmpFileForCheckSum, checkSum: "aaa"}, wantErr: true}, - } - for _, tt := range tests { -- if tt.name == "errordir" { -- os.Mkdir("/aaa", os.ModePerm) -- } - t.Run(tt.name, func(t *testing.T) { - if err := checkSumMatch(tt.args.filePath, tt.args.checkSum); (err != nil) != tt.wantErr { - t.Errorf("checkSumMatch() error = %v, wantErr %v", err, tt.wantErr) - } - }) -- if tt.name == "errordir" { -- os.RemoveAll("/aaa") -- } - } -- defer os.Remove("aa.txt") -- defer ff.Close() -- - } - --func TestgetImageURL(t *testing.T) { -+func Test_getImageURL(t *testing.T) { - type args struct { - req *pb.UpdateRequest - } -@@ -105,23 +137,29 @@ func TestgetImageURL(t *testing.T) { - wantErr bool - }{ - {name: "httpNotSafe", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "http://www.openeuler.org/zh/", -+ ImageUrl: "http://www.openeuler.abc/zh/", - FlagSafe: false, - MTLS: false, - Certs: &pb.CertsInfo{}, - }}, want: &http.Response{}, wantErr: true}, -- {name: "mTLSError", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "http://www.openeuler.org/zh/", -+ {name: "httpSuccess", args: args{req: &pb.UpdateRequest{ -+ ImageUrl: "http://www.openeuler.abc/zh/", -+ FlagSafe: true, -+ MTLS: false, -+ Certs: &pb.CertsInfo{}, -+ }}, want: &http.Response{StatusCode: http.StatusOK}, wantErr: false}, -+ {name: "mTLSGetSuccess", args: args{req: &pb.UpdateRequest{ -+ ImageUrl: "https://www.openeuler.abc/zh/", - FlagSafe: true, - MTLS: true, - Certs: &pb.CertsInfo{}, -- }}, want: &http.Response{}, wantErr: true}, -- {name: "httpsError", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "https://www.openeuler.org/zh/", -+ }}, want: &http.Response{StatusCode: http.StatusOK}, wantErr: false}, -+ {name: "httpsGetSuccess", args: args{req: &pb.UpdateRequest{ -+ ImageUrl: "https://www.openeuler.abc/zh/", - FlagSafe: true, - MTLS: false, - Certs: &pb.CertsInfo{}, -- }}, want: &http.Response{}, wantErr: true}, -+ }}, want: &http.Response{StatusCode: http.StatusOK}, wantErr: false}, - } - patchLoadClientCerts := gomonkey.ApplyFunc(loadClientCerts, func(caCert, clientCert, clientKey string) (*http.Client, error) { - return &http.Client{}, nil -@@ -131,8 +169,20 @@ func TestgetImageURL(t *testing.T) { - return &http.Client{}, nil - }) - defer patchLoadCaCerts.Reset() -+ patchGet := gomonkey.ApplyFunc(http.Get, func(url string) (resp *http.Response, err error) { -+ return &http.Response{StatusCode: http.StatusOK}, nil -+ }) -+ defer patchGet.Reset() -+ patchClientGet := gomonkey.ApplyMethod(reflect.TypeOf(&http.Client{}), "Get", func(_ *http.Client, url string) (resp *http.Response, err error) { -+ return &http.Response{StatusCode: http.StatusOK}, nil -+ }) -+ defer patchClientGet.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { -+ if tt.name == "httpSuccess" { -+ patchGet := gomonkey.ApplyFuncReturn(http.Get, &http.Response{StatusCode: http.StatusOK}, nil) -+ defer patchGet.Reset() -+ } - got, err := getImageURL(tt.args.req) - if (err != nil) != tt.wantErr { - t.Errorf("getImageURL() error = %v, wantErr %v", err, tt.wantErr) -@@ -145,20 +195,28 @@ func TestgetImageURL(t *testing.T) { - } - } - --func TestloadCaCerts(t *testing.T) { -+func Test_loadCaCerts(t *testing.T) { -+ tmpDir := t.TempDir() -+ caPath := tmpDir + "/fake.crt" -+ createFakeCertKey(caPath, "") - type args struct { - caCert string - } - tests := []struct { - name string - args args -- want *http.Client - wantErr bool - }{ -- {name: "noCaCertError", args: args{caCert: "bb.txt"}, want: &http.Client{}, wantErr: true}, -+ { -+ name: "normal", -+ args: args{ -+ caCert: caPath, -+ }, -+ wantErr: false, -+ }, - } -- os.MkdirAll(certPath, 0644) -- defer os.RemoveAll(certPath) -+ patchGetCertPath := gomonkey.ApplyFuncReturn(getCertPath, "") -+ defer patchGetCertPath.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := loadCaCerts(tt.args.caCert) -@@ -166,48 +224,39 @@ func TestloadCaCerts(t *testing.T) { - t.Errorf("loadCaCerts() error = %v, wantErr %v", err, tt.wantErr) - return - } -- if !reflect.DeepEqual(got, tt.want) { -- t.Errorf("loadCaCerts() = %v, want %v", got, tt.want) -+ if got == nil { -+ t.Errorf("loadCaCerts() = %v", got) - } - }) - } - - } - --func TestloadClientCerts(t *testing.T) { -+func Test_loadClientCerts(t *testing.T) { -+ tmpDir := t.TempDir() -+ clientCertPath := tmpDir + "/fakeClientCert.crt" -+ clientKeyPath := tmpDir + "/fakeClientKey.crt" -+ createFakeCertKey(clientCertPath, clientKeyPath) - type args struct { - caCert string - clientCert string - clientKey string - } -- pool := &x509.CertPool{} - tests := []struct { - name string - args args -- want *http.Client - wantErr bool - }{ -- {name: "noCaCertError", args: args{" dd.txt", "bb.txt", "cc.txt"}, want: &http.Client{}, wantErr: true}, -- {name: "noClientCertError", args: args{"ca.crt", "bb.txt", "cc.txt"}, want: &http.Client{}, wantErr: true}, -- {name: "noClientKeyError", args: args{"ca.crt", "client.crt", "cc.txt"}, want: &http.Client{}, wantErr: true}, -- } -- os.MkdirAll(certPath, 0644) -- caFile, _ := os.Create(certPath + "ca.crt") -- clientCertFile, _ := os.Create(certPath + "client.crt") -- clientKeyFile, _ := os.Create(certPath + "client.key") -- -- patchNewCertPool := gomonkey.ApplyFunc(x509.NewCertPool, func() *x509.CertPool { -- return pool -- }) -- defer patchNewCertPool.Reset() -- patchAppendCertsFromPEM := gomonkey.ApplyMethod(reflect.TypeOf(pool), "AppendCertsFromPEM", func(_ *x509.CertPool, _ []byte) (ok bool) { -- return true -- }) -- defer patchAppendCertsFromPEM.Reset() -- patchLoadX509KeyPair := gomonkey.ApplyFunc(tls.LoadX509KeyPair, func(certFile string, keyFile string) (tls.Certificate, error) { -- return tls.Certificate{}, nil -- }) -- defer patchLoadX509KeyPair.Reset() -+ { -+ name: "normal", -+ args: args{ -+ caCert: clientCertPath, clientCert: clientCertPath, clientKey: clientKeyPath, -+ }, -+ wantErr: false, -+ }, -+ } -+ patchGetCertPath := gomonkey.ApplyFuncReturn(getCertPath, "") -+ defer patchGetCertPath.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := loadClientCerts(tt.args.caCert, tt.args.clientCert, tt.args.clientKey) -@@ -215,19 +264,14 @@ func TestloadClientCerts(t *testing.T) { - t.Errorf("loadClientCerts() error = %v, wantErr %v", err, tt.wantErr) - return - } -- if !reflect.DeepEqual(got, tt.want) { -- t.Errorf("loadClientCerts() got = %v, want %v", got, tt.want) -+ if got == nil { -+ t.Errorf("loadClientCerts() got = %v", got) - } - }) - } -- caFile.Close() -- clientCertFile.Close() -- clientKeyFile.Close() -- defer os.RemoveAll("/etc/KubeOS") -- - } - --func TestcertExist(t *testing.T) { -+func Test_certExist(t *testing.T) { - type args struct { - certFile string - } -@@ -238,10 +282,7 @@ func TestcertExist(t *testing.T) { - }{ - {name: "fileEmpty", args: args{certFile: ""}, wantErr: true}, - {name: "fileNotExist", args: args{certFile: "bb.txt"}, wantErr: true}, -- {name: "normal", args: args{certFile: "aa.txt"}, wantErr: false}, - } -- os.MkdirAll(certPath, 0644) -- ff, _ := os.Create(certPath + "aa.txt") - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := certExist(tt.args.certFile); (err != nil) != tt.wantErr { -@@ -249,6 +290,71 @@ func TestcertExist(t *testing.T) { - } - }) - } -- ff.Close() - defer os.RemoveAll("/etc/KubeOS/") - } -+ -+func createFakeCertKey(certPath, keyPath string) { -+ privateKey, _ := rsa.GenerateKey(rand.Reader, 2048) -+ template := x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ Subject: pkix.Name{ -+ CommonName: "Fake Client Certificate", -+ }, -+ NotBefore: time.Now(), -+ NotAfter: time.Now().AddDate(1, 0, 0), -+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, -+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, -+ BasicConstraintsValid: true, -+ } -+ certBytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) -+ certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes}) -+ keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) -+ os.WriteFile(certPath, certPEM, 0644) -+ if keyPath != "" { -+ os.WriteFile(keyPath, keyPEM, 0644) -+ } -+} -+ -+func calculateChecksum(data string) string { -+ hash := sha256.New() -+ hash.Write([]byte(data)) -+ return hex.EncodeToString(hash.Sum(nil)) -+} -+ -+func Test_diskHandler_getRootfsArchive(t *testing.T) { -+ type args struct { -+ req *pb.UpdateRequest -+ neededPath preparePath -+ } -+ tests := []struct { -+ name string -+ d diskHandler -+ args args -+ want string -+ wantErr bool -+ }{ -+ { -+ name: "normal", d: diskHandler{}, -+ args: args{req: &pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/"}, neededPath: preparePath{}}, -+ want: "/persist/update.img", -+ wantErr: false, -+ }, -+ } -+ patchDownload := gomonkey.ApplyFuncReturn(download, "/persist/update.img", nil) -+ defer patchDownload.Reset() -+ patchCheckSumMatch := gomonkey.ApplyFuncReturn(checkSumMatch, nil) -+ defer patchCheckSumMatch.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ d := diskHandler{} -+ got, err := d.getRootfsArchive(tt.args.req, tt.args.neededPath) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("diskHandler.getRootfsArchive() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("diskHandler.getRootfsArchive() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -diff --git a/cmd/agent/server/server.go b/cmd/agent/server/server.go -index b41ebc4..8ac6ffd 100644 ---- a/cmd/agent/server/server.go -+++ b/cmd/agent/server/server.go -@@ -171,3 +171,7 @@ func (s *Server) reboot() error { - } - return syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART) - } -+ -+func getCertPath() string { -+ return certPath -+} -diff --git a/cmd/agent/server/server_test.go b/cmd/agent/server/server_test.go -index 0aac36a..74e2ead 100644 ---- a/cmd/agent/server/server_test.go -+++ b/cmd/agent/server/server_test.go -@@ -89,7 +89,21 @@ func TestServerUpdate(t *testing.T) { - {name: "error", fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, - args: args{in0: context.Background(), req: &pb.UpdateRequest{Version: "test", Certs: &pb.CertsInfo{}}}, - want: &pb.UpdateResponse{}, wantErr: true}, -+ {name: "success", fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, -+ args: args{in0: context.Background(), req: &pb.UpdateRequest{Version: "test", Certs: &pb.CertsInfo{}, ImageType: "containerd"}}, -+ want: &pb.UpdateResponse{}, wantErr: false}, - } -+ patchRootfsDisks := gomonkey.ApplyFuncReturn(getRootfsDisks, "/dev/sda2", "/dev/sda3", nil) -+ defer patchRootfsDisks.Reset() -+ // assume now is partition A, want to swiching to partition B -+ patchGetNextPartition := gomonkey.ApplyFuncReturn(getNextPart, "/dev/sda3", "B", nil) -+ defer patchGetNextPartition.Reset() -+ patchDownloadImage := gomonkey.ApplyPrivateMethod(conImageHandler{}, "downloadImage", func(_ conImageHandler, req *pb.UpdateRequest) (string, error) { -+ return "", nil -+ }) -+ defer patchDownloadImage.Reset() -+ patchInstall := gomonkey.ApplyFuncReturn(install, nil) -+ defer patchInstall.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &Server{ -@@ -129,11 +143,26 @@ func TestServerRollback(t *testing.T) { - {name: "error", fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, - args: args{in0: context.Background(), req: &pb.RollbackRequest{}}, - want: &pb.RollbackResponse{}, wantErr: true}, -+ {name: "success", fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, -+ args: args{in0: context.Background(), req: &pb.RollbackRequest{}}, -+ want: &pb.RollbackResponse{}, wantErr: false}, - } -- patchGetNextPart := gomonkey.ApplyFunc(getNextPart, func(partA string, partB string) (string, string, error) { -- return "", "", fmt.Errorf("rollbak test error") -+ patchRootfsDisks := gomonkey.ApplyFuncReturn(getRootfsDisks, "/dev/sda2", "/dev/sda3", nil) -+ defer patchRootfsDisks.Reset() -+ // assume now is partition A, want to swiching to partition B -+ patchGetNextPartition := gomonkey.ApplyFuncSeq(getNextPart, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{"", "", fmt.Errorf("rollbak test error")}}, -+ {Values: gomonkey.Params{"/dev/sda3", "B", nil}}, - }) -- defer patchGetNextPart.Reset() -+ defer patchGetNextPartition.Reset() -+ patchDownloadImage := gomonkey.ApplyPrivateMethod(conImageHandler{}, "downloadImage", func(_ conImageHandler, req *pb.UpdateRequest) (string, error) { -+ return "", nil -+ }) -+ defer patchDownloadImage.Reset() -+ patchInstall := gomonkey.ApplyFuncReturn(install, nil) -+ defer patchInstall.Reset() -+ patchRunCommand := gomonkey.ApplyFuncReturn(runCommand, nil) -+ defer patchRunCommand.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &Server{ -@@ -179,9 +208,9 @@ func TestServerupdate(t *testing.T) { - }}, - wantErr: true}, - {name: "errordocker", args: args{&pb.UpdateRequest{ -- DockerImage: "", -- ImageType: "docker", -- Certs: &pb.CertsInfo{}, -+ ContainerImage: "", -+ ImageType: "docker", -+ Certs: &pb.CertsInfo{}, - }}, - wantErr: true}, - } -@@ -264,3 +293,48 @@ func TestServerreboot(t *testing.T) { - }) - } - } -+ -+func TestServer_Configure(t *testing.T) { -+ type fields struct { -+ UnimplementedOSServer pb.UnimplementedOSServer -+ mutex Lock -+ disableReboot bool -+ } -+ type args struct { -+ in0 context.Context -+ req *pb.ConfigureRequest -+ } -+ tests := []struct { -+ name string -+ fields fields -+ args args -+ want *pb.ConfigureResponse -+ wantErr bool -+ }{ -+ // TODO: Add test cases. -+ { -+ name: "nil", -+ fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, -+ args: args{in0: context.Background(), req: &pb.ConfigureRequest{}}, -+ want: &pb.ConfigureResponse{}, -+ wantErr: false, -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ s := &Server{ -+ UnimplementedOSServer: tt.fields.UnimplementedOSServer, -+ mutex: tt.fields.mutex, -+ disableReboot: tt.fields.disableReboot, -+ } -+ got, err := s.Configure(tt.args.in0, tt.args.req) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("Server.Configure() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if !reflect.DeepEqual(got, tt.want) { -+ t.Errorf("Server.Configure() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -diff --git a/cmd/agent/server/utils_test.go b/cmd/agent/server/utils_test.go -index 8e7fd90..89b2c3b 100644 ---- a/cmd/agent/server/utils_test.go -+++ b/cmd/agent/server/utils_test.go -@@ -14,13 +14,17 @@ - package server - - import ( -+ "archive/tar" - "os" - "os/exec" -- "strings" -+ "reflect" - "testing" -+ "time" -+ -+ "github.com/agiledragon/gomonkey/v2" - ) - --func TestrunCommand(t *testing.T) { -+func Test_runCommand(t *testing.T) { - type args struct { - name string - args []string -@@ -41,23 +45,21 @@ func TestrunCommand(t *testing.T) { - } - } - --func Testinstall(t *testing.T) { -+func Test_install(t *testing.T) { - type args struct { - imagePath string - side string - next string - } -- out, _ := exec.Command("bash", "-c", "df -h | grep '/$' | awk '{print $1}'").CombinedOutput() -- mountPart := strings.TrimSpace(string(out)) - tests := []struct { - name string - args args - wantErr bool - }{ -- {name: "normal", args: args{imagePath: "aa.txt", side: mountPart, next: ""}, wantErr: false}, -+ {name: "normal", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false}, - } -- ff, _ := os.Create("aa.txt") -- ff.Chmod(os.ModePerm) -+ patchRunCommand := gomonkey.ApplyFuncReturn(runCommand, nil) -+ defer patchRunCommand.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 { -@@ -65,17 +67,13 @@ func Testinstall(t *testing.T) { - } - }) - } -- ff.Close() -- defer os.Remove("aa.txt") - } - --func TestgetNextPart(t *testing.T) { -+func Test_getNextPart(t *testing.T) { - type args struct { - partA string - partB string - } -- out, _ := exec.Command("bash", "-c", "df -h | grep '/$' | awk '{print $1}'").CombinedOutput() -- mountPart := strings.TrimSpace(string(out)) - tests := []struct { - name string - args args -@@ -83,8 +81,14 @@ func TestgetNextPart(t *testing.T) { - want1 string - wantErr bool - }{ -- {name: "normal", args: args{partA: mountPart, partB: "testB"}, want: "testB", want1: "B", wantErr: false}, -+ {name: "switch to sda3", args: args{partA: "/dev/sda2", partB: "/dev/sda3"}, want: "/dev/sda3", want1: "B", wantErr: false}, -+ {name: "switch to sda2", args: args{partA: "/dev/sda2", partB: "/dev/sda3"}, want: "/dev/sda2", want1: "A", wantErr: false}, - } -+ patchExecCommand := gomonkey.ApplyMethodSeq(&exec.Cmd{}, "CombinedOutput", []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{[]byte("/"), nil}}, -+ {Values: gomonkey.Params{[]byte(""), nil}}, -+ }) -+ defer patchExecCommand.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, got1, err := getNextPart(tt.args.partA, tt.args.partB) -@@ -101,3 +105,117 @@ func TestgetNextPart(t *testing.T) { - }) - } - } -+ -+func Test_prepareEnv(t *testing.T) { -+ mountPath := "/persist/KubeOS-Update/kubeos-update" -+ if err := os.MkdirAll(mountPath, 0644); err != nil { -+ t.Fatalf("mkdir err %v", err) -+ } -+ defer os.RemoveAll("/persist") -+ tests := []struct { -+ name string -+ want preparePath -+ wantErr bool -+ }{ -+ { -+ name: "success", -+ want: preparePath{ -+ updatePath: "/persist/KubeOS-Update", -+ mountPath: "/persist/KubeOS-Update/kubeos-update", -+ tarPath: "/persist/KubeOS-Update/os.tar", -+ imagePath: "/persist/update.img", -+ rootfsFile: "os.tar", -+ }, -+ wantErr: false, -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := prepareEnv() -+ if (err != nil) != tt.wantErr { -+ t.Errorf("prepareEnv() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if !reflect.DeepEqual(got, tt.want) { -+ t.Errorf("prepareEnv() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func Test_createOSImage(t *testing.T) { -+ mountPath := "/persist/KubeOS-Update/kubeos-update" -+ if err := os.MkdirAll(mountPath, 0644); err != nil { -+ t.Fatalf("mkdir err %v", err) -+ } -+ defer os.RemoveAll("/persist") -+ tarPath := "/persist/KubeOS-Update/os.tar" -+ path, err := createTmpTarFile(tarPath) -+ if path != tarPath && err != nil { -+ t.Fatalf("create temp zip file err %v", err) -+ } -+ type args struct { -+ neededPath preparePath -+ } -+ tests := []struct { -+ name string -+ args args -+ want string -+ wantErr bool -+ }{ -+ { -+ name: "normal", -+ args: args{ -+ neededPath: preparePath{ -+ updatePath: "/persist/KubeOS-Update", -+ mountPath: "/persist/KubeOS-Update/kubeos-update", -+ tarPath: "/persist/KubeOS-Update/os.tar", -+ imagePath: "/persist/update.img", -+ }, -+ }, -+ want: "/persist/update.img", -+ wantErr: false, -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := createOSImage(tt.args.neededPath) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("createOSImage() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("createOSImage() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func createTmpTarFile(tarPath string) (string, error) { -+ tempFile, err := os.Create(tarPath) -+ if err != nil { -+ return "", err -+ } -+ defer tempFile.Close() -+ -+ tarWriter := tar.NewWriter(tempFile) -+ fakeData := []byte("This is a fake file") -+ fakeFile := "fakefile.txt" -+ header := &tar.Header{ -+ Name: fakeFile, -+ Size: int64(len(fakeData)), -+ Mode: 0644, -+ ModTime: time.Now(), -+ } -+ -+ if err = tarWriter.WriteHeader(header); err != nil { -+ return "", err -+ } -+ if _, err := tarWriter.Write(fakeData); err != nil { -+ return "", err -+ } -+ if err := tarWriter.Flush(); err != nil { -+ return "", err -+ } -+ return tempFile.Name(), nil -+} -diff --git a/cmd/operator/controllers/os_controller_test.go b/cmd/operator/controllers/os_controller_test.go -index a391005..98de6d0 100644 ---- a/cmd/operator/controllers/os_controller_test.go -+++ b/cmd/operator/controllers/os_controller_test.go -@@ -14,16 +14,22 @@ package controllers - - import ( - "context" -+ "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" -@@ -506,3 +512,64 @@ var _ = Describe("OsController", func() { - }) - }) - }) -+ -+func TestOSReconciler_DeleteOSInstance(t *testing.T) { -+ type fields struct { -+ Scheme *runtime.Scheme -+ Client client.Client -+ } -+ kClient, _ := client.New(cfg, client.Options{Scheme: scheme.Scheme}) -+ type args struct { -+ e event.DeleteEvent -+ q workqueue.RateLimitingInterface -+ } -+ tests := []struct { -+ name string -+ fields fields -+ args args -+ }{ -+ { -+ name: "delete osinstance", -+ fields: fields{ -+ Scheme: nil, -+ Client: kClient, -+ }, -+ args: args{ -+ e: event.DeleteEvent{ -+ Object: &upgradev1.OSInstance{ -+ ObjectMeta: metav1.ObjectMeta{ -+ Name: "test-node1", -+ Namespace: "test", -+ }, -+ }, -+ }, -+ q: nil, -+ }, -+ }, -+ } -+ 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, -+ } -+ 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() -+} -diff --git a/cmd/operator/controllers/suite_test.go b/cmd/operator/controllers/suite_test.go -index 889789e..aa6deea 100644 ---- a/cmd/operator/controllers/suite_test.go -+++ b/cmd/operator/controllers/suite_test.go -@@ -51,7 +51,7 @@ var _ = BeforeSuite(func() { - - By("bootstrapping test environment") - testEnv = &envtest.Environment{ -- CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd")}, -+ CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "docs", "example", "config", "crd")}, - ErrorIfCRDPathMissing: true, - } - -diff --git a/cmd/proxy/controllers/os_controller.go b/cmd/proxy/controllers/os_controller.go -index b0b17e7..09d61c0 100644 ---- a/cmd/proxy/controllers/os_controller.go -+++ b/cmd/proxy/controllers/os_controller.go -@@ -87,6 +87,9 @@ func (r *OSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re - sameOSVersion := checkVersion(osCr.Spec.OSVersion, node.Status.NodeInfo.OSImage) - if sameOSVersion { - configOps, err := checkConfigVersion(osCr, osInstance, values.SysConfigName) -+ if err != nil { -+ return values.RequeueNow, err -+ } - if configOps == values.Reassign { - if err = r.refreshNode(ctx, &node, osInstance, osCr.Spec.SysConfigs.Version, values.SysConfigName); err != nil { - return values.RequeueNow, err -@@ -113,6 +116,9 @@ func (r *OSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re - return values.RequeueNow, err - } - configOps, err := checkConfigVersion(osCr, osInstance, values.UpgradeConfigName) -+ if err != nil { -+ return values.RequeueNow, err -+ } - if configOps == values.Reassign { - if err = r.refreshNode(ctx, &node, osInstance, osCr.Spec.UpgradeConfigs.Version, - values.UpgradeConfigName); err != nil { -diff --git a/cmd/proxy/controllers/os_controller_test.go b/cmd/proxy/controllers/os_controller_test.go -index e6cd5b7..d63f176 100644 ---- a/cmd/proxy/controllers/os_controller_test.go -+++ b/cmd/proxy/controllers/os_controller_test.go -@@ -67,6 +67,148 @@ var _ = Describe("OsController", func() { - testNamespace = existingNamespace.Name - }) - -+ Context("When we want to rollback", func() { -+ It("Should be able to rollback to previous version", 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.NodeStatusUpgrade.String(), -+ SysConfigs: upgradev1.SysConfigs{}, -+ UpgradeConfigs: upgradev1.SysConfigs{}, -+ }, -+ 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.Spec.NodeStatus).Should(Equal(values.NodeStatusUpgrade.String())) -+ -+ // stub r.Connection.RollbackSpec() -+ patchRollback := gomonkey.ApplyMethodReturn(reconciler.Connection, "RollbackSpec", nil) -+ defer patchRollback.Reset() -+ patchConfigure := gomonkey.ApplyMethodReturn(reconciler.Connection, "ConfigureSpec", nil) -+ defer patchConfigure.Reset() -+ -+ 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: "rollback", -+ MaxUnavailable: 3, -+ OSVersion: "KubeOS v1", -+ FlagSafe: true, -+ MTLS: false, -+ EvictPodForce: true, -+ SysConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, -+ UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, -+ }, -+ } -+ 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 v1")) -+ Expect(createdOS.Spec.OpsType).Should(Equal("rollback")) -+ -+ By("Changing the nodeinfo OSImage to previous version, pretending the rollback success") -+ 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()) -+ existingNode.Status.NodeInfo.OSImage = "KubeOS v1" -+ Expect(k8sClient.Status().Update(ctx, existingNode)).Should(Succeed()) -+ -+ By("Changing the OS Spec config to trigger reconcile") -+ createdOS = &upgradev1.OS{} -+ Eventually(func() bool { -+ err := k8sClient.Get(ctx, osCRLookupKey, createdOS) -+ return err == nil -+ }, timeout, interval).Should(BeTrue()) -+ createdOS.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -+ Expect(k8sClient.Update(ctx, createdOS)).Should(Succeed()) -+ -+ time.Sleep(2 * time.Second) // sleep a while to make sure Reconcile finished -+ createdOSIns = &upgradev1.OSInstance{} -+ Eventually(func() bool { -+ err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns) -+ return err == nil -+ }, timeout, interval).Should(BeTrue()) -+ // NodeStatus changes to idle then operator can reassign configs to this node -+ Expect(createdOSIns.Spec.NodeStatus).Should(Equal(values.NodeStatusIdle.String())) -+ 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)) -+ }) -+ }) -+ - Context("When we have a sysconfig whose version is different from current OSInstance config version", func() { - It("Should configure the node", func() { - ctx := context.Background() -@@ -482,6 +624,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(), -@@ -634,6 +779,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(), -@@ -798,6 +946,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(), -@@ -915,7 +1066,7 @@ var _ = Describe("OsController", func() { - Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v2")) - - By("Checking the OSInstance status config version failed to be updated") -- 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 { -diff --git a/cmd/proxy/controllers/suite_test.go b/cmd/proxy/controllers/suite_test.go -index a52c18f..00eebbf 100644 ---- a/cmd/proxy/controllers/suite_test.go -+++ b/cmd/proxy/controllers/suite_test.go -@@ -53,7 +53,7 @@ var _ = BeforeSuite(func() { - - By("bootstrapping test environment") - testEnv = &envtest.Environment{ -- CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd")}, -+ CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "docs", "example", "config", "crd")}, - ErrorIfCRDPathMissing: true, - } - --- -2.39.0 - diff --git a/0005-KubeOS-fix-validate-image-name-bug.patch b/0005-KubeOS-fix-validate-image-name-bug.patch deleted file mode 100644 index bc274c99fa186e0a3bc131ee30d0fb1842a7bdb9..0000000000000000000000000000000000000000 --- a/0005-KubeOS-fix-validate-image-name-bug.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 5c5922a922f225a9ebc5f99a5008ddcf182b7da6 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0006-KubeOS-fix-a-bug-that-failed-to-parse-key-with.patch b/0006-KubeOS-fix-a-bug-that-failed-to-parse-key-with.patch deleted file mode 100644 index 87bda7b06b848463e49abcc1f6e44900c4ec876c..0000000000000000000000000000000000000000 --- a/0006-KubeOS-fix-a-bug-that-failed-to-parse-key-with.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 911fbd04ba55a2560e8da8595ff379a742e5fa30 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0007-KubeOS-add-warning-log-during-config.patch b/0007-KubeOS-add-warning-log-during-config.patch deleted file mode 100644 index 2d913b4cab4e1a97427bf618136def8075ee12f3..0000000000000000000000000000000000000000 --- a/0007-KubeOS-add-warning-log-during-config.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 59473394cca1e227ec579236d71ec54deb79b068 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0008-KubeOS-modify-log-level-and-content.patch b/0008-KubeOS-modify-log-level-and-content.patch deleted file mode 100644 index 94f650f41f33e0bd3e7a023b9c6742152c442926..0000000000000000000000000000000000000000 --- a/0008-KubeOS-modify-log-level-and-content.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 38ed69d2ad089d124ee72a4431fcc96ef3d9cf28 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Thu, 10 Aug 2023 21:10:29 +0800 -Subject: [PATCH 08/17] KubeOS: modify log level and content - -Signed-off-by: Yuhang Wei ---- - 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 - diff --git a/0009-KubeOS-fix-updating-key-to-kv.patch b/0009-KubeOS-fix-updating-key-to-kv.patch deleted file mode 100644 index a7e9c66bd7c5a64d8c204707fc629959daffa7aa..0000000000000000000000000000000000000000 --- a/0009-KubeOS-fix-updating-key-to-kv.patch +++ /dev/null @@ -1,151 +0,0 @@ -From dcfb6e0397e649631ec42dcf51c3e98e914f8269 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0010-KubeOS-fix-proxy-requeue-bug.patch b/0010-KubeOS-fix-proxy-requeue-bug.patch deleted file mode 100644 index 751dba8935d07090e61a3abd91e94cdae5e948ab..0000000000000000000000000000000000000000 --- a/0010-KubeOS-fix-proxy-requeue-bug.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 657e3e5c9bcc0fac3a079f51842d59a9e6b5e163 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0011-KubeOS-fix-operator-bug-of-missing-deep-copy.patch b/0011-KubeOS-fix-operator-bug-of-missing-deep-copy.patch deleted file mode 100644 index 0e1598758dd6915b03bcba493eaadeaa3b8c2ac3..0000000000000000000000000000000000000000 --- a/0011-KubeOS-fix-operator-bug-of-missing-deep-copy.patch +++ /dev/null @@ -1,665 +0,0 @@ -From a87666e17d729feb67f987fa7038ef83b3fa2e1b Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0012-KubeOS-add-unit-test.patch b/0012-KubeOS-add-unit-test.patch deleted file mode 100644 index 9852ccf161adcb6f4632530d5d53db5fbe32d3ee..0000000000000000000000000000000000000000 --- a/0012-KubeOS-add-unit-test.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 9bd13d2a1b8b7282d7247caf9ba54f11bb297cd5 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0013-KubeOS-fix-clean-space-problems.patch b/0013-KubeOS-fix-clean-space-problems.patch deleted file mode 100644 index 57a7428557475216ffb528716f50d9479da9d55f..0000000000000000000000000000000000000000 --- a/0013-KubeOS-fix-clean-space-problems.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 1bc41e7e58e99e23cd8be522cc1c2d30090975d2 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0014-KubeOS-update-version.patch b/0014-KubeOS-update-version.patch deleted file mode 100644 index 54eab5187b5c1405b6692b3605eac4ed60f0ac49..0000000000000000000000000000000000000000 --- a/0014-KubeOS-update-version.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 9f0f03251a1bd0449f4e7e7ab5699e4771fbaa56 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Fri, 18 Aug 2023 17:19:53 +0800 -Subject: [PATCH 15/17] KubeOS: update version - -Signed-off-by: Yuhang Wei ---- - 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 - diff --git a/0015-KubeOS-add-line-breaks.patch b/0015-KubeOS-add-line-breaks.patch deleted file mode 100644 index 109b96b9e1bf4744b41ddac1d96e4ef98e82df63..0000000000000000000000000000000000000000 --- a/0015-KubeOS-add-line-breaks.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 235a13b34e65b8d4ec4bde59e36247445b0778e8 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Tue, 15 Aug 2023 16:24:25 +0800 -Subject: [PATCH] KubeOS: add line breaks - -Signed-off-by: Yuhang Wei ---- - 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 - diff --git a/0016-KubeOS-modify-code-for-clean-code.patch b/0016-KubeOS-modify-code-for-clean-code.patch deleted file mode 100644 index dd3d0e3776d46d5898a39ec46d3a90574f040241..0000000000000000000000000000000000000000 --- a/0016-KubeOS-modify-code-for-clean-code.patch +++ /dev/null @@ -1,46 +0,0 @@ -From a01e5ebfd9c314b840eb3a652cda71e33954a403 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Wed, 16 Aug 2023 22:41:44 +0800 -Subject: [PATCH 16/17] KubeOS: modify code for clean code - -Signed-off-by: Yuhang Wei ---- - 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 - diff --git a/0017-KubeOS-fix-the-issue-that-osinstance-is-not-updated-.patch b/0017-KubeOS-fix-the-issue-that-osinstance-is-not-updated-.patch deleted file mode 100644 index 81e825f60f7603377da911dcf07879c755979160..0000000000000000000000000000000000000000 --- a/0017-KubeOS-fix-the-issue-that-osinstance-is-not-updated-.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 0c0f3c7ef5749b8806511d9e3312f6cacd4cca04 Mon Sep 17 00:00:00 2001 -From: liyuanr -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 ---- - 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 - diff --git a/0018-KubeOS-update-config-log-contents.patch b/0018-KubeOS-update-config-log-contents.patch deleted file mode 100644 index 5271458779504f10f53966df5df879380977ff98..0000000000000000000000000000000000000000 --- a/0018-KubeOS-update-config-log-contents.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 662f68aa131c09154bb91085e4657beaee00d1d6 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Mon, 21 Aug 2023 09:58:45 +0800 -Subject: [PATCH 1/5] KubeOS: update config log contents - -Signed-off-by: Yuhang Wei ---- - 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 - diff --git a/0019-KubeOS-add-unit-tests.patch b/0019-KubeOS-add-unit-tests.patch deleted file mode 100644 index 18f7bb6fe194e431d645dd3280f7de1a0ed7afad..0000000000000000000000000000000000000000 --- a/0019-KubeOS-add-unit-tests.patch +++ /dev/null @@ -1,1069 +0,0 @@ -From f35fee982d0afefef4643993dc0f64c7aa243a22 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Wed, 16 Aug 2023 14:27:36 +0800 -Subject: [PATCH 2/5] KubeOS:add unit tests - -modify proxy ut to avoid panic bug -add config, disk_image, operator, proxy, server and utils unit tests - -Signed-off-by: Yuhang Wei ---- - cmd/agent/server/config_test.go | 41 ++- - cmd/agent/server/disk_image_test.go | 56 +++- - cmd/agent/server/server_test.go | 1 - - cmd/agent/server/utils_test.go | 112 +++++++ - .../controllers/os_controller_test.go | 232 +++++++++++++- - cmd/proxy/controllers/os_controller_test.go | 295 +++++++++++++++--- - 6 files changed, 685 insertions(+), 52 deletions(-) - -diff --git a/cmd/agent/server/config_test.go b/cmd/agent/server/config_test.go -index 08daf99..29bb926 100644 ---- a/cmd/agent/server/config_test.go -+++ b/cmd/agent/server/config_test.go -@@ -75,6 +75,16 @@ func TestKernelSysctl_SetConfig(t *testing.T) { - }, - }}, - }, -+ { -+ name: "nil key", -+ k: KernelSysctl{}, -+ args: args{config: &agent.SysConfig{ -+ Contents: map[string]*agent.KeyInfo{ -+ "": {Value: "1"}, -+ }, -+ }}, -+ wantErr: true, -+ }, - } - tmpDir := t.TempDir() - patchGetProcPath := gomonkey.ApplyFuncReturn(getDefaultProcPath, tmpDir+"/") -@@ -320,8 +330,7 @@ menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestri - defer patchGetConfigPartition.Reset() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { -- g := GrubCmdline{} -- if err := g.SetConfig(tt.args.config); (err != nil) != tt.wantErr { -+ if err := tt.g.SetConfig(tt.args.config); (err != nil) != tt.wantErr { - t.Errorf("GrubCmdline.SetConfig() error = %v, wantErr %v", err, tt.wantErr) - } - contents, err := os.ReadFile(grubCfgPath) -@@ -513,3 +522,31 @@ func Test_ConfigFactoryTemplate(t *testing.T) { - }) - } - } -+ -+func Test_convertNewConfigsToString(t *testing.T) { -+ type args struct { -+ newConfigs []string -+ } -+ tests := []struct { -+ name string -+ args args -+ want string -+ wantErr bool -+ }{ -+ {name: "error", args: args{newConfigs: []string{"a"}}, want: "", wantErr: true}, -+ } -+ patchFprintf := gomonkey.ApplyFuncReturn(fmt.Fprintf, 0, fmt.Errorf("error")) -+ defer patchFprintf.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := convertNewConfigsToString(tt.args.newConfigs) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("convertNewConfigsToString() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("convertNewConfigsToString() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -diff --git a/cmd/agent/server/disk_image_test.go b/cmd/agent/server/disk_image_test.go -index 265b323..f970bd7 100644 ---- a/cmd/agent/server/disk_image_test.go -+++ b/cmd/agent/server/disk_image_test.go -@@ -23,6 +23,7 @@ import ( - "encoding/pem" - "fmt" - "io" -+ "io/fs" - "math/big" - "net/http" - "os" -@@ -159,6 +160,7 @@ func Test_checkSumMatch(t *testing.T) { - wantErr: false, - }, - {name: "error", args: args{filePath: tmpFileForCheckSum, checkSum: "aaa"}, wantErr: true}, -+ {name: "unfound error", args: args{filePath: "", checkSum: "aaa"}, wantErr: true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { -@@ -271,6 +273,7 @@ func Test_loadCaCerts(t *testing.T) { - }, - wantErr: false, - }, -+ {name: "no cert", args: args{caCert: ""}, wantErr: true}, - } - patchGetCertPath := gomonkey.ApplyFuncReturn(getCertPath, "") - defer patchGetCertPath.Reset() -@@ -339,12 +342,22 @@ func Test_certExist(t *testing.T) { - }{ - {name: "fileEmpty", args: args{certFile: ""}, wantErr: true}, - {name: "fileNotExist", args: args{certFile: "bb.txt"}, wantErr: true}, -+ {name: "unknow error", args: args{certFile: "cc.txt"}, wantErr: true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { -+ var patchStat *gomonkey.Patches -+ if tt.name == "unknow error" { -+ patchStat = gomonkey.ApplyFunc(os.Stat, func(name string) (fs.FileInfo, error) { -+ return fs.FileInfo(nil), fmt.Errorf("error") -+ }) -+ } - if err := certExist(tt.args.certFile); (err != nil) != tt.wantErr { - t.Errorf("certExist() error = %v, wantErr %v", err, tt.wantErr) - } -+ if tt.name == "unknow error" { -+ patchStat.Reset() -+ } - }) - } - defer os.RemoveAll("/etc/KubeOS/") -@@ -396,8 +409,17 @@ func Test_diskHandler_getRootfsArchive(t *testing.T) { - want: "/persist/update.img", - wantErr: false, - }, -+ { -+ name: "error", d: diskHandler{}, -+ args: args{req: &pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/"}, neededPath: preparePath{}}, -+ want: "", -+ wantErr: true, -+ }, - } -- patchDownload := gomonkey.ApplyFuncReturn(download, "/persist/update.img", nil) -+ patchDownload := gomonkey.ApplyFuncSeq(download, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{"/persist/update.img", nil}}, -+ {Values: gomonkey.Params{"", fmt.Errorf("error")}}, -+ }) - defer patchDownload.Reset() - patchCheckSumMatch := gomonkey.ApplyFuncReturn(checkSumMatch, nil) - defer patchCheckSumMatch.Reset() -@@ -415,3 +437,35 @@ func Test_diskHandler_getRootfsArchive(t *testing.T) { - }) - } - } -+ -+func Test_diskHandler_downloadImage(t *testing.T) { -+ type args struct { -+ req *pb.UpdateRequest -+ } -+ tests := []struct { -+ name string -+ d diskHandler -+ args args -+ want string -+ wantErr bool -+ }{ -+ {name: "normal", d: diskHandler{}, args: args{req: &pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/"}}, want: "/persist/update.img", wantErr: false}, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ d := diskHandler{} -+ patchGetRootfsArchive := gomonkey.ApplyPrivateMethod(reflect.TypeOf(d), "getRootfsArchive", func(_ *diskHandler, _ *pb.UpdateRequest, _ preparePath) (string, error) { -+ return "/persist/update.img", nil -+ }) -+ got, err := d.downloadImage(tt.args.req) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("diskHandler.downloadImage() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("diskHandler.downloadImage() = %v, want %v", got, tt.want) -+ } -+ patchGetRootfsArchive.Reset() -+ }) -+ } -+} -diff --git a/cmd/agent/server/server_test.go b/cmd/agent/server/server_test.go -index 74e2ead..15b6f5e 100644 ---- a/cmd/agent/server/server_test.go -+++ b/cmd/agent/server/server_test.go -@@ -311,7 +311,6 @@ func TestServer_Configure(t *testing.T) { - want *pb.ConfigureResponse - wantErr bool - }{ -- // TODO: Add test cases. - { - name: "nil", - fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, -diff --git a/cmd/agent/server/utils_test.go b/cmd/agent/server/utils_test.go -index 0796bce..da53c0e 100644 ---- a/cmd/agent/server/utils_test.go -+++ b/cmd/agent/server/utils_test.go -@@ -15,6 +15,7 @@ package server - - import ( - "archive/tar" -+ "fmt" - "os" - "os/exec" - "reflect" -@@ -58,12 +59,14 @@ func Test_install(t *testing.T) { - }{ - {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}, -+ {name: "get boot mode error", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: true}, - } - patchRunCommand := gomonkey.ApplyFuncReturn(runCommand, nil) - defer patchRunCommand.Reset() - patchGetBootMode := gomonkey.ApplyFuncSeq(getBootMode, []gomonkey.OutputCell{ - {Values: gomonkey.Params{"uefi", nil}}, - {Values: gomonkey.Params{"legacy", nil}}, -+ {Values: gomonkey.Params{"", fmt.Errorf("error")}}, - }) - defer patchGetBootMode.Reset() - for _, tt := range tests { -@@ -89,10 +92,12 @@ func Test_getNextPart(t *testing.T) { - }{ - {name: "switch to sda3", args: args{partA: "/dev/sda2", partB: "/dev/sda3"}, want: "/dev/sda3", want1: "B", wantErr: false}, - {name: "switch to sda2", args: args{partA: "/dev/sda2", partB: "/dev/sda3"}, want: "/dev/sda2", want1: "A", wantErr: false}, -+ {name: "error", args: args{partA: "/dev/sda2", partB: "/dev/sda3"}, want: "", want1: "", wantErr: true}, - } - patchExecCommand := gomonkey.ApplyMethodSeq(&exec.Cmd{}, "CombinedOutput", []gomonkey.OutputCell{ - {Values: gomonkey.Params{[]byte("/"), nil}}, - {Values: gomonkey.Params{[]byte(""), nil}}, -+ {Values: gomonkey.Params{[]byte(""), fmt.Errorf("error")}}, - }) - defer patchExecCommand.Reset() - for _, tt := range tests { -@@ -242,10 +247,16 @@ func Test_getBootMode(t *testing.T) { - want: "legacy", - wantErr: false, - }, -+ { -+ name: "error", -+ want: "", -+ wantErr: true, -+ }, - } - patchOSStat := gomonkey.ApplyFuncSeq(os.Stat, []gomonkey.OutputCell{ - {Values: gomonkey.Params{nil, nil}}, - {Values: gomonkey.Params{nil, os.ErrNotExist}}, -+ {Values: gomonkey.Params{nil, fmt.Errorf("fake error")}}, - }) - defer patchOSStat.Reset() - for _, tt := range tests { -@@ -326,3 +337,104 @@ func Test_checkOCIImageDigestMatch(t *testing.T) { - }) - } - } -+ -+func Test_runCommandWithOut(t *testing.T) { -+ type args struct { -+ name string -+ args []string -+ } -+ tests := []struct { -+ name string -+ args args -+ want string -+ wantErr bool -+ }{ -+ {name: "error", args: args{name: "/mmm", args: []string{"", ""}}, wantErr: true}, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := runCommandWithOut(tt.args.name, tt.args.args...) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("runCommandWithOut() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("runCommandWithOut() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func Test_getRootfsDisks(t *testing.T) { -+ tests := []struct { -+ name string -+ want string -+ want1 string -+ wantErr bool -+ }{ -+ {name: "error", want: "", want1: "", wantErr: true}, -+ } -+ patchRunCommandWithOut := gomonkey.ApplyFuncSeq(runCommandWithOut, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{"", fmt.Errorf("fake error")}}, -+ }) -+ defer patchRunCommandWithOut.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, got1, err := getRootfsDisks() -+ if (err != nil) != tt.wantErr { -+ t.Errorf("getRootfsDisks() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("getRootfsDisks() got = %v, want %v", got, tt.want) -+ } -+ if got1 != tt.want1 { -+ t.Errorf("getRootfsDisks() got1 = %v, want %v", got1, tt.want1) -+ } -+ }) -+ } -+} -+ -+func Test_checkDiskSize(t *testing.T) { -+ type args struct { -+ needGBSize int -+ path string -+ } -+ tests := []struct { -+ name string -+ args args -+ wantErr bool -+ }{ -+ {name: "zero GB need", args: args{needGBSize: 0, path: "/dev/sda"}, wantErr: false}, -+ {name: "disk not enough", args: args{needGBSize: 100000, path: "/dev/sda"}, wantErr: true}, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ if err := checkDiskSize(tt.args.needGBSize, tt.args.path); (err != nil) != tt.wantErr { -+ t.Errorf("checkDiskSize() error = %v, wantErr %v", err, tt.wantErr) -+ } -+ }) -+ } -+} -+ -+func Test_deleteFile(t *testing.T) { -+ type args struct { -+ path string -+ } -+ tests := []struct { -+ name string -+ args args -+ wantErr bool -+ }{ -+ {name: "error", args: args{path: "/mmm"}, wantErr: true}, -+ } -+ patchStat := gomonkey.ApplyFuncReturn(os.Stat, nil, fmt.Errorf("fake error")) -+ defer patchStat.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ if err := deleteFile(tt.args.path); (err != nil) != tt.wantErr { -+ t.Errorf("deleteFile() error = %v, wantErr %v", err, tt.wantErr) -+ } -+ }) -+ } -+} -diff --git a/cmd/operator/controllers/os_controller_test.go b/cmd/operator/controllers/os_controller_test.go -index e59ce7e..6cc2760 100644 ---- a/cmd/operator/controllers/os_controller_test.go -+++ b/cmd/operator/controllers/os_controller_test.go -@@ -14,17 +14,22 @@ package controllers - - import ( - "context" -+ "fmt" -+ "reflect" - "testing" - "time" - -+ "github.com/agiledragon/gomonkey/v2" - "github.com/google/uuid" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -+ corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -+ "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/types" -- - upgradev1 "openeuler.org/KubeOS/api/v1alpha1" -+ "openeuler.org/KubeOS/pkg/common" - "openeuler.org/KubeOS/pkg/values" - ) - -@@ -775,3 +780,228 @@ func Test_deepCopySpecConfigs(t *testing.T) { - }) - } - } -+ -+func Test_getConfigOSInstances(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ } -+ tests := []struct { -+ name string -+ args args -+ want []upgradev1.OSInstance -+ wantErr bool -+ }{ -+ { -+ name: "list error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ }, -+ want: nil, -+ wantErr: true, -+ }, -+ } -+ patchList := gomonkey.ApplyMethodSeq(&OSReconciler{}, "List", []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{fmt.Errorf("list error")}}, -+ }) -+ defer patchList.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := getConfigOSInstances(tt.args.ctx, tt.args.r) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("getConfigOSInstances() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if !reflect.DeepEqual(got, tt.want) { -+ t.Errorf("getConfigOSInstances() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func Test_checkUpgrading(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ maxUnavailable int -+ } -+ tests := []struct { -+ name string -+ args args -+ want int -+ wantErr bool -+ }{ -+ { -+ name: "label error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ }, -+ want: 0, -+ wantErr: true, -+ }, -+ } -+ patchNewRequirement := gomonkey.ApplyFuncSeq(labels.NewRequirement, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{nil, fmt.Errorf("label error")}}, -+ {Values: gomonkey.Params{nil, nil}}, -+ }) -+ defer patchNewRequirement.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := checkUpgrading(tt.args.ctx, tt.args.r, tt.args.maxUnavailable) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("checkUpgrading() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if got != tt.want { -+ t.Errorf("checkUpgrading() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func Test_getIdleOSInstances(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ limit int -+ } -+ tests := []struct { -+ name string -+ args args -+ want []upgradev1.OSInstance -+ wantErr bool -+ }{ -+ { -+ name: "list error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ limit: 1, -+ }, -+ want: nil, -+ wantErr: true, -+ }, -+ } -+ patchList := gomonkey.ApplyMethodSeq(&OSReconciler{}, "List", []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{fmt.Errorf("list error")}}, -+ }) -+ defer patchList.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := getIdleOSInstances(tt.args.ctx, tt.args.r, tt.args.limit) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("getIdleOSInstances() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if !reflect.DeepEqual(got, tt.want) { -+ t.Errorf("getIdleOSInstances() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func Test_getNodes(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ limit int -+ reqs []labels.Requirement -+ } -+ tests := []struct { -+ name string -+ args args -+ want []corev1.Node -+ wantErr bool -+ }{ -+ { -+ name: "list error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ limit: 1, -+ }, -+ want: nil, -+ wantErr: true, -+ }, -+ } -+ patchList := gomonkey.ApplyMethodSeq(&OSReconciler{}, "List", []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{fmt.Errorf("list error")}}, -+ }) -+ defer patchList.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ got, err := getNodes(tt.args.ctx, tt.args.r, tt.args.limit, tt.args.reqs...) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("getNodes() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if !reflect.DeepEqual(got, tt.want) { -+ t.Errorf("getNodes() = %v, want %v", got, tt.want) -+ } -+ }) -+ } -+} -+ -+func Test_getAndUpdateOS(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ name types.NamespacedName -+ } -+ tests := []struct { -+ name string -+ args args -+ wantOs upgradev1.OS -+ wantNodeNum int -+ wantErr bool -+ }{ -+ { -+ name: "label error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ name: types.NamespacedName{Namespace: "test_ns", Name: "test"}, -+ }, -+ wantOs: upgradev1.OS{}, -+ wantNodeNum: 0, -+ wantErr: true, -+ }, -+ { -+ name: "get nodes error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ name: types.NamespacedName{Namespace: "test_ns", Name: "test"}, -+ }, -+ wantOs: upgradev1.OS{}, -+ wantNodeNum: 0, -+ wantErr: true, -+ }, -+ } -+ patchGet := gomonkey.ApplyMethodReturn(&OSReconciler{}, "Get", nil) -+ defer patchGet.Reset() -+ patchNewRequirement := gomonkey.ApplyFuncSeq(labels.NewRequirement, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{nil, fmt.Errorf("label error")}}, -+ {Values: gomonkey.Params{&labels.Requirement{}, nil}}, -+ }) -+ defer patchNewRequirement.Reset() -+ patchGetNodes := gomonkey.ApplyFuncReturn(getNodes, nil, fmt.Errorf("get nodes error")) -+ defer patchGetNodes.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ gotOs, gotNodeNum, err := getAndUpdateOS(tt.args.ctx, tt.args.r, tt.args.name) -+ if (err != nil) != tt.wantErr { -+ t.Errorf("getAndUpdateOS() error = %v, wantErr %v", err, tt.wantErr) -+ return -+ } -+ if !reflect.DeepEqual(gotOs, tt.wantOs) { -+ t.Errorf("getAndUpdateOS() gotOs = %v, want %v", gotOs, tt.wantOs) -+ } -+ if gotNodeNum != tt.wantNodeNum { -+ t.Errorf("getAndUpdateOS() gotNodeNum = %v, want %v", gotNodeNum, tt.wantNodeNum) -+ } -+ }) -+ } -+} -diff --git a/cmd/proxy/controllers/os_controller_test.go b/cmd/proxy/controllers/os_controller_test.go -index 27cb0cd..14b6b66 100644 ---- a/cmd/proxy/controllers/os_controller_test.go -+++ b/cmd/proxy/controllers/os_controller_test.go -@@ -16,25 +16,27 @@ import ( - "context" - "fmt" - "reflect" -+ "testing" - "time" - - "github.com/agiledragon/gomonkey/v2" - "github.com/google/uuid" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -+ corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -- -+ "k8s.io/kubectl/pkg/drain" - upgradev1 "openeuler.org/KubeOS/api/v1alpha1" - "openeuler.org/KubeOS/pkg/agentclient" -+ "openeuler.org/KubeOS/pkg/common" - "openeuler.org/KubeOS/pkg/values" - ) - - var _ = Describe("OsController", func() { - const ( -- OSName = "test-os" -- -+ OSName = "test-os" - timeout = time.Second * 20 - interval = time.Millisecond * 500 - ) -@@ -67,6 +69,24 @@ var _ = Describe("OsController", func() { - testNamespace = existingNamespace.Name - }) - -+ AfterEach(func() { -+ // delete all OS CRs -+ osList := &upgradev1.OSList{} -+ err := k8sClient.List(context.Background(), osList) -+ Expect(err).ToNot(HaveOccurred()) -+ for _, os := range osList.Items { -+ k8sClient.Delete(context.Background(), &os) -+ } -+ osList = &upgradev1.OSList{} -+ Eventually(func() bool { -+ err = k8sClient.List(context.Background(), osList) -+ if err != nil || len(osList.Items) != 0 { -+ return false -+ } -+ return true -+ }, timeout, interval).Should(BeTrue()) -+ }) -+ - Context("When we want to rollback", func() { - It("Should be able to rollback to previous version", func() { - ctx := context.Background() -@@ -182,6 +202,13 @@ var _ = Describe("OsController", func() { - Expect(k8sClient.Status().Update(ctx, existingNode)).Should(Succeed()) - - By("Changing the OS Spec config to trigger reconcile") -+ createdOSIns = &upgradev1.OSInstance{} -+ Eventually(func() bool { -+ err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns) -+ return err == nil -+ }, timeout, interval).Should(BeTrue()) -+ createdOSIns.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -+ Expect(k8sClient.Update(ctx, createdOSIns)).Should(Succeed()) - createdOS = &upgradev1.OS{} - Eventually(func() bool { - err := k8sClient.Get(ctx, osCRLookupKey, createdOS) -@@ -190,7 +217,7 @@ var _ = Describe("OsController", func() { - createdOS.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} - Expect(k8sClient.Update(ctx, createdOS)).Should(Succeed()) - -- 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 - createdOSIns = &upgradev1.OSInstance{} - Eventually(func() bool { - err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns) -@@ -335,7 +362,7 @@ var _ = Describe("OsController", func() { - Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v1")) - - By("Checking the OSInstance status config version") -- 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 { -@@ -451,7 +478,7 @@ var _ = Describe("OsController", func() { - OSVersion: "KubeOS v2", - FlagSafe: true, - MTLS: false, -- EvictPodForce: true, -+ EvictPodForce: false, - SysConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, - UpgradeConfigs: upgradev1.SysConfigs{ - Version: "v2", -@@ -478,7 +505,7 @@ var _ = Describe("OsController", func() { - Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v2")) - - By("Checking the OSInstance status config version") -- 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 { -@@ -566,7 +593,7 @@ var _ = Describe("OsController", func() { - Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v1")) - - By("Checking the existence of new OSInstance") -- 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 { -@@ -644,7 +671,7 @@ var _ = Describe("OsController", func() { - }, - UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, - }, -- Status: upgradev1.OSInstanceStatus{}, -+ Status: upgradev1.OSInstanceStatus{SysConfigs: upgradev1.SysConfigs{Version: "v1"}}, - } - Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed()) - -@@ -711,7 +738,7 @@ var _ = Describe("OsController", func() { - Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v1")) - - By("Checking the OSInstance status config version failed to be updated") -- 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 { -@@ -721,10 +748,18 @@ var _ = Describe("OsController", func() { - Expect(createdOSIns.Status.SysConfigs.Version).Should(Equal("v1")) - Expect(createdOSIns.Spec.SysConfigs.Version).Should(Equal("v2")) - -- By("Changing the OS Spec config version to previous one") -+ By("Changing the OS and OSi Spec config version to previous one") - OS.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} - Expect(k8sClient.Update(ctx, OS)).Should(Succeed()) -- time.Sleep(1 * time.Second) // sleep a while to make sure Reconcile finished -+ createdOSIns = &upgradev1.OSInstance{} -+ Eventually(func() bool { -+ err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns) -+ return err == nil -+ }, timeout, interval).Should(BeTrue()) -+ createdOSIns.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -+ Expect(k8sClient.Update(ctx, createdOSIns)).Should(Succeed()) -+ -+ time.Sleep(2 * time.Second) // sleep a while to make sure Reconcile finished - createdOSIns = &upgradev1.OSInstance{} - Eventually(func() bool { - err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns) -@@ -799,7 +834,6 @@ var _ = Describe("OsController", func() { - }, - }, - }, -- Status: upgradev1.OSInstanceStatus{}, - } - Expect(k8sClient.Create(ctx, OSIns)).Should(Succeed()) - -@@ -870,7 +904,7 @@ var _ = Describe("OsController", func() { - Expect(createdOS.Spec.OSVersion).Should(Equal("KubeOS v2")) - - By("Checking the OSInstance status config version failed to be updated") -- 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 { -@@ -889,6 +923,16 @@ var _ = Describe("OsController", func() { - err := k8sClient.Get(ctx, osInsCRLookupKey, createdOSIns) - return err == nil - }, timeout, interval).Should(BeTrue()) -+ -+ 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()) -+ createdOSIns.Spec.UpgradeConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -+ Expect(k8sClient.Update(ctx, createdOSIns)).Should(Succeed()) -+ - // NodeStatus changes to idle then operator can reassign configs to this node - Expect(createdOSIns.Spec.NodeStatus).Should(Equal(values.NodeStatusIdle.String())) - existingNode = &v1.Node{} -@@ -906,37 +950,7 @@ var _ = Describe("OsController", func() { - It("Should be able to rollback to previous config version to jump out of error state", 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{ -@@ -1004,6 +1018,37 @@ var _ = Describe("OsController", func() { - createdOSIns.Status.SysConfigs.Version = "v1" - Expect(k8sClient.Status().Update(ctx, createdOSIns)).Should(Succeed()) - Expect(createdOSIns.Status.UpgradeConfigs.Version).Should(Equal("v2")) -+ Expect(createdOSIns.Status.SysConfigs.Version).Should(Equal("v1")) -+ -+ By("Creating a worker node") -+ 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 - - // stub r.Connection.ConfigureSpec() - patchConfigure := gomonkey.ApplyMethod(reflect.TypeOf(reconciler.Connection), -@@ -1067,7 +1112,6 @@ var _ = Describe("OsController", func() { - - By("Checking the OSInstance status config version failed to be updated") - 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) -@@ -1077,8 +1121,21 @@ var _ = Describe("OsController", func() { - Expect(createdOSIns.Spec.SysConfigs.Version).Should(Equal("v2")) - - By("Changing the OS Spec config version to previous one") -- OS.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -- Expect(k8sClient.Update(ctx, OS)).Should(Succeed()) -+ createdOS = &upgradev1.OS{} -+ Eventually(func() bool { -+ err := k8sClient.Get(ctx, osCRLookupKey, createdOS) -+ return err == nil -+ }, timeout, interval).Should(BeTrue()) -+ createdOS.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -+ Expect(k8sClient.Update(ctx, createdOS)).Should(Succeed()) -+ getOSIns := &upgradev1.OSInstance{} -+ Eventually(func() bool { -+ err := k8sClient.Get(ctx, osInsCRLookupKey, getOSIns) -+ return err == nil -+ }, timeout, interval).Should(BeTrue()) -+ getOSIns.Spec.SysConfigs = upgradev1.SysConfigs{Version: "v1", Configs: []upgradev1.SysConfig{}} -+ Expect(k8sClient.Update(ctx, getOSIns)).Should(Succeed()) -+ - time.Sleep(2 * time.Second) // sleep a while to make sure Reconcile finished - createdOSIns = &upgradev1.OSInstance{} - Eventually(func() bool { -@@ -1225,3 +1282,147 @@ var _ = Describe("OsController", func() { - }) - }) - }) -+ -+func Test_evictNode(t *testing.T) { -+ type args struct { -+ drainer *drain.Helper -+ node *corev1.Node -+ } -+ tests := []struct { -+ name string -+ args args -+ wantErr bool -+ }{ -+ { -+ name: "node unschedulable", -+ args: args{ -+ drainer: &drain.Helper{}, -+ node: &corev1.Node{Spec: v1.NodeSpec{Unschedulable: true}}, -+ }, -+ wantErr: false, -+ }, -+ { -+ name: "runCordonError1", -+ args: args{ -+ drainer: &drain.Helper{}, -+ node: &corev1.Node{}, -+ }, -+ wantErr: true, -+ }, -+ { -+ name: "runNodeDrainError", -+ args: args{ -+ drainer: &drain.Helper{}, -+ node: &corev1.Node{}, -+ }, -+ wantErr: true, -+ }, -+ { -+ name: "runUncordonError2", -+ args: args{ -+ drainer: &drain.Helper{}, -+ node: &corev1.Node{}, -+ }, -+ wantErr: true, -+ }, -+ } -+ patchRunCordon := gomonkey.ApplyFuncSeq(drain.RunCordonOrUncordon, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{fmt.Errorf("cordon error")}}, -+ {Values: gomonkey.Params{nil}}, -+ {Values: gomonkey.Params{fmt.Errorf("cordon error")}}, -+ {Values: gomonkey.Params{nil}}, -+ {Values: gomonkey.Params{nil}}, -+ }) -+ defer patchRunCordon.Reset() -+ patchRunNodeDrain := gomonkey.ApplyFuncSeq(drain.RunNodeDrain, []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{fmt.Errorf("node drain error")}}, -+ {Values: gomonkey.Params{fmt.Errorf("node drain error")}}, -+ }) -+ defer patchRunNodeDrain.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ if err := evictNode(tt.args.drainer, tt.args.node); (err != nil) != tt.wantErr { -+ t.Errorf("evictNode() error = %v, wantErr %v", err, tt.wantErr) -+ } -+ }) -+ } -+} -+ -+func Test_updateConfigStatus(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ osInstance *upgradev1.OSInstance -+ configType string -+ } -+ tests := []struct { -+ name string -+ args args -+ wantErr bool -+ }{ -+ { -+ name: "invalid config type", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ osInstance: &upgradev1.OSInstance{}, -+ configType: "invalid", -+ }, -+ wantErr: true, -+ }, -+ } -+ patchUpdate := gomonkey.ApplyMethodReturn(&OSReconciler{}, "Update", fmt.Errorf("update error")) -+ patchStatus := gomonkey.ApplyMethodReturn(&OSReconciler{}, "Status", &OSReconciler{}) -+ defer patchUpdate.Reset() -+ defer patchStatus.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ if err := updateConfigStatus(tt.args.ctx, tt.args.r, tt.args.osInstance, tt.args.configType); (err != nil) != tt.wantErr { -+ t.Errorf("updateConfigStatus() error = %v, wantErr %v", err, tt.wantErr) -+ } -+ }) -+ } -+} -+ -+func Test_getOSAndNodeStatus(t *testing.T) { -+ type args struct { -+ ctx context.Context -+ r common.ReadStatusWriter -+ name types.NamespacedName -+ hostName string -+ } -+ tests := []struct { -+ name string -+ args args -+ wantOS upgradev1.OS -+ wantNode corev1.Node -+ }{ -+ { -+ name: "get node error", -+ args: args{ -+ ctx: context.Background(), -+ r: &OSReconciler{}, -+ name: types.NamespacedName{}, -+ hostName: "test-node", -+ }, -+ wantOS: upgradev1.OS{}, -+ wantNode: corev1.Node{}, -+ }, -+ } -+ patchGet := gomonkey.ApplyMethodSeq(&OSReconciler{}, "Get", []gomonkey.OutputCell{ -+ {Values: gomonkey.Params{nil}}, -+ {Values: gomonkey.Params{fmt.Errorf("get node error")}}, -+ }) -+ defer patchGet.Reset() -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ gotOS, gotNode := getOSAndNodeStatus(tt.args.ctx, tt.args.r, tt.args.name, tt.args.hostName) -+ if !reflect.DeepEqual(gotOS, tt.wantOS) { -+ t.Errorf("getOSAndNodeStatus() gotOS = %v, want %v", gotOS, tt.wantOS) -+ } -+ if !reflect.DeepEqual(gotNode, tt.wantNode) { -+ t.Errorf("getOSAndNodeStatus() gotNode = %v, want %v", gotNode, tt.wantNode) -+ } -+ }) -+ } -+} --- -2.39.0 - diff --git a/0020-KubeOS-modify-code-for-clean-code.patch b/0020-KubeOS-modify-code-for-clean-code.patch deleted file mode 100644 index 6e6bb6cdd6646f7253e24df4a7050e701bce4adb..0000000000000000000000000000000000000000 --- a/0020-KubeOS-modify-code-for-clean-code.patch +++ /dev/null @@ -1,86 +0,0 @@ -From a9220ad3175c38979a052cd595efd34888d886c6 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -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 ---- - 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 - diff --git a/0021-KubeOS-delete-raw-and-docker-image-upgrade.patch b/0021-KubeOS-delete-raw-and-docker-image-upgrade.patch deleted file mode 100644 index cd248bf8830021afcbe81b55aeb0fc74a7a0959e..0000000000000000000000000000000000000000 --- a/0021-KubeOS-delete-raw-and-docker-image-upgrade.patch +++ /dev/null @@ -1,1867 +0,0 @@ -From 5c9609914a7418ea34d1ff15dfc21877fb197763 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Thu, 24 Aug 2023 11:00:26 +0800 -Subject: [PATCH 4/5] KubeOS: delete raw and docker image upgrade - -delete the part of using raw and docker image to upgrade - -Signed-off-by: Yuhang Wei ---- - api/v1alpha1/os_types.go | 9 - - cmd/agent/api/agent.pb.go | 337 ++++--------- - cmd/agent/api/agent.proto | 15 +- - cmd/agent/server/disk_image.go | 217 -------- - cmd/agent/server/disk_image_test.go | 471 ------------------ - cmd/agent/server/docker_image.go | 73 --- - cmd/agent/server/docker_image_test.go | 118 ----- - cmd/agent/server/server.go | 8 - - cmd/agent/server/server_test.go | 23 +- - .../controllers/os_controller_test.go | 8 - - cmd/proxy/controllers/os_controller.go | 6 - - cmd/proxy/controllers/os_controller_test.go | 16 - - .../config/crd/upgrade.openeuler.org_os.yaml | 15 - - pkg/agentclient/connection.go | 15 - - 14 files changed, 115 insertions(+), 1216 deletions(-) - delete mode 100644 cmd/agent/server/disk_image.go - delete mode 100644 cmd/agent/server/disk_image_test.go - delete mode 100644 cmd/agent/server/docker_image.go - delete mode 100644 cmd/agent/server/docker_image_test.go - -diff --git a/api/v1alpha1/os_types.go b/api/v1alpha1/os_types.go -index f9474b7..b4655e8 100644 ---- a/api/v1alpha1/os_types.go -+++ b/api/v1alpha1/os_types.go -@@ -19,22 +19,13 @@ import ( - // OSSpec defines the desired state of OS - type OSSpec struct { - OSVersion string `json:"osversion"` -- ImageURL string `json:"imageurl"` - MaxUnavailable int `json:"maxunavailable"` - CheckSum string `json:"checksum"` -- FlagSafe bool `json:"flagSafe"` -- MTLS bool `json:"mtls"` - ImageType string `json:"imagetype"` - ContainerImage string `json:"containerimage"` - OpsType string `json:"opstype"` - EvictPodForce bool `json:"evictpodforce"` - // +kubebuilder:validation:Optional -- CaCert string `json:"cacert"` -- // +kubebuilder:validation:Optional -- ClientCert string `json:"clientcert"` -- // +kubebuilder:validation:Optional -- ClientKey string `json:"clientkey"` -- // +kubebuilder:validation:Optional - SysConfigs SysConfigs `json:"sysconfigs"` - // +kubebuilder:validation:Optional - UpgradeConfigs SysConfigs `json:"upgradeconfigs"` -diff --git a/cmd/agent/api/agent.pb.go b/cmd/agent/api/agent.pb.go -index 077a57e..034337d 100644 ---- a/cmd/agent/api/agent.pb.go -+++ b/cmd/agent/api/agent.pb.go -@@ -36,14 +36,10 @@ type UpdateRequest struct { - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - -- Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -- ImageUrl string `protobuf:"bytes,2,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` -- CheckSum string `protobuf:"bytes,3,opt,name=check_sum,json=checkSum,proto3" json:"check_sum,omitempty"` -- FlagSafe bool `protobuf:"varint,4,opt,name=flagSafe,proto3" json:"flagSafe,omitempty"` -- MTLS bool `protobuf:"varint,5,opt,name=mTLS,proto3" json:"mTLS,omitempty"` -- ImageType string `protobuf:"bytes,6,opt,name=image_type,json=imageType,proto3" json:"image_type,omitempty"` -- ContainerImage string `protobuf:"bytes,7,opt,name=container_image,json=containerImage,proto3" json:"container_image,omitempty"` -- Certs *CertsInfo `protobuf:"bytes,8,opt,name=certs,proto3" json:"certs,omitempty"` -+ Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -+ CheckSum string `protobuf:"bytes,2,opt,name=check_sum,json=checkSum,proto3" json:"check_sum,omitempty"` -+ ImageType string `protobuf:"bytes,3,opt,name=image_type,json=imageType,proto3" json:"image_type,omitempty"` -+ ContainerImage string `protobuf:"bytes,4,opt,name=container_image,json=containerImage,proto3" json:"container_image,omitempty"` - } - - func (x *UpdateRequest) Reset() { -@@ -85,13 +81,6 @@ func (x *UpdateRequest) GetVersion() string { - return "" - } - --func (x *UpdateRequest) GetImageUrl() string { -- if x != nil { -- return x.ImageUrl -- } -- return "" --} -- - func (x *UpdateRequest) GetCheckSum() string { - if x != nil { - return x.CheckSum -@@ -99,20 +88,6 @@ func (x *UpdateRequest) GetCheckSum() string { - return "" - } - --func (x *UpdateRequest) GetFlagSafe() bool { -- if x != nil { -- return x.FlagSafe -- } -- return false --} -- --func (x *UpdateRequest) GetMTLS() bool { -- if x != nil { -- return x.MTLS -- } -- return false --} -- - func (x *UpdateRequest) GetImageType() string { - if x != nil { - return x.ImageType -@@ -127,76 +102,6 @@ func (x *UpdateRequest) GetContainerImage() string { - return "" - } - --func (x *UpdateRequest) GetCerts() *CertsInfo { -- if x != nil { -- return x.Certs -- } -- return nil --} -- --type CertsInfo struct { -- state protoimpl.MessageState -- sizeCache protoimpl.SizeCache -- unknownFields protoimpl.UnknownFields -- -- CaCaert string `protobuf:"bytes,1,opt,name=ca_caert,json=caCaert,proto3" json:"ca_caert,omitempty"` -- ClientCert string `protobuf:"bytes,2,opt,name=client_cert,json=clientCert,proto3" json:"client_cert,omitempty"` -- ClientKey string `protobuf:"bytes,3,opt,name=client_key,json=clientKey,proto3" json:"client_key,omitempty"` --} -- --func (x *CertsInfo) Reset() { -- *x = CertsInfo{} -- if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[1] -- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) -- ms.StoreMessageInfo(mi) -- } --} -- --func (x *CertsInfo) String() string { -- return protoimpl.X.MessageStringOf(x) --} -- --func (*CertsInfo) ProtoMessage() {} -- --func (x *CertsInfo) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[1] -- if protoimpl.UnsafeEnabled && x != nil { -- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) -- if ms.LoadMessageInfo() == nil { -- ms.StoreMessageInfo(mi) -- } -- return ms -- } -- return mi.MessageOf(x) --} -- --// Deprecated: Use CertsInfo.ProtoReflect.Descriptor instead. --func (*CertsInfo) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{1} --} -- --func (x *CertsInfo) GetCaCaert() string { -- if x != nil { -- return x.CaCaert -- } -- return "" --} -- --func (x *CertsInfo) GetClientCert() string { -- if x != nil { -- return x.ClientCert -- } -- return "" --} -- --func (x *CertsInfo) GetClientKey() string { -- if x != nil { -- return x.ClientKey -- } -- return "" --} -- - type UpdateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache -@@ -208,7 +113,7 @@ type UpdateResponse struct { - func (x *UpdateResponse) Reset() { - *x = UpdateResponse{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[2] -+ mi := &file_api_agent_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -221,7 +126,7 @@ func (x *UpdateResponse) String() string { - func (*UpdateResponse) ProtoMessage() {} - - func (x *UpdateResponse) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[2] -+ mi := &file_api_agent_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -234,7 +139,7 @@ func (x *UpdateResponse) ProtoReflect() protoreflect.Message { - - // Deprecated: Use UpdateResponse.ProtoReflect.Descriptor instead. - func (*UpdateResponse) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{2} -+ return file_api_agent_proto_rawDescGZIP(), []int{1} - } - - func (x *UpdateResponse) GetErr() int32 { -@@ -253,7 +158,7 @@ type RollbackRequest struct { - func (x *RollbackRequest) Reset() { - *x = RollbackRequest{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[3] -+ mi := &file_api_agent_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -266,7 +171,7 @@ func (x *RollbackRequest) String() string { - func (*RollbackRequest) ProtoMessage() {} - - func (x *RollbackRequest) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[3] -+ mi := &file_api_agent_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -279,7 +184,7 @@ func (x *RollbackRequest) ProtoReflect() protoreflect.Message { - - // Deprecated: Use RollbackRequest.ProtoReflect.Descriptor instead. - func (*RollbackRequest) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{3} -+ return file_api_agent_proto_rawDescGZIP(), []int{2} - } - - type RollbackResponse struct { -@@ -293,7 +198,7 @@ type RollbackResponse struct { - func (x *RollbackResponse) Reset() { - *x = RollbackResponse{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[4] -+ mi := &file_api_agent_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -306,7 +211,7 @@ func (x *RollbackResponse) String() string { - func (*RollbackResponse) ProtoMessage() {} - - func (x *RollbackResponse) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[4] -+ mi := &file_api_agent_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -319,7 +224,7 @@ func (x *RollbackResponse) ProtoReflect() protoreflect.Message { - - // Deprecated: Use RollbackResponse.ProtoReflect.Descriptor instead. - func (*RollbackResponse) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{4} -+ return file_api_agent_proto_rawDescGZIP(), []int{3} - } - - func (x *RollbackResponse) GetErr() int32 { -@@ -340,7 +245,7 @@ type ConfigureRequest struct { - func (x *ConfigureRequest) Reset() { - *x = ConfigureRequest{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[5] -+ mi := &file_api_agent_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -353,7 +258,7 @@ func (x *ConfigureRequest) String() string { - func (*ConfigureRequest) ProtoMessage() {} - - func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[5] -+ mi := &file_api_agent_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -366,7 +271,7 @@ func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { - - // Deprecated: Use ConfigureRequest.ProtoReflect.Descriptor instead. - func (*ConfigureRequest) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{5} -+ return file_api_agent_proto_rawDescGZIP(), []int{4} - } - - func (x *ConfigureRequest) GetConfigs() []*SysConfig { -@@ -387,7 +292,7 @@ type ConfigureResponse struct { - func (x *ConfigureResponse) Reset() { - *x = ConfigureResponse{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[6] -+ mi := &file_api_agent_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -400,7 +305,7 @@ func (x *ConfigureResponse) String() string { - func (*ConfigureResponse) ProtoMessage() {} - - func (x *ConfigureResponse) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[6] -+ mi := &file_api_agent_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -413,7 +318,7 @@ func (x *ConfigureResponse) ProtoReflect() protoreflect.Message { - - // Deprecated: Use ConfigureResponse.ProtoReflect.Descriptor instead. - func (*ConfigureResponse) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{6} -+ return file_api_agent_proto_rawDescGZIP(), []int{5} - } - - func (x *ConfigureResponse) GetErr() int32 { -@@ -436,7 +341,7 @@ type SysConfig struct { - func (x *SysConfig) Reset() { - *x = SysConfig{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[7] -+ mi := &file_api_agent_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -449,7 +354,7 @@ func (x *SysConfig) String() string { - func (*SysConfig) ProtoMessage() {} - - func (x *SysConfig) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[7] -+ mi := &file_api_agent_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -462,7 +367,7 @@ func (x *SysConfig) ProtoReflect() protoreflect.Message { - - // Deprecated: Use SysConfig.ProtoReflect.Descriptor instead. - func (*SysConfig) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{7} -+ return file_api_agent_proto_rawDescGZIP(), []int{6} - } - - func (x *SysConfig) GetModel() string { -@@ -498,7 +403,7 @@ type KeyInfo struct { - func (x *KeyInfo) Reset() { - *x = KeyInfo{} - if protoimpl.UnsafeEnabled { -- mi := &file_api_agent_proto_msgTypes[8] -+ mi := &file_api_agent_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -@@ -511,7 +416,7 @@ func (x *KeyInfo) String() string { - func (*KeyInfo) ProtoMessage() {} - - func (x *KeyInfo) ProtoReflect() protoreflect.Message { -- mi := &file_api_agent_proto_msgTypes[8] -+ mi := &file_api_agent_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { -@@ -524,7 +429,7 @@ func (x *KeyInfo) ProtoReflect() protoreflect.Message { - - // Deprecated: Use KeyInfo.ProtoReflect.Descriptor instead. - func (*KeyInfo) Descriptor() ([]byte, []int) { -- return file_api_agent_proto_rawDescGZIP(), []int{8} -+ return file_api_agent_proto_rawDescGZIP(), []int{7} - } - - func (x *KeyInfo) GetValue() string { -@@ -545,74 +450,60 @@ var File_api_agent_proto protoreflect.FileDescriptor - - var file_api_agent_proto_rawDesc = []byte{ - 0x0a, 0x0f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, -- 0x6f, 0x12, 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x22, 0x83, 0x02, 0x0a, 0x0d, 0x55, 0x70, 0x64, -+ 0x6f, 0x12, 0x05, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x22, 0x8e, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, -- 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, -- 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, -- 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x03, -- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x75, 0x6d, 0x12, 0x1a, -- 0x0a, 0x08, 0x66, 0x6c, 0x61, 0x67, 0x53, 0x61, 0x66, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, -- 0x52, 0x08, 0x66, 0x6c, 0x61, 0x67, 0x53, 0x61, 0x66, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x54, -- 0x4c, 0x53, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x6d, 0x54, 0x4c, 0x53, 0x12, 0x1d, -- 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, -- 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, -- 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, -- 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, -- 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, -- 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x65, -- 0x72, 0x74, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x63, 0x65, 0x72, 0x74, 0x73, 0x22, 0x66, -- 0x0a, 0x09, 0x43, 0x65, 0x72, 0x74, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x63, -- 0x61, 0x5f, 0x63, 0x61, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, -- 0x61, 0x43, 0x61, 0x65, 0x72, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, -- 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, -- 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, -- 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x69, -- 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x22, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, -- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, -- 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x11, 0x0a, 0x0f, 0x52, 0x6f, -- 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x24, 0x0a, -- 0x10, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, -- 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, -- 0x65, 0x72, 0x72, 0x22, 0x3e, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, -- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, -- 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, -- 0x2e, 0x53, 0x79, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x66, -- 0x69, 0x67, 0x73, 0x22, 0x25, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, -- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, -- 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0xca, 0x01, 0x0a, 0x09, 0x53, -- 0x79, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, -- 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1e, -- 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, -- 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x3a, -- 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, -- 0x32, 0x1e, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x43, 0x6f, 0x6e, 0x66, -- 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, -- 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x4b, 0x0a, 0x0d, 0x43, 0x6f, -- 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, -- 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, -- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, -- 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x76, 0x61, -- 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3d, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x49, 0x6e, -- 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, -- 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, -- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x70, 0x65, -- 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xbe, 0x01, 0x0a, 0x02, 0x4f, 0x53, 0x12, 0x37, 0x0a, -- 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, -- 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, -- 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, -- 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, -- 0x63, 0x6b, 0x12, 0x16, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, -- 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x67, 0x65, -- 0x6e, 0x74, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, -- 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, -- 0x72, 0x65, 0x12, 0x17, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, -- 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x67, -- 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, -- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x20, 0x5a, 0x1e, 0x6f, 0x70, 0x65, 0x6e, 0x65, -- 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x6f, 0x73, 0x2f, -- 0x61, 0x70, 0x69, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, -- 0x33, -+ 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x73, 0x75, -+ 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x75, -+ 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, -+ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, -+ 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x6d, -+ 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, -+ 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x22, 0x0a, 0x0e, 0x55, 0x70, 0x64, -+ 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, -+ 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x11, 0x0a, -+ 0x0f, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, -+ 0x22, 0x24, 0x0a, 0x10, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, -+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, -+ 0x05, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x3e, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, -+ 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x07, 0x63, 0x6f, -+ 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x67, -+ 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x63, -+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, 0x25, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, -+ 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, -+ 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0xca, 0x01, -+ 0x0a, 0x09, 0x53, 0x79, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6d, -+ 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, -+ 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x18, -+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, -+ 0x68, 0x12, 0x3a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, -+ 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x79, 0x73, 0x43, -+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, -+ 0x74, 0x72, 0x79, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x4b, 0x0a, -+ 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, -+ 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, -+ 0x12, 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, -+ 0x0e, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, -+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3d, 0x0a, 0x07, 0x4b, 0x65, -+ 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, -+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, -+ 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, -+ 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xbe, 0x01, 0x0a, 0x02, 0x4f, 0x53, -+ 0x12, 0x37, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x61, 0x67, 0x65, -+ 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, -+ 0x1a, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, -+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x08, 0x52, 0x6f, 0x6c, -+ 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x16, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x6f, -+ 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, -+ 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, -+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, -+ 0x69, 0x67, 0x75, 0x72, 0x65, 0x12, 0x17, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, -+ 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, -+ 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, -+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x20, 0x5a, 0x1e, 0x6f, 0x70, -+ 0x65, 0x6e, 0x65, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6b, 0x75, 0x62, 0x65, -+ 0x6f, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, -+ 0x6f, 0x74, 0x6f, 0x33, - } - - var ( -@@ -627,35 +518,33 @@ func file_api_agent_proto_rawDescGZIP() []byte { - return file_api_agent_proto_rawDescData - } - --var file_api_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 10) -+var file_api_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 9) - var file_api_agent_proto_goTypes = []interface{}{ - (*UpdateRequest)(nil), // 0: agent.UpdateRequest -- (*CertsInfo)(nil), // 1: agent.CertsInfo -- (*UpdateResponse)(nil), // 2: agent.UpdateResponse -- (*RollbackRequest)(nil), // 3: agent.RollbackRequest -- (*RollbackResponse)(nil), // 4: agent.RollbackResponse -- (*ConfigureRequest)(nil), // 5: agent.ConfigureRequest -- (*ConfigureResponse)(nil), // 6: agent.ConfigureResponse -- (*SysConfig)(nil), // 7: agent.SysConfig -- (*KeyInfo)(nil), // 8: agent.KeyInfo -- nil, // 9: agent.SysConfig.ContentsEntry -+ (*UpdateResponse)(nil), // 1: agent.UpdateResponse -+ (*RollbackRequest)(nil), // 2: agent.RollbackRequest -+ (*RollbackResponse)(nil), // 3: agent.RollbackResponse -+ (*ConfigureRequest)(nil), // 4: agent.ConfigureRequest -+ (*ConfigureResponse)(nil), // 5: agent.ConfigureResponse -+ (*SysConfig)(nil), // 6: agent.SysConfig -+ (*KeyInfo)(nil), // 7: agent.KeyInfo -+ nil, // 8: agent.SysConfig.ContentsEntry - } - var file_api_agent_proto_depIdxs = []int32{ -- 1, // 0: agent.UpdateRequest.certs:type_name -> agent.CertsInfo -- 7, // 1: agent.ConfigureRequest.configs:type_name -> agent.SysConfig -- 9, // 2: agent.SysConfig.contents:type_name -> agent.SysConfig.ContentsEntry -- 8, // 3: agent.SysConfig.ContentsEntry.value:type_name -> agent.KeyInfo -- 0, // 4: agent.OS.Update:input_type -> agent.UpdateRequest -- 3, // 5: agent.OS.Rollback:input_type -> agent.RollbackRequest -- 5, // 6: agent.OS.Configure:input_type -> agent.ConfigureRequest -- 2, // 7: agent.OS.Update:output_type -> agent.UpdateResponse -- 4, // 8: agent.OS.Rollback:output_type -> agent.RollbackResponse -- 6, // 9: agent.OS.Configure:output_type -> agent.ConfigureResponse -- 7, // [7:10] is the sub-list for method output_type -- 4, // [4:7] is the sub-list for method input_type -- 4, // [4:4] is the sub-list for extension type_name -- 4, // [4:4] is the sub-list for extension extendee -- 0, // [0:4] is the sub-list for field type_name -+ 6, // 0: agent.ConfigureRequest.configs:type_name -> agent.SysConfig -+ 8, // 1: agent.SysConfig.contents:type_name -> agent.SysConfig.ContentsEntry -+ 7, // 2: agent.SysConfig.ContentsEntry.value:type_name -> agent.KeyInfo -+ 0, // 3: agent.OS.Update:input_type -> agent.UpdateRequest -+ 2, // 4: agent.OS.Rollback:input_type -> agent.RollbackRequest -+ 4, // 5: agent.OS.Configure:input_type -> agent.ConfigureRequest -+ 1, // 6: agent.OS.Update:output_type -> agent.UpdateResponse -+ 3, // 7: agent.OS.Rollback:output_type -> agent.RollbackResponse -+ 5, // 8: agent.OS.Configure:output_type -> agent.ConfigureResponse -+ 6, // [6:9] is the sub-list for method output_type -+ 3, // [3:6] is the sub-list for method input_type -+ 3, // [3:3] is the sub-list for extension type_name -+ 3, // [3:3] is the sub-list for extension extendee -+ 0, // [0:3] is the sub-list for field type_name - } - - func init() { file_api_agent_proto_init() } -@@ -677,18 +566,6 @@ func file_api_agent_proto_init() { - } - } - file_api_agent_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { -- switch v := v.(*CertsInfo); i { -- case 0: -- return &v.state -- case 1: -- return &v.sizeCache -- case 2: -- return &v.unknownFields -- default: -- return nil -- } -- } -- file_api_agent_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateResponse); i { - case 0: - return &v.state -@@ -700,7 +577,7 @@ func file_api_agent_proto_init() { - return nil - } - } -- file_api_agent_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { -+ file_api_agent_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RollbackRequest); i { - case 0: - return &v.state -@@ -712,7 +589,7 @@ func file_api_agent_proto_init() { - return nil - } - } -- file_api_agent_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { -+ file_api_agent_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RollbackResponse); i { - case 0: - return &v.state -@@ -724,7 +601,7 @@ func file_api_agent_proto_init() { - return nil - } - } -- file_api_agent_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { -+ file_api_agent_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigureRequest); i { - case 0: - return &v.state -@@ -736,7 +613,7 @@ func file_api_agent_proto_init() { - return nil - } - } -- file_api_agent_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { -+ file_api_agent_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigureResponse); i { - case 0: - return &v.state -@@ -748,7 +625,7 @@ func file_api_agent_proto_init() { - return nil - } - } -- file_api_agent_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { -+ file_api_agent_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SysConfig); i { - case 0: - return &v.state -@@ -760,7 +637,7 @@ func file_api_agent_proto_init() { - return nil - } - } -- file_api_agent_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { -+ file_api_agent_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyInfo); i { - case 0: - return &v.state -@@ -779,7 +656,7 @@ func file_api_agent_proto_init() { - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_api_agent_proto_rawDesc, - NumEnums: 0, -- NumMessages: 10, -+ NumMessages: 9, - NumExtensions: 0, - NumServices: 1, - }, -diff --git a/cmd/agent/api/agent.proto b/cmd/agent/api/agent.proto -index fd15b9f..e81ad54 100644 ---- a/cmd/agent/api/agent.proto -+++ b/cmd/agent/api/agent.proto -@@ -24,20 +24,11 @@ service OS { - - message UpdateRequest { - string version = 1; -- string image_url = 2; -- string check_sum = 3; -- bool flagSafe = 4; -- bool mTLS = 5; -- string image_type = 6; -- string container_image = 7; -- CertsInfo certs = 8; -+ string check_sum = 2; -+ string image_type = 3; -+ string container_image = 4; - } - --message CertsInfo { -- string ca_caert = 1; -- string client_cert = 2; -- string client_key = 3; --} - - message UpdateResponse { - int32 err = 1; -diff --git a/cmd/agent/server/disk_image.go b/cmd/agent/server/disk_image.go -deleted file mode 100644 -index 8bd6bf6..0000000 ---- a/cmd/agent/server/disk_image.go -+++ /dev/null -@@ -1,217 +0,0 @@ --/* -- * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 ( -- "crypto/sha256" -- "crypto/tls" -- "crypto/x509" -- "encoding/hex" -- "fmt" -- "io" -- "io/ioutil" -- "net/http" -- "os" -- "path/filepath" -- "strings" -- "syscall" -- -- "github.com/sirupsen/logrus" -- -- pb "openeuler.org/KubeOS/cmd/agent/api" --) -- --type diskHandler struct{} -- --func (d diskHandler) downloadImage(req *pb.UpdateRequest) (string, error) { -- imagePath, err := d.getRootfsArchive(req, preparePath{}) -- if err != nil { -- return "", err -- } -- return imagePath, nil --} -- --func (d diskHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath preparePath) (string, error) { -- imagePath, err := download(req) -- if err != nil { -- return "", err -- } -- if err = checkSumMatch(imagePath, req.CheckSum); err != nil { -- return "", err -- } -- return imagePath, nil --} -- --func download(req *pb.UpdateRequest) (string, error) { -- resp, err := getImageURL(req) -- if err != nil { -- return "", err -- } -- defer resp.Body.Close() -- if resp.StatusCode != http.StatusOK { -- return "", fmt.Errorf("URL %s returns error %s", req.ImageUrl, resp.Status) -- } -- fs := syscall.Statfs_t{} -- if err = syscall.Statfs(PersistDir, &fs); err != nil { -- return "", err -- } -- if int64(fs.Bfree)*fs.Bsize < resp.ContentLength+buffer { // these data come from disk size, will not overflow -- return "", fmt.Errorf("space is not enough for downloaing") -- } -- -- out, err := os.Create(filepath.Join(PersistDir, "update.img")) -- if err != nil { -- return "", err -- } -- defer out.Close() -- err = os.Chmod(out.Name(), imgPermission) -- if err != nil { -- return "", err -- } -- logrus.Infoln("downloading to file " + out.Name()) -- if _, err = io.Copy(out, resp.Body); err != nil { -- if errRemove := os.Remove(out.Name()); errRemove != nil { -- logrus.Errorln("remove " + out.Name() + " error " + errRemove.Error()) -- } -- return "", err -- } -- return out.Name(), nil --} -- --func checkSumMatch(filePath, checkSum string) error { -- file, err := os.Open(filePath) -- if err != nil { -- return err -- } -- defer file.Close() -- hash := sha256.New() -- if _, err := io.Copy(hash, file); err != nil { -- return err -- } -- if calSum := hex.EncodeToString(hash.Sum(nil)); calSum != checkSum { -- defer os.Remove(filePath) -- return fmt.Errorf("checkSum %s mismatch to %s", calSum, checkSum) -- } -- return nil --} -- --func getImageURL(req *pb.UpdateRequest) (*http.Response, error) { -- imageURL := req.ImageUrl -- flagSafe := req.FlagSafe -- mTLS := req.MTLS -- caCert := req.Certs.CaCaert -- clientCert := req.Certs.ClientCert -- clientKey := req.Certs.ClientKey -- -- if !strings.HasPrefix(imageURL, "https://") { -- if !flagSafe { -- logrus.Errorln("this imageUrl is not safe") -- return &http.Response{}, fmt.Errorf("this imageUrl is not safe") -- } -- resp, err := http.Get(imageURL) -- if err != nil { -- return &http.Response{}, err -- } -- return resp, nil -- } else if mTLS { -- client, err := loadClientCerts(caCert, clientCert, clientKey) -- if err != nil { -- return &http.Response{}, err -- } -- resp, err := client.Get(imageURL) -- if err != nil { -- return &http.Response{}, err -- } -- return resp, nil -- } else { -- client, err := loadCaCerts(caCert) -- if err != nil { -- return &http.Response{}, err -- } -- resp, err := client.Get(imageURL) -- if err != nil { -- return &http.Response{}, err -- } -- return resp, nil -- } --} -- --func loadCaCerts(caCert string) (*http.Client, error) { -- pool := x509.NewCertPool() -- err := certExist(caCert) -- if err != nil { -- return &http.Client{}, err -- } -- ca, err := ioutil.ReadFile(getCertPath() + caCert) -- if err != nil { -- return &http.Client{}, fmt.Errorf("read the ca certificate error %s", err) -- } -- pool.AppendCertsFromPEM(ca) -- tr := &http.Transport{ -- TLSClientConfig: &tls.Config{ -- RootCAs: pool, -- }, -- } -- client := &http.Client{Transport: tr} -- return client, nil --} -- --func loadClientCerts(caCert, clientCert, clientKey string) (*http.Client, error) { -- pool := x509.NewCertPool() -- err := certExist(caCert) -- if err != nil { -- return &http.Client{}, err -- } -- ca, err := ioutil.ReadFile(getCertPath() + caCert) -- if err != nil { -- return &http.Client{}, err -- } -- pool.AppendCertsFromPEM(ca) -- err = certExist(clientCert) -- if err != nil { -- return &http.Client{}, err -- } -- err = certExist(clientKey) -- if err != nil { -- return &http.Client{}, err -- } -- cliCrt, err := tls.LoadX509KeyPair(getCertPath()+clientCert, getCertPath()+clientKey) -- if err != nil { -- return &http.Client{}, err -- } -- -- tr := &http.Transport{ -- TLSClientConfig: &tls.Config{ -- RootCAs: pool, -- Certificates: []tls.Certificate{cliCrt}, -- }, -- } -- -- client := &http.Client{Transport: tr} -- return client, nil --} -- --func certExist(certFile string) error { -- if certFile == "" { -- return fmt.Errorf("please provide the certificate") -- } -- _, err := os.Stat(getCertPath() + certFile) -- if err != nil { -- if os.IsNotExist(err) { -- return fmt.Errorf("certificate is not exist %s ", err) -- } -- return fmt.Errorf("certificate has an error %s", err) -- } -- return nil --} -diff --git a/cmd/agent/server/disk_image_test.go b/cmd/agent/server/disk_image_test.go -deleted file mode 100644 -index f970bd7..0000000 ---- a/cmd/agent/server/disk_image_test.go -+++ /dev/null -@@ -1,471 +0,0 @@ --/* -- * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 ( -- "crypto/rand" -- "crypto/rsa" -- "crypto/sha256" -- "crypto/x509" -- "crypto/x509/pkix" -- "encoding/hex" -- "encoding/pem" -- "fmt" -- "io" -- "io/fs" -- "math/big" -- "net/http" -- "os" -- "reflect" -- "strings" -- "syscall" -- "testing" -- "time" -- -- "github.com/agiledragon/gomonkey/v2" -- pb "openeuler.org/KubeOS/cmd/agent/api" --) -- --func Test_download(t *testing.T) { -- tmpDir := t.TempDir() -- tmpFileForDownload := tmpDir + "/tmpFileForDownload" -- tmpFile, err := os.Create(tmpFileForDownload) -- if err != nil { -- t.Errorf("open file error: %v", err) -- } -- defer tmpFile.Close() -- type args struct { -- req *pb.UpdateRequest -- } -- tests := []struct { -- name string -- args args -- want string -- wantErr bool -- }{ -- {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, -- }, -- } -- 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.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) -- return -- } -- if got != tt.want { -- t.Errorf("download() got = %v, want %v", got, tt.want) -- } -- }) -- } --} -- --func Test_checkSumMatch(t *testing.T) { -- tmpDir := t.TempDir() -- tmpFileForCheckSum := tmpDir + "/tmpFileForCheckSum" -- err := os.WriteFile(tmpFileForCheckSum, []byte("hello"), 0644) -- if err != nil { -- t.Errorf("open file error: %v", err) -- } -- type args struct { -- filePath string -- checkSum string -- } -- tests := []struct { -- name string -- args args -- wantErr bool -- }{ -- { -- name: "normal", -- args: args{filePath: tmpFileForCheckSum, checkSum: calculateChecksum("hello")}, -- wantErr: false, -- }, -- {name: "error", args: args{filePath: tmpFileForCheckSum, checkSum: "aaa"}, wantErr: true}, -- {name: "unfound error", args: args{filePath: "", checkSum: "aaa"}, wantErr: true}, -- } -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- if err := checkSumMatch(tt.args.filePath, tt.args.checkSum); (err != nil) != tt.wantErr { -- t.Errorf("checkSumMatch() error = %v, wantErr %v", err, tt.wantErr) -- } -- }) -- } --} -- --func Test_getImageURL(t *testing.T) { -- type args struct { -- req *pb.UpdateRequest -- } -- tests := []struct { -- name string -- args args -- want *http.Response -- wantErr bool -- }{ -- {name: "httpNotSafe", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "http://www.openeuler.abc/zh/", -- FlagSafe: false, -- MTLS: false, -- Certs: &pb.CertsInfo{}, -- }}, want: &http.Response{}, wantErr: true}, -- {name: "httpSuccess", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "http://www.openeuler.abc/zh/", -- FlagSafe: true, -- MTLS: false, -- Certs: &pb.CertsInfo{}, -- }}, want: &http.Response{StatusCode: http.StatusOK}, wantErr: false}, -- {name: "mTLSGetSuccess", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "https://www.openeuler.abc/zh/", -- FlagSafe: true, -- MTLS: true, -- Certs: &pb.CertsInfo{}, -- }}, want: &http.Response{StatusCode: http.StatusOK}, wantErr: false}, -- {name: "httpsGetSuccess", args: args{req: &pb.UpdateRequest{ -- ImageUrl: "https://www.openeuler.abc/zh/", -- FlagSafe: true, -- 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.ApplyFuncSeq(loadClientCerts, []gomonkey.OutputCell{ -- {Values: gomonkey.Params{&http.Client{}, nil}}, -- {Values: gomonkey.Params{&http.Client{}, fmt.Errorf("error")}}, -- }) -- defer patchLoadClientCerts.Reset() -- 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) { -- return &http.Response{StatusCode: http.StatusOK}, nil -- }) -- defer patchGet.Reset() -- patchClientGet := gomonkey.ApplyMethod(reflect.TypeOf(&http.Client{}), "Get", func(_ *http.Client, url string) (resp *http.Response, err error) { -- return &http.Response{StatusCode: http.StatusOK}, nil -- }) -- defer patchClientGet.Reset() -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- if tt.name == "httpSuccess" { -- patchGet := gomonkey.ApplyFuncReturn(http.Get, &http.Response{StatusCode: http.StatusOK}, nil) -- defer patchGet.Reset() -- } -- got, err := getImageURL(tt.args.req) -- if (err != nil) != tt.wantErr { -- t.Errorf("getImageURL() error = %v, wantErr %v", err, tt.wantErr) -- return -- } -- if !reflect.DeepEqual(got, tt.want) { -- t.Errorf("getImageURL() got = %v, want %v", got, tt.want) -- } -- }) -- } --} -- --func Test_loadCaCerts(t *testing.T) { -- tmpDir := t.TempDir() -- caPath := tmpDir + "/fake.crt" -- createFakeCertKey(caPath, "") -- type args struct { -- caCert string -- } -- tests := []struct { -- name string -- args args -- wantErr bool -- }{ -- { -- name: "normal", -- args: args{ -- caCert: caPath, -- }, -- wantErr: false, -- }, -- {name: "no cert", args: args{caCert: ""}, wantErr: true}, -- } -- patchGetCertPath := gomonkey.ApplyFuncReturn(getCertPath, "") -- defer patchGetCertPath.Reset() -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- got, err := loadCaCerts(tt.args.caCert) -- if (err != nil) != tt.wantErr { -- t.Errorf("loadCaCerts() error = %v, wantErr %v", err, tt.wantErr) -- return -- } -- if got == nil { -- t.Errorf("loadCaCerts() = %v", got) -- } -- }) -- } -- --} -- --func Test_loadClientCerts(t *testing.T) { -- tmpDir := t.TempDir() -- clientCertPath := tmpDir + "/fakeClientCert.crt" -- clientKeyPath := tmpDir + "/fakeClientKey.crt" -- createFakeCertKey(clientCertPath, clientKeyPath) -- type args struct { -- caCert string -- clientCert string -- clientKey string -- } -- tests := []struct { -- name string -- args args -- wantErr bool -- }{ -- { -- name: "normal", -- args: args{ -- caCert: clientCertPath, clientCert: clientCertPath, clientKey: clientKeyPath, -- }, -- wantErr: false, -- }, -- } -- patchGetCertPath := gomonkey.ApplyFuncReturn(getCertPath, "") -- defer patchGetCertPath.Reset() -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- got, err := loadClientCerts(tt.args.caCert, tt.args.clientCert, tt.args.clientKey) -- if (err != nil) != tt.wantErr { -- t.Errorf("loadClientCerts() error = %v, wantErr %v", err, tt.wantErr) -- return -- } -- if got == nil { -- t.Errorf("loadClientCerts() got = %v", got) -- } -- }) -- } --} -- --func Test_certExist(t *testing.T) { -- type args struct { -- certFile string -- } -- tests := []struct { -- name string -- args args -- wantErr bool -- }{ -- {name: "fileEmpty", args: args{certFile: ""}, wantErr: true}, -- {name: "fileNotExist", args: args{certFile: "bb.txt"}, wantErr: true}, -- {name: "unknow error", args: args{certFile: "cc.txt"}, wantErr: true}, -- } -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- var patchStat *gomonkey.Patches -- if tt.name == "unknow error" { -- patchStat = gomonkey.ApplyFunc(os.Stat, func(name string) (fs.FileInfo, error) { -- return fs.FileInfo(nil), fmt.Errorf("error") -- }) -- } -- if err := certExist(tt.args.certFile); (err != nil) != tt.wantErr { -- t.Errorf("certExist() error = %v, wantErr %v", err, tt.wantErr) -- } -- if tt.name == "unknow error" { -- patchStat.Reset() -- } -- }) -- } -- defer os.RemoveAll("/etc/KubeOS/") --} -- --func createFakeCertKey(certPath, keyPath string) { -- privateKey, _ := rsa.GenerateKey(rand.Reader, 2048) -- template := x509.Certificate{ -- SerialNumber: big.NewInt(1), -- Subject: pkix.Name{ -- CommonName: "Fake Client Certificate", -- }, -- NotBefore: time.Now(), -- NotAfter: time.Now().AddDate(1, 0, 0), -- KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, -- ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, -- BasicConstraintsValid: true, -- } -- certBytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) -- certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes}) -- keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) -- os.WriteFile(certPath, certPEM, 0644) -- if keyPath != "" { -- os.WriteFile(keyPath, keyPEM, 0644) -- } --} -- --func calculateChecksum(data string) string { -- hash := sha256.New() -- hash.Write([]byte(data)) -- return hex.EncodeToString(hash.Sum(nil)) --} -- --func Test_diskHandler_getRootfsArchive(t *testing.T) { -- type args struct { -- req *pb.UpdateRequest -- neededPath preparePath -- } -- tests := []struct { -- name string -- d diskHandler -- args args -- want string -- wantErr bool -- }{ -- { -- name: "normal", d: diskHandler{}, -- args: args{req: &pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/"}, neededPath: preparePath{}}, -- want: "/persist/update.img", -- wantErr: false, -- }, -- { -- name: "error", d: diskHandler{}, -- args: args{req: &pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/"}, neededPath: preparePath{}}, -- want: "", -- wantErr: true, -- }, -- } -- patchDownload := gomonkey.ApplyFuncSeq(download, []gomonkey.OutputCell{ -- {Values: gomonkey.Params{"/persist/update.img", nil}}, -- {Values: gomonkey.Params{"", fmt.Errorf("error")}}, -- }) -- defer patchDownload.Reset() -- patchCheckSumMatch := gomonkey.ApplyFuncReturn(checkSumMatch, nil) -- defer patchCheckSumMatch.Reset() -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- d := diskHandler{} -- got, err := d.getRootfsArchive(tt.args.req, tt.args.neededPath) -- if (err != nil) != tt.wantErr { -- t.Errorf("diskHandler.getRootfsArchive() error = %v, wantErr %v", err, tt.wantErr) -- return -- } -- if got != tt.want { -- t.Errorf("diskHandler.getRootfsArchive() = %v, want %v", got, tt.want) -- } -- }) -- } --} -- --func Test_diskHandler_downloadImage(t *testing.T) { -- type args struct { -- req *pb.UpdateRequest -- } -- tests := []struct { -- name string -- d diskHandler -- args args -- want string -- wantErr bool -- }{ -- {name: "normal", d: diskHandler{}, args: args{req: &pb.UpdateRequest{ImageUrl: "http://www.openeuler.org/zh/"}}, want: "/persist/update.img", wantErr: false}, -- } -- for _, tt := range tests { -- t.Run(tt.name, func(t *testing.T) { -- d := diskHandler{} -- patchGetRootfsArchive := gomonkey.ApplyPrivateMethod(reflect.TypeOf(d), "getRootfsArchive", func(_ *diskHandler, _ *pb.UpdateRequest, _ preparePath) (string, error) { -- return "/persist/update.img", nil -- }) -- got, err := d.downloadImage(tt.args.req) -- if (err != nil) != tt.wantErr { -- t.Errorf("diskHandler.downloadImage() error = %v, wantErr %v", err, tt.wantErr) -- return -- } -- if got != tt.want { -- t.Errorf("diskHandler.downloadImage() = %v, want %v", got, tt.want) -- } -- patchGetRootfsArchive.Reset() -- }) -- } --} -diff --git a/cmd/agent/server/docker_image.go b/cmd/agent/server/docker_image.go -deleted file mode 100644 -index 16bcea5..0000000 ---- a/cmd/agent/server/docker_image.go -+++ /dev/null -@@ -1,73 +0,0 @@ --/* -- * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 ( -- "github.com/sirupsen/logrus" -- -- pb "openeuler.org/KubeOS/cmd/agent/api" --) -- --type dockerImageHandler struct{} -- --func (d dockerImageHandler) downloadImage(req *pb.UpdateRequest) (string, error) { -- neededPath, err := prepareEnv() -- if err != nil { -- return "", err -- } -- if _, err = d.getRootfsArchive(req, neededPath); err != nil { -- return "", err -- } -- return createOSImage(neededPath) --} -- --func (d dockerImageHandler) getRootfsArchive(req *pb.UpdateRequest, neededPath preparePath) (string, error) { -- imageName := req.ContainerImage -- if err := isValidImageName(imageName); err != nil { -- return "", err -- } -- logrus.Infof("start pull %s", imageName) -- if err := runCommand("docker", "pull", imageName); err != nil { -- return "", err -- } -- if err := checkOCIImageDigestMatch("docker", imageName, req.CheckSum); err != nil { -- return "", err -- } -- containerName := "kubeos-temp" -- dockerPsCmd := "docker ps -a -f=name=" + containerName + "| awk 'NR==2' | awk '{print $1}'" -- existId, err := runCommandWithOut("bash", "-c", dockerPsCmd) -- if err != nil { -- return "", err -- } -- if existId != "" { -- logrus.Infoln("kubeos-temp container exist,start clean environment first") -- if err := runCommand("docker", "rm", existId); err != nil { -- return "", err -- } -- } -- logrus.Infof("start get rootfs") -- containerId, err := runCommandWithOut("docker", "create", "--name", containerName, imageName) -- if 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/docker_image_test.go b/cmd/agent/server/docker_image_test.go -deleted file mode 100644 -index 2dbf337..0000000 ---- a/cmd/agent/server/docker_image_test.go -+++ /dev/null -@@ -1,118 +0,0 @@ --/* -- * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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_dockerImageHandler_downloadImage(t *testing.T) { -- type args struct { -- req *pb.UpdateRequest -- } -- tests := []struct { -- name string -- d dockerImageHandler -- args args -- want string -- wantErr bool -- }{ -- { -- 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) { -- 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("dockerImageHandler.downloadImage() error = %v, wantErr %v", err, tt.wantErr) -- return -- } -- if got != tt.want { -- t.Errorf("dockerImageHandler.downloadImage() = %v, want %v", got, tt.want) -- } -- }) -- } -- 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/server.go b/cmd/agent/server/server.go -index f8cbb41..23ab1c6 100644 ---- a/cmd/agent/server/server.go -+++ b/cmd/agent/server/server.go -@@ -102,12 +102,8 @@ func (s *Server) update(req *pb.UpdateRequest) error { - action := req.ImageType - var handler imageDownload - switch action { -- case "docker": -- handler = dockerImageHandler{} - case "containerd": - handler = conImageHandler{} -- case "disk": -- handler = diskHandler{} - default: - return fmt.Errorf("image type %s cannot be recognized", action) - } -@@ -180,7 +176,3 @@ func (s *Server) reboot() error { - } - return syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART) - } -- --func getCertPath() string { -- return certPath --} -diff --git a/cmd/agent/server/server_test.go b/cmd/agent/server/server_test.go -index 15b6f5e..22ed38c 100644 ---- a/cmd/agent/server/server_test.go -+++ b/cmd/agent/server/server_test.go -@@ -87,10 +87,10 @@ func TestServerUpdate(t *testing.T) { - wantErr bool - }{ - {name: "error", fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, -- args: args{in0: context.Background(), req: &pb.UpdateRequest{Version: "test", Certs: &pb.CertsInfo{}}}, -+ args: args{in0: context.Background(), req: &pb.UpdateRequest{Version: "test"}}, - want: &pb.UpdateResponse{}, wantErr: true}, - {name: "success", fields: fields{UnimplementedOSServer: pb.UnimplementedOSServer{}, disableReboot: true}, -- args: args{in0: context.Background(), req: &pb.UpdateRequest{Version: "test", Certs: &pb.CertsInfo{}, ImageType: "containerd"}}, -+ args: args{in0: context.Background(), req: &pb.UpdateRequest{Version: "test", ImageType: "containerd"}}, - want: &pb.UpdateResponse{}, wantErr: false}, - } - patchRootfsDisks := gomonkey.ApplyFuncReturn(getRootfsDisks, "/dev/sda2", "/dev/sda3", nil) -@@ -197,22 +197,9 @@ func TestServerupdate(t *testing.T) { - args args - wantErr bool - }{ -- {name: "errortype", args: args{&pb.UpdateRequest{Certs: &pb.CertsInfo{}}}, wantErr: true}, -- -- {name: "errordisk", args: args{&pb.UpdateRequest{ -- ImageUrl: "http://w3.huawei.com/", -- FlagSafe: true, -- CheckSum: "", -- ImageType: "disk", -- Certs: &pb.CertsInfo{}, -- }}, -- wantErr: true}, -- {name: "errordocker", args: args{&pb.UpdateRequest{ -- ContainerImage: "", -- ImageType: "docker", -- Certs: &pb.CertsInfo{}, -- }}, -- wantErr: true}, -+ {name: "errortype", args: args{&pb.UpdateRequest{}}, wantErr: true}, -+ {name: "errordisk", args: args{&pb.UpdateRequest{CheckSum: "", ImageType: "disk"}}, wantErr: true}, -+ {name: "errordocker", args: args{&pb.UpdateRequest{ContainerImage: "", ImageType: "docker"}}, wantErr: true}, - } - for _, tt := range tests { - if tt.name == "errordisk" { -diff --git a/cmd/operator/controllers/os_controller_test.go b/cmd/operator/controllers/os_controller_test.go -index 6cc2760..66aa1a4 100644 ---- a/cmd/operator/controllers/os_controller_test.go -+++ b/cmd/operator/controllers/os_controller_test.go -@@ -242,8 +242,6 @@ var _ = Describe("OsController", func() { - OpsType: "rollback", - MaxUnavailable: 3, - OSVersion: "KubeOS v1", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v1", -@@ -420,8 +418,6 @@ var _ = Describe("OsController", func() { - OpsType: "config", - MaxUnavailable: 3, - OSVersion: "KubeOS v1", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v2", -@@ -512,8 +508,6 @@ var _ = Describe("OsController", func() { - OpsType: "upgrade", - MaxUnavailable: 3, - OSVersion: "KubeOS v2", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Configs: []upgradev1.SysConfig{}, -@@ -686,8 +680,6 @@ var _ = Describe("OsController", func() { - OpsType: "upgrade", - MaxUnavailable: 3, - OSVersion: "KubeOS v2", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v2", -diff --git a/cmd/proxy/controllers/os_controller.go b/cmd/proxy/controllers/os_controller.go -index b8d0f80..d7da343 100644 ---- a/cmd/proxy/controllers/os_controller.go -+++ b/cmd/proxy/controllers/os_controller.go -@@ -211,13 +211,7 @@ func (r *OSReconciler) upgradeNode(ctx context.Context, osCr *upgradev1.OS, node - case "upgrade": - version := osVersionSpec - downloadInfo := &agentclient.DownloadInfo{ -- ImageURL: osCr.Spec.ImageURL, -- FlagSafe: osCr.Spec.FlagSafe, - CheckSum: osCr.Spec.CheckSum, -- CaCert: osCr.Spec.CaCert, -- ClientCert: osCr.Spec.ClientCert, -- ClientKey: osCr.Spec.ClientKey, -- MTLS: osCr.Spec.MTLS, - ImageType: osCr.Spec.ImageType, - ContainerImage: osCr.Spec.ContainerImage, - } -diff --git a/cmd/proxy/controllers/os_controller_test.go b/cmd/proxy/controllers/os_controller_test.go -index 14b6b66..847f22e 100644 ---- a/cmd/proxy/controllers/os_controller_test.go -+++ b/cmd/proxy/controllers/os_controller_test.go -@@ -173,8 +173,6 @@ var _ = Describe("OsController", func() { - OpsType: "rollback", - MaxUnavailable: 3, - OSVersion: "KubeOS v1", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, - UpgradeConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, -@@ -333,8 +331,6 @@ var _ = Describe("OsController", func() { - OpsType: "config", - MaxUnavailable: 3, - OSVersion: "KubeOS v1", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v2", -@@ -476,8 +472,6 @@ var _ = Describe("OsController", func() { - OpsType: "upgrade", - MaxUnavailable: 3, - OSVersion: "KubeOS v2", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: false, - SysConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, - UpgradeConfigs: upgradev1.SysConfigs{ -@@ -564,8 +558,6 @@ var _ = Describe("OsController", func() { - OpsType: "config", - MaxUnavailable: 3, - OSVersion: "KubeOS v1", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v1", -@@ -709,8 +701,6 @@ var _ = Describe("OsController", func() { - OpsType: "config", - MaxUnavailable: 3, - OSVersion: "KubeOS v1", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v2", -@@ -875,8 +865,6 @@ var _ = Describe("OsController", func() { - OpsType: "upgrade", - MaxUnavailable: 3, - OSVersion: "KubeOS v2", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{Configs: []upgradev1.SysConfig{}}, - UpgradeConfigs: upgradev1.SysConfigs{ -@@ -1071,8 +1059,6 @@ var _ = Describe("OsController", func() { - OpsType: "upgrade", - MaxUnavailable: 3, - OSVersion: "KubeOS v2", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v2", -@@ -1232,8 +1218,6 @@ var _ = Describe("OsController", func() { - OpsType: "upgrade", - MaxUnavailable: 3, - OSVersion: "KubeOS v2", -- FlagSafe: true, -- MTLS: false, - EvictPodForce: true, - SysConfigs: upgradev1.SysConfigs{ - Version: "v2", -diff --git a/docs/example/config/crd/upgrade.openeuler.org_os.yaml b/docs/example/config/crd/upgrade.openeuler.org_os.yaml -index 3bb1333..8fadb2c 100644 ---- a/docs/example/config/crd/upgrade.openeuler.org_os.yaml -+++ b/docs/example/config/crd/upgrade.openeuler.org_os.yaml -@@ -32,28 +32,16 @@ spec: - spec: - description: OSSpec defines the desired state of OS - properties: -- cacert: -- type: string - checksum: - type: string -- clientcert: -- type: string -- clientkey: -- type: string - containerimage: - type: string - evictpodforce: - type: boolean -- flagSafe: -- type: boolean - imagetype: - type: string -- imageurl: -- type: string - maxunavailable: - type: integer -- mtls: -- type: boolean - opstype: - type: string - osversion: -@@ -118,11 +106,8 @@ spec: - - checksum - - containerimage - - evictpodforce -- - flagSafe - - imagetype -- - imageurl - - maxunavailable -- - mtls - - opstype - - osversion - type: object -diff --git a/pkg/agentclient/connection.go b/pkg/agentclient/connection.go -index 7b53a14..ad31da4 100644 ---- a/pkg/agentclient/connection.go -+++ b/pkg/agentclient/connection.go -@@ -32,13 +32,7 @@ type Client struct { - - // DownloadInfo contains the information required for image download - type DownloadInfo struct { -- ImageURL string -- FlagSafe bool - CheckSum string -- CaCert string -- ClientCert string -- ClientKey string -- MTLS bool - ImageType string - ContainerImage string - } -@@ -83,19 +77,10 @@ func New(sockAddr string) (*Client, error) { - - // UpdateSpec send update requests to the server in os-agent - func (c *Client) UpdateSpec(version string, downloadInfo *DownloadInfo) error { -- certs := &pb.CertsInfo{ -- CaCaert: downloadInfo.CaCert, -- ClientCert: downloadInfo.ClientCert, -- ClientKey: downloadInfo.ClientKey, -- } - _, err := c.client.Update(context.Background(), - &pb.UpdateRequest{ - Version: version, -- ImageUrl: downloadInfo.ImageURL, -- FlagSafe: downloadInfo.FlagSafe, - CheckSum: downloadInfo.CheckSum, -- MTLS: downloadInfo.MTLS, -- Certs: certs, - ImageType: downloadInfo.ImageType, - ContainerImage: downloadInfo.ContainerImage, - }) --- -2.39.0 - diff --git a/0022-KubeOS-delete-scripts-except-admin-container.patch b/0022-KubeOS-delete-scripts-except-admin-container.patch deleted file mode 100644 index 32faa4a1e6c987c1eb47948f77ba37dee1ea4444..0000000000000000000000000000000000000000 --- a/0022-KubeOS-delete-scripts-except-admin-container.patch +++ /dev/null @@ -1,1671 +0,0 @@ -From aaf7a75f0feacafcfcccd8c3812b1654694c26c0 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Mon, 28 Aug 2023 18:01:42 +0800 -Subject: [PATCH 5/5] KubeOS: delete scripts except admin container - -Signed-off-by: Yuhang Wei ---- - scripts/00bootup/Global.cfg | 16 -- - scripts/00bootup/module-setup.sh | 28 -- - scripts/00bootup/mount.sh | 341 ------------------------ - scripts/Dockerfile | 3 - - scripts/admin-container/Dockerfile | 28 -- - scripts/bootloader.sh | 42 --- - scripts/common/globalVariables.sh | 22 -- - scripts/common/log.sh | 20 -- - scripts/common/utils.sh | 191 -------------- - scripts/create/imageCreate.sh | 122 --------- - scripts/create/rootfsCreate.sh | 105 -------- - scripts/grub.cfg | 173 ------------- - scripts/kbimg.sh | 402 ----------------------------- - scripts/rpmlist | 22 -- - scripts/set_in_chroot.sh | 20 -- - 15 files changed, 1535 deletions(-) - delete mode 100644 scripts/00bootup/Global.cfg - delete mode 100644 scripts/00bootup/module-setup.sh - delete mode 100644 scripts/00bootup/mount.sh - delete mode 100644 scripts/Dockerfile - delete mode 100644 scripts/admin-container/Dockerfile - delete mode 100644 scripts/bootloader.sh - delete mode 100644 scripts/common/globalVariables.sh - delete mode 100644 scripts/common/log.sh - delete mode 100644 scripts/common/utils.sh - delete mode 100644 scripts/create/imageCreate.sh - delete mode 100644 scripts/create/rootfsCreate.sh - delete mode 100644 scripts/grub.cfg - delete mode 100644 scripts/kbimg.sh - delete mode 100644 scripts/rpmlist - delete mode 100644 scripts/set_in_chroot.sh - -diff --git a/scripts/00bootup/Global.cfg b/scripts/00bootup/Global.cfg -deleted file mode 100644 -index dd78617..0000000 ---- a/scripts/00bootup/Global.cfg -+++ /dev/null -@@ -1,16 +0,0 @@ --# rootfs file name --rootfs_name=kubeos.tar -- --# select the target disk to install kubeOS --disk=/dev/sda -- --# pxe server ip address where stores the rootfs on the http server --server_ip=192.168.1.50 --# target machine ip --local_ip=192.168.1.100 --# target machine route --route_ip=192.168.1.1 --# target machine netmask --netmask=255.255.255.0 --# target machine netDevice name --net_name=eth0 -diff --git a/scripts/00bootup/module-setup.sh b/scripts/00bootup/module-setup.sh -deleted file mode 100644 -index 5460b2b..0000000 ---- a/scripts/00bootup/module-setup.sh -+++ /dev/null -@@ -1,28 +0,0 @@ --#!/bin/bash -- --check() { -- return 0 --} -- --depends() { -- echo systemd --} -- --install() { -- inst_multiple -o grub2-mkimage mkfs.ext4 mkfs.vfat lsblk tar cpio gunzip lspci parted dhclient ifconfig curl hwinfo head tee arch df awk route -- inst_hook mount 00 "$moddir/mount.sh" -- inst_simple "$moddir/mount.sh" "/mount.sh" -- inst_simple "$moddir/Global.cfg" "/Global.cfg" --} -- --installkernel() { -- hostonly='' \ -- instmods \ -- =drivers/ata \ -- =drivers/nvme \ -- =drivers/scsi \ -- =drivers/net \ -- =fs/fat \ -- =fs/nls --} -- -diff --git a/scripts/00bootup/mount.sh b/scripts/00bootup/mount.sh -deleted file mode 100644 -index 7f00fd6..0000000 ---- a/scripts/00bootup/mount.sh -+++ /dev/null -@@ -1,341 +0,0 @@ --#!/bin/bash --arch=$(arch) --min_size=8 --log=/install.log -- --source /Global.cfg -- --function CheckSpace() { -- local disk_ava="$(parted -l | grep ${disk} | awk '{print $3}')" -- if echo "${disk_ava}" | grep [GT]B$; then -- if echo "${disk_ava}" | grep GB$; then -- disk_ava="$(echo ${disk_ava} | awk -F G '{print $1}' | awk -F . '{print $1}')" -- if [ "${disk_ava}" -lt ${min_size} ]; then -- echo "The available disk space is not enough, at least ${min_size}GB." | tee -a ${log} -- return 1 -- fi -- fi -- else -- echo "The available disk space is not enough, at least ${min_size}G." | tee -a ${log} -- return 1 -- fi -- -- return 0 --} -- --function mount_proc_dev_sys() { -- local tmp_root=$1 -- mount -t proc none "${tmp_root}/proc" -- mount --bind /dev "${tmp_root}/dev" -- mount --bind /dev/pts "${tmp_root}/dev/pts" -- mount -t sysfs none "${tmp_root}/sys" --} -- --function GetDisk() { -- disks=(`hwinfo --disk --short 2>&1 | grep -vi "^disk" | awk '{print $1}'`) -- if [ ${#disks[*]} -gt 0 ]; then -- if [ -n "${disk}" ] && echo "${disks[@]}" | grep -wq "${disk}" ; then -- echo "${disk} exists, start partition" | tee -a ${log} -- else -- echo "disk not exist, please choose correct disk" | tee -a ${log} -- fi -- else -- echo "no disk found" | tee -a ${log} -- return 1 -- fi -- CheckSpace -- if [ $? -ne 0 ]; then -- echo "no enough space on ${disk}" | tee -a ${log} -- return 1 -- fi -- -- return 0 --} -- --function PartitionAndFormatting() { -- echo "Partitioning and formatting disk $disk..." -- # partition and format -- parted ${disk} -s mklabel gpt >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "partition failed" | tee -a ${log} -- return 1 -- fi -- -- parted ${disk} -s mkpart primary fat16 1M 100M >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "partition failed" | tee -a ${log} -- return 1 -- fi -- -- parted ${disk} -s mkpart primary ext4 100M 2600M >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "partition failed" | tee -a ${log} -- return 1 -- fi -- -- parted ${disk} -s mkpart primary ext4 2600M 5100M >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "partition failed" | tee -a ${log} -- return 1 -- fi -- -- parted ${disk} -s mkpart primary ext4 5100M 100% >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "partition failed" | tee -a ${log} -- return 1 -- fi -- -- parted ${disk} -s set 1 boot on >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "partition failed" | tee -a ${log} -- return 1 -- fi -- -- mkfs.vfat -n "BOOT" ${disk}1 >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "format failed" | tee -a ${log} -- return 1 -- fi -- -- mkfs.ext4 -L "ROOT-A" ${disk}2 >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "format failed" | tee -a ${log} -- return 1 -- fi -- -- mkfs.ext4 -L "ROOT-B" ${disk}3 >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "format failed" | tee -a ${log} -- return 1 -- fi -- -- mkfs.ext4 -L "PERSIST" ${disk}4 >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "format failed" | tee -a ${log} -- return 1 -- fi -- -- return 0 --} -- --function InitNetwork() { -- echo "Initializing network..." -- netNames=(`ifconfig -a | awk '{print $1}' | grep : | grep '^e' | awk -F: '{print $1}'`) -- if [ ${#netNames[*]} -gt 0 ]; then -- if [ -n "${net_name}" ] && echo "${netNames[@]}" | grep -wq "${net_name}" ; then -- echo "${net_name} exists, start set ip" | tee -a ${log} -- else -- echo "net_name not exist, choose default net" | tee -a ${log} -- net_name=${netNames[0]} -- fi -- else -- echo "no net Device found" | tee -a ${log} -- return 1 -- fi -- -- ifconfig ${net_name} up -- if [ $? -ne 0 ]; then -- echo "load net card failed" | tee -a ${log} -- return 1 -- fi -- sleep 3 -- -- ifconfig ${net_name} ${local_ip} netmask ${netmask} >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "ip set failed" | tee -a ${log} -- return 1 -- fi -- sleep 3 -- -- route add default gw ${route_ip} >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "add route failed" | tee -a ${log} -- return 1 -- fi -- sleep 3 -- return 0 --} -- --function MountRoot() { -- echo "Mounting rootfs..." -- # mount rootfs -- mount ${disk}2 /sysroot >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "mount rootfs failed" | tee -a ${log} -- return 1 -- fi -- -- return 0 --} -- --function MountPersist() { -- echo "Mounting persist" -- mount ${disk}4 /sysroot/persist >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "mount persist failed" | tee -a ${log} -- return 1 -- fi -- mkdir /sysroot/persist/{var,etc,etcwork} -- mkdir -p /sysroot/persist/etc/KubeOS/certs -- return 0 --} -- --function MountBoot() { -- echo "Mounting boot" -- mkdir -p /sysroot/boot/efi -- mount ${disk}1 /sysroot/boot/efi >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "mount boot failed" | tee -a ${log} -- return 1 -- fi -- return 0 --} -- --function GetRootfs() { -- echo "Downloading rootfs..." -- -- curl -o /${rootfs_name} http://${server_ip}/${rootfs_name} -- if [ ! -e "/${rootfs_name}" ]; then -- echo "download rootfs failed" | tee -a ${log} -- return 1 -- fi -- -- tar -xf /${rootfs_name} -C /sysroot -- if [ $? -ne 0 ]; then -- echo "decompose rootfs failed" | tee -a ${log} -- return 1 -- fi -- -- rm -rf /${rootfs_name} -- mount -o remount,ro ${disk}2 /sysroot >> ${log} 2>&1 -- return 0 --} -- --function Inst_Grub2_x86() { -- # copy the files that boot need -- cp -r /sysroot/usr/lib/grub/x86_64-efi /sysroot/boot/efi/EFI/openEuler -- eval "grub2-mkimage -d /sysroot/usr/lib/grub/x86_64-efi -O x86_64-efi --output=/sysroot/boot/efi/EFI/openEuler/grubx64.efi '--prefix=(,gpt1)/EFI/openEuler' fat part_gpt part_msdos linux" >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "grub2-mkimage on x86 failed" | tee -a ${log} -- return 1 -- fi -- -- mkdir -p /sysroot/boot/efi/EFI/BOOT/ -- cp -f /sysroot/boot/efi/EFI/openEuler/grubx64.efi /sysroot/boot/efi/EFI/BOOT/BOOTX64.EFI -- -- return 0 --} -- --function Inst_Grub2_aarch64() { -- cp -r /sysroot/usr/lib/grub/arm64-efi /sysroot/boot/efi/EFI/openEuler/ -- eval "grub2-mkimage -d /sysroot/usr/lib/grub/arm64-efi -O arm64-efi --output=/sysroot/boot/efi/EFI/openEuler/grubaa64.efi '--prefix=(,gpt1)/EFI/openEuler' fat part_gpt part_msdos linux" >> ${log} 2>&1 -- if [ $? -ne 0 ]; then -- echo "grub2-mkimage on aarch64 failed" | tee -a ${log} -- return 1 -- fi -- -- mkdir -p /sysroot/boot/efi/EFI/BOOT/ -- cp -f /sysroot/boot/efi/EFI/openEuler/grubaa64.efi /sysroot/boot/efi/EFI/BOOT/BOOTAA64.EFI -- -- return 0 --} -- --function SetBoot() { -- # mount boot -- echo "Setting boot" -- -- if [ $arch == "x86_64" ]; then -- Inst_Grub2_x86 -- if [ $? -ne 0 ]; then -- echo "install grub on x86 failed" | tee -a ${log} -- return 1 -- fi -- fi -- -- if [ $arch == "aarch64" ]; then -- Inst_Grub2_aarch64 -- if [ $? -ne 0 ]; then -- echo "install grub on aarch64 failed" | tee -a ${log} -- return 1 -- fi -- fi -- sed -i 's#/dev/sda#'${disk}'#g' /sysroot/boot/efi/EFI/openEuler/grub.cfg -- -- return 0 --} -- --function Bootup_Main() { -- # get disk -- echo "Checking disk info..." | tee -a ${log} -- GetDisk -- if [ $? -ne 0 ]; then -- echo "Checking disk info failed" | tee -a ${log} -- return 1 -- fi -- -- # partition and format disk -- echo "Partion and formatting..." | tee -a ${log} -- PartitionAndFormatting -- if [ $? -ne 0 ]; then -- echo "Partition and formatting disk failed" | tee -a ${log} -- return 1 -- fi -- -- # init network -- echo "Initializing network..." | tee -a ${log} -- InitNetwork -- if [ $? -ne 0 ]; then -- echo "Initializing network failed" | tee -a ${log} -- return 1 -- fi -- -- # mount partitions -- -- # mount boot -- echo "Mounting root..." | tee -a ${log} -- MountRoot -- if [ $? -ne 0 ]; then -- echo "Mounting root failed" | tee -a ${log} -- return 1 -- fi -- -- echo "Mounting boot..." | tee -a ${log} -- MountBoot -- if [ $? -ne 0 ]; then -- echo "Mounting boot failed" | tee -a ${log} -- return 1 -- fi -- -- # download rootfs -- echo "Downloading rootfs..." | tee -a ${log} -- GetRootfs -- if [ $? -ne 0 ]; then -- echo "Downloading rootfs failed" | tee -a ${log} -- return 1 -- fi -- mount_proc_dev_sys /sysroot -- # set boot -- echo "Setting boot..." | tee -a ${log} -- SetBoot -- if [ $? -ne 0 ]; then -- echo "Setting boot failed" | tee -a ${log} -- return 1 -- fi -- # mount persist -- echo "Mounting persist..." | tee -a ${log} -- MountPersist -- if [ $? -ne 0 ]; then -- echo "Mounting persist failed" | tee -a ${log} -- return 1 -- fi -- return 0 --} -- --Bootup_Main --ret=$? --if [ ${ret} -eq 0 ]; then -- echo "kubeOS install success! switch to root" | tee -a ${log} -- cp ${log} /sysroot/persist --else -- echo "kubeOS install failed, see install.log" | tee -a ${log} --fi -diff --git a/scripts/Dockerfile b/scripts/Dockerfile -deleted file mode 100644 -index 3da4708..0000000 ---- a/scripts/Dockerfile -+++ /dev/null -@@ -1,3 +0,0 @@ --FROM scratch --COPY os.tar / --CMD ["/bin/sh"] -diff --git a/scripts/admin-container/Dockerfile b/scripts/admin-container/Dockerfile -deleted file mode 100644 -index d4ddd06..0000000 ---- a/scripts/admin-container/Dockerfile -+++ /dev/null -@@ -1,28 +0,0 @@ --## 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. -- --FROM openeuler-22.03-lts --MAINTAINER -- --RUN yum -y install openssh-clients util-linux -- -- --ADD ./sysmaster-0.2.3-1.oe2203.aarch64.rpm /home --RUN rpm -ivh /home/sysmaster-0.2.3-1.oe2203.aarch64.rpm -- --COPY ./hostshell /usr/bin/ --COPY ./set-ssh-pub-key.sh /usr/local/bin --COPY ./set-ssh-pub-key.service /usr/lib/sysmaster -- --EXPOSE 22 --# set sshd.service and set-ssh-pub-key.service pulled up by default --RUN sed -i 's/sysinit.target/sysinit.target;sshd.service;set-ssh-pub-key.service/g' /usr/lib/sysmaster/basic.target -- --CMD ["/usr/lib/sysmaster/init"] -diff --git a/scripts/bootloader.sh b/scripts/bootloader.sh -deleted file mode 100644 -index 75096a3..0000000 ---- a/scripts/bootloader.sh -+++ /dev/null -@@ -1,42 +0,0 @@ --#!/bin/bash --set -eu --set -o pipefail --set -x --ARCH=`arch` -- --function install_grub2_x86 () --{ -- if [ "$BOOT_MODE" = "legacy" ]; then -- # make boot.img/core.img and setup, to support legacy boot mode -- GRUBNAME=$(which grub2-install) -- echo "Installing GRUB2..." -- GRUB_OPTS=${GRUB_OPTS:-"--force"} -- GRUB_OPTS="$GRUB_OPTS --target=i386-pc" -- -- $GRUBNAME --modules="biosdisk part_msdos" $GRUB_OPTS $DEVICE -- else -- # make efi file, and save in FAT16 partition, to support UEFI boot mode -- cp -r /usr/lib/grub/x86_64-efi boot/efi/EFI/openEuler -- eval "grub2-mkimage -d /usr/lib/grub/x86_64-efi -O x86_64-efi --output=/boot/efi/EFI/openEuler/grubx64.efi '--prefix=(,gpt1)/EFI/openEuler' fat part_gpt part_msdos linux" -- -- mkdir -p /boot/EFI/BOOT/ -- cp -f /boot/efi/EFI/openEuler/grubx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI -- fi --} -- --function install_grub2_efi () --{ -- cp -r /usr/lib/grub/arm64-efi /boot/efi/EFI/openEuler/ -- eval "grub2-mkimage -d /usr/lib/grub/arm64-efi -O arm64-efi --output=/boot/efi/EFI/openEuler/grubaa64.efi '--prefix=(,gpt1)/EFI/openEuler' fat part_gpt part_msdos linux" -- -- mkdir -p /boot/EFI/BOOT/ -- cp -f /boot/efi/EFI/openEuler/grubaa64.efi /boot/efi/EFI/BOOT/BOOTAA64.EFI --} -- --if [ $ARCH == "x86_64" ]; then -- install_grub2_x86 --fi -- --if [ $ARCH == "aarch64" ]; then -- install_grub2_efi --fi -diff --git a/scripts/common/globalVariables.sh b/scripts/common/globalVariables.sh -deleted file mode 100644 -index 95af9c8..0000000 ---- a/scripts/common/globalVariables.sh -+++ /dev/null -@@ -1,22 +0,0 @@ --#!/bin/bash --## Copyright (c) Huawei Technologies Co., Ltd. 2022. 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. -- --IMG_SIZE=20 --PWD="$(pwd)" --TMP_MOUNT_PATH="${PWD}/mnt" --RPM_ROOT="${PWD}/rootfs" --ARCH=$(arch) -- --export IMG_SIZE --export PWD --export TMP_MOUNT_PATH --export RPM_ROOT --export ARCH -diff --git a/scripts/common/log.sh b/scripts/common/log.sh -deleted file mode 100644 -index 4d3ed2b..0000000 ---- a/scripts/common/log.sh -+++ /dev/null -@@ -1,20 +0,0 @@ --#!/bin/bash --## Copyright (c) Huawei Technologies Co., Ltd. 2022. 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. -- --function log_error_print(){ -- local logmsg="[ ERROR ] - ""`date "+%b %d %Y %H:%M:%S"`"" $1" -- echo $logmsg --} -- --function log_info_print(){ -- local logmsg="[ INFO ] - ""`date "+%b %d %Y %H:%M:%S"`"" $1" -- echo $logmsg --} -diff --git a/scripts/common/utils.sh b/scripts/common/utils.sh -deleted file mode 100644 -index ec244b7..0000000 ---- a/scripts/common/utils.sh -+++ /dev/null -@@ -1,191 +0,0 @@ --#!/bin/bash --## Copyright (c) Huawei Technologies Co., Ltd. 2022. 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. -- --CHECK_REGEX='\||;|&|&&|\|\||>|>>|<|,|#|!|\$' -- --function mount_proc_dev_sys() { -- local tmp_root=$1 -- mount -t proc none "${tmp_root}/proc" -- mount --bind /dev "${tmp_root}/dev" -- mount --bind /dev/pts "${tmp_root}/dev/pts" -- mount -t sysfs none "${tmp_root}/sys" --} -- --function unmount_dir() { -- local dir=$1 -- -- if [ -L "${dir}" ] || [ -f "${dir}" ]; then -- log_error_print "${dir} is not a directory, please check it." -- return 1 -- fi -- -- if [ ! -d "${dir}" ]; then -- return 0 -- fi -- -- local real_dir=$(readlink -e "${dir}") -- local mnts=$(awk '{print $2}' < /proc/mounts | grep "^${real_dir}" | sort -r) -- for m in ${mnts}; do -- log_info_print "Unmount ${m}" -- umount -f "${m}" || true -- done -- -- return 0 --} -- --function init_part() { -- local offset=$(fdisk -l system.img | grep $1 | awk '{print $2}') -- local sizelimit=$(fdisk -l system.img | grep $1 | awk '{print $3}') -- sizelimit=$(echo "($sizelimit - $offset)*512" | bc) -- offset=$(echo "${offset}*512" | bc) -- local loop=$(losetup -f) -- losetup -o "${offset}" --sizelimit "${sizelimit}" "${loop}" system.img -- if [ $2 == "BOOT" ];then -- mkfs.vfat -n "$2" "${loop}" -- mount -t vfat "${loop}" "$3" -- else -- mkfs.ext4 -L "$2" "${loop}" -- mount -t ext4 "${loop}" "$3" -- rm -rf "$3/lost+found" -- fi --} -- --function delete_dir() { -- local ret=0 -- local dir="$1" -- unmount_dir "${dir}" -- ret=$? -- if [ "${ret}" -eq 0 ]; then -- rm -rf "${dir}" -- return 0 -- else -- log_error_print "${dir} is failed to unmount , can not delete $dir." -- return 1 -- fi --} -- --function delete_file() { -- local file="$1" -- if [ ! -e "${file}" ]; then -- return 0 -- fi -- -- if [ ! -f "${file}" ]; then -- log_error_print "${file} is not a file." -- return 1 -- fi -- -- rm -f "${file}" -- return 0 --} -- --function check_file_valid() { -- local file="$1" -- local mesg="$2" -- if [ ! -e "${file}" ]; then -- log_error_print "${mesg} is not exist." -- exit 3 -- fi -- if [ ! -f "${file}" ];then -- log_error_print "${mesg} is not a file." -- exit 3 -- fi --} -- --function check_conf_valid() { -- local conf_path="${PWD}/00bootup/Global.cfg" -- check_file_valid ${conf_path} "Globab.cfg" -- if [ $# != 7 ];then -- log_error_print "configure configured in Global.cfg is empty." -- exit 3 -- fi -- for addr in ${server_ip} ${local_ip} ${route_ip} ${netmask}; do -- check_ip_valid $addr -- done --} -- --function check_ip_valid() { -- local ipaddr="$1"; -- if [[ ! $ipaddr =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] ; then -- log_error_print "ip address configured in Global.cfg is not valid." -- exit 3; -- fi -- for quad in $(echo "${ipaddr//./ }"); do -- if [ $quad -ge 0 ] && [ $quad -le 255 ];then -- continue -- fi -- log_error_print "ip address configured in Global.cfg is not valid." -- exit 3; -- done -- --} -- --function check_binary_exist() { -- check_file_valid "$1" "os-agent binary" --} -- --function check_repo_path() { -- check_file_valid $1 "REPO file" -- if [ -d "${RPM_ROOT}" ]; then -- log_error_print "there is a rootfs folder. please confirm if rootfs is being used, if not, please remove ${RPM_ROOT} first." -- exit 5 -- fi --} -- --function check_disk_space() { -- local disk_ava="$(df ${PWD} | awk 'NR==2{print}' | awk '{print $4}')" -- case $1 in -- docker) -- local maxsize=$((6*1024*1024)) -- if [ "${disk_ava}" -lt "${maxsize}" ]; then -- log_error_print "The available disk space is not enough, at least 6GiB." -- exit 6 -- fi -- ;; -- vm) -- local maxsize=$((25*1024*1024)) -- if [ "${disk_ava}" -lt "${maxsize}" ]; then -- log_error_print "The available disk space is not enough, at least 25GiB." -- exit 6 -- fi -- ;; -- pxe) -- local maxsize=$((5*1024*1024)) -- if [ "${disk_ava}" -lt "${maxsize}" ]; then -- log_error_print "The available disk space is not enough, at least 5GiB." -- exit 6 -- fi -- ;; -- esac --} -- --function check_param() { -- set +eE -- local arg=$1 -- echo "${arg}" | grep -v -E -q ${CHECK_REGEX} -- filterParam=$(echo "${arg}" | grep -v -E ${CHECK_REGEX}) -- if [[ "${filterParam}" != "${arg}" ]]; then -- log_error_print "params ${arg} is invalid, please check it." -- exit 3 -- fi -- set -eE --} -- --function check_docker_exist() { -- if [[ "$(docker images -q $1 2> /dev/null)" == "" ]]; then -- log_error_print "docker is not exist please pull $1 first " -- exit 9 -- fi --} -- --function check_docker_file() { -- check_file_valid $1 "admin-container Dockerfile" --} -\ No newline at end of file -diff --git a/scripts/create/imageCreate.sh b/scripts/create/imageCreate.sh -deleted file mode 100644 -index 4d02f9d..0000000 ---- a/scripts/create/imageCreate.sh -+++ /dev/null -@@ -1,122 +0,0 @@ --#!/bin/bash --## Copyright (c) Huawei Technologies Co., Ltd. 2022. 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. -- --TMP_MOUNT_PATH="${PWD}/mnt" --RPM_ROOT="${PWD}/rootfs" --IMG_SIZE=20 --PWD="$(pwd)" --function create_img() { -- local BOOT_MODE=$1 -- rm -f system.img update.img -- qemu-img create system.img ${IMG_SIZE}G -- if [ "$BOOT_MODE" = "legacy" ]; then -- local BOOT_PATH=${TMP_MOUNT_PATH}/boot/grub2 -- parted system.img -s mklabel msdos -- parted system.img -s mkpart primary ext4 1MiB 60MiB -- else -- local BOOT_PATH=${TMP_MOUNT_PATH}/boot/efi -- parted system.img -s mklabel gpt -- parted system.img -s mkpart primary fat32 1MiB 60MiB -- fi -- parted system.img -s mkpart primary ext4 60MiB 2160MiB -- parted system.img -s mkpart primary ext4 2160MiB 4260MiB -- parted system.img -s mkpart primary ext4 4260MiB 100% -- local device=$(losetup -f) -- losetup "${device}" system.img -- -- mkdir -p "${TMP_MOUNT_PATH}" -- -- init_part system.img2 ROOT-A "${TMP_MOUNT_PATH}" -- -- mkdir -p ${BOOT_PATH} -- chmod 755 ${BOOT_PATH} -- if [ "$BOOT_MODE" = "legacy" ]; then -- init_part system.img1 GRUB2 "${BOOT_PATH}" -- else -- init_part system.img1 BOOT "${BOOT_PATH}" -- fi -- tar -x -C ${TMP_MOUNT_PATH} -f os.tar -- if [ "$BOOT_MODE" = "legacy" ]; then -- sed -i "s/insmod part_gpt/insmod part_msdos/g; \ --s/set root='hd0,gpt2'/set root='hd0,msdos2'/g; \ --s/set root='hd0,gpt3'/set root='hd0,msdos3'/g" \ --"${TMP_MOUNT_PATH}"/boot/grub2/grub.cfg -- fi -- sync -- cp bootloader.sh "${TMP_MOUNT_PATH}" -- mount_proc_dev_sys "${TMP_MOUNT_PATH}" -- DEVICE="${device}" BOOT_MODE="${BOOT_MODE}" chroot "${TMP_MOUNT_PATH}" bash bootloader.sh -- rm -rf "${TMP_MOUNT_PATH}/bootloader.sh" -- sync -- -- dd if=/dev/disk/by-label/ROOT-A of=update.img bs=8M -- sync -- unmount_dir "${TMP_MOUNT_PATH}" -- init_part system.img3 ROOT-B "${TMP_MOUNT_PATH}" -- umount "${TMP_MOUNT_PATH}" -- -- init_part system.img4 PERSIST "${TMP_MOUNT_PATH}" -- mkdir ${TMP_MOUNT_PATH}/{var,etc,etcwork} -- mkdir -p ${TMP_MOUNT_PATH}/etc/KubeOS/certs -- umount "${TMP_MOUNT_PATH}" -- -- losetup -D -- parted system.img -- set 1 boot on -- qemu-img convert system.img -O qcow2 system.qcow2 --} -- --function create_pxe_img() { -- rm -rf initramfs.img kubeos.tar -- local opt=$1 -- shift -- case $opt in -- "repo") -- create_os_tar_from_repo "$@" -- ;; -- "docker") -- create_os_tar_from_docker "$@" -- ;; -- esac -- tar -xvf os.tar ./initramfs.img -- mv os.tar kubeos.tar --} -- --function create_docker_image() { -- local DOCKER_IMG="$6" -- create_os_tar_from_repo "$@" -- docker build -t ${DOCKER_IMG} -f ./Dockerfile . --} -- --function create_vm_img() { -- local opt=$1 -- shift -- local BOOT_MODE=$5 -- case $opt in -- "repo") -- create_os_tar_from_repo "$@" -- create_img "${BOOT_MODE}" -- ;; -- "docker") -- create_os_tar_from_docker "$@" -- create_img "${BOOT_MODE}" -- ;; -- esac -- --} -- --function create_admin_img() { -- local DOCKERFILE="$1" -- local DOCKER_IMG="$2" -- local ADMIN_CONTAINER_DIR="$3" -- cp ../bin/hostshell ${ADMIN_CONTAINER_DIR} -- docker build -t ${DOCKER_IMG} -f ${DOCKERFILE} ${ADMIN_CONTAINER_DIR} -- rm -rf ${ADMIN_CONTAINER_DIR}/hostshell --} -\ No newline at end of file -diff --git a/scripts/create/rootfsCreate.sh b/scripts/create/rootfsCreate.sh -deleted file mode 100644 -index 377cbf8..0000000 ---- a/scripts/create/rootfsCreate.sh -+++ /dev/null -@@ -1,105 +0,0 @@ --#!/bin/bash --## Copyright (c) Huawei Technologies Co., Ltd. 2022. 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. -- --function prepare_yum() { -- # init rpmdb -- local REPO=$1 -- rpm --root "${RPM_ROOT}" --initdb -- mkdir -p "${RPM_ROOT}"{/etc/yum.repos.d,/persist,/proc,/dev/pts,/sys} -- mount_proc_dev_sys "${RPM_ROOT}" -- # init yum repo -- local iso_repo="${RPM_ROOT}/etc/yum.repos.d/iso.repo" -- cat "${REPO}" > ${RPM_ROOT}/etc/yum.repos.d/iso.repo --} -- --function install_packages() { -- local REPO=$1 -- local BOOT_MODE=$2 -- prepare_yum ${REPO} -- -- echo "install package.." -- -- local filesize=$(stat -c "%s" ./rpmlist) -- local maxsize=$((1024*1024)) -- if [ "${filesize}" -gt "${maxsize}" ]; then -- echo "please check if rpmlist is too big or something wrong" -- exit 7 -- fi -- -- local rpms=$(cat ./rpmlist | tr "\n" " ") -- if [ "${ARCH}" == "x86_64" ]; then -- if [ "${BOOT_MODE}" = "legacy" ]; then -- rpms+=" grub2" -- else -- rpms+=" grub2-efi grub2-tools grub2-efi-x64-modules grub2-pc-modules" -- fi -- yum -y --installroot="${RPM_ROOT}" install --nogpgcheck --setopt install_weak_deps=False ${rpms} -- elif [ "${ARCH}" == "aarch64" ]; then -- yum -y --installroot="${RPM_ROOT}" install --nogpgcheck --setopt install_weak_deps=False ${rpms} grub2-efi grub2-tools grub2-efi-aa64-modules -- fi -- yum -y --installroot="${RPM_ROOT}" clean all --} -- --function install_misc() { -- local VERSION=$1 -- local AGENT_PATH=$2 -- local PASSWD=$3 -- local BOOT_MODE=$4 -- local DNS_CONF="${PWD}/resolv.conf" -- cp ../files/*mount ../files/os-agent.service "${RPM_ROOT}/usr/lib/systemd/system/" -- cp ../files/os-release "${RPM_ROOT}/usr/lib/" -- cp "${AGENT_PATH}" "${RPM_ROOT}/usr/bin" -- rm "${RPM_ROOT}/etc/os-release" -- -- cat < "${RPM_ROOT}/usr/lib/os-release" --NAME=${NAME} --ID=${NAME} --EOF -- echo "PRETTY_NAME=\"${NAME} ${VERSION}\"" >> "${RPM_ROOT}/usr/lib/os-release" -- echo "VERSION_ID=${VERSION}" >> "${RPM_ROOT}/usr/lib/os-release" -- mv "${RPM_ROOT}"/boot/vmlinuz* "${RPM_ROOT}/boot/vmlinuz" -- mv "${RPM_ROOT}"/boot/initramfs* "${RPM_ROOT}/boot/initramfs.img" -- if [ "$BOOT_MODE" = "legacy" ]; then -- cp grub.cfg "${RPM_ROOT}"/boot/grub2 -- sed -i "s/insmod part_gpt/insmod part_msdos/g; \ --s/set root='hd0,gpt2'/set root='hd0,msdos2'/g; \ --s/set root='hd0,gpt3'/set root='hd0,msdos3'/g" \ --"${RPM_ROOT}"/boot/grub2/grub.cfg -- else -- cp grub.cfg "${RPM_ROOT}"/boot/efi/EFI/openEuler -- fi -- cp -r ./00bootup ${RPM_ROOT}/usr/lib/dracut/modules.d/ -- cp set_in_chroot.sh "${RPM_ROOT}" -- ROOT_PWD="${PASSWD}" BOOT_MODE="${BOOT_MODE}" chroot "${RPM_ROOT}" bash /set_in_chroot.sh -- rm "${RPM_ROOT}/set_in_chroot.sh" -- if [ -e "${DNS_CONF}" ]; then -- cp "${DNS_CONF}" "${RPM_ROOT}/etc/resolv.conf" -- fi --} -- --function create_os_tar_from_repo() { -- local REPO=$1 -- local VERSION=$2 -- local AGENT_PATH=$3 -- local PASSWD=$4 -- local BOOT_MODE=$5 -- install_packages ${REPO} ${BOOT_MODE} -- install_misc ${VERSION} ${AGENT_PATH} ${PASSWD} ${BOOT_MODE} -- unmount_dir "${RPM_ROOT}" -- tar -C "$RPM_ROOT" -cf ./os.tar . --} --function create_os_tar_from_docker() { -- local DOCKER_IMG=$1 -- container_id=$(docker create ${DOCKER_IMG}) -- echo "$container_id" -- docker cp $container_id:/os.tar ./ -- docker rm $container_id --} -diff --git a/scripts/grub.cfg b/scripts/grub.cfg -deleted file mode 100644 -index 984b161..0000000 ---- a/scripts/grub.cfg -+++ /dev/null -@@ -1,173 +0,0 @@ --## Copyright (c) Huawei Technologies Co., Ltd. 2021. 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. --set pager=1 -- --if [ -f ${config_directory}/grubenv ]; then -- load_env -f ${config_directory}/grubenv --elif [ -s $prefix/grubenv ]; then -- load_env --fi --if [ "${next_entry}" ] ; then -- set default="${next_entry}" -- set next_entry= -- save_env next_entry -- set boot_once=true --else -- set default="${saved_entry}" --fi -- --if [ x"${feature_menuentry_id}" = xy ]; then -- menuentry_id_option="--id" --else -- menuentry_id_option="" --fi -- --export menuentry_id_option -- --if [ "${prev_saved_entry}" ]; then -- set saved_entry="${prev_saved_entry}" -- save_env saved_entry -- set prev_saved_entry= -- save_env prev_saved_entry -- set boot_once=true --fi -- --function savedefault { -- if [ -z "${boot_once}" ]; then -- saved_entry="${chosen}" -- save_env saved_entry -- fi --} -- --function load_video { -- if [ x$feature_all_video_module = xy ]; then -- insmod all_video -- else -- insmod efi_gop -- insmod efi_uga -- insmod ieee1275_fb -- insmod vbe -- insmod vga -- insmod video_bochs -- insmod video_cirrus -- fi --} -- --terminal_output console --if [ x$feature_timeout_style = xy ] ; then -- set timeout_style=menu -- set timeout=5 --# Fallback normal timeout code in case the timeout_style feature is --# unavailable. --else -- set timeout=5 --fi --set superusers="root" --### END /etc/grub.d/00_header ### -- --### BEGIN /etc/grub.d/01_users ### --if [ -f ${prefix}/user.cfg ]; then -- source ${prefix}/user.cfg -- if [ -n "${GRUB2_PASSWORD}" ]; then -- set superusers="root" -- export superusers -- password_pbkdf2 root ${GRUB2_PASSWORD} -- fi --fi --### END /etc/grub.d/01_users ### -- --### BEGIN /etc/grub.d/10_linux ### --menuentry 'A' --class KubeOS --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'KubeOS-A' { -- load_video -- set gfxpayload=keep -- insmod gzio -- insmod part_gpt -- insmod ext2 -- set root='hd0,gpt2' -- linux /boot/vmlinuz root=/dev/sda2 ro rootfstype=ext4 nomodeset quiet oops=panic softlockup_panic=1 nmi_watchdog=1 rd.shell=0 selinux=0 crashkernel=256M panic=3 -- initrd /boot/initramfs.img --} -- --menuentry 'B' --class KubeOS --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'KubeOS-B' { -- load_video -- set gfxpayload=keep -- insmod gzio -- insmod part_gpt -- insmod ext2 -- set root='hd0,gpt3' -- linux /boot/vmlinuz root=/dev/sda3 ro rootfstype=ext4 nomodeset quiet oops=panic softlockup_panic=1 nmi_watchdog=1 rd.shell=0 selinux=0 crashkernel=256M panic=3 -- initrd /boot/initramfs.img --} -- --### END /etc/grub.d/10_linux ### -- --### BEGIN /etc/grub.d/10_reset_boot_success ### --# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry --if [ "${boot_success}" = "1" -o "${boot_indeterminate}" = "1" ]; then -- set menu_hide_ok=1 --else -- set menu_hide_ok=0 --fi --# Reset boot_indeterminate after a successful boot --if [ "${boot_success}" = "1" ] ; then -- set boot_indeterminate=0 --# Avoid boot_indeterminate causing the menu to be hidden more then once --elif [ "${boot_indeterminate}" = "1" ]; then -- set boot_indeterminate=2 --fi --# Reset boot_success for current boot --set boot_success=0 --save_env boot_success boot_indeterminate --### END /etc/grub.d/10_reset_boot_success ### -- --### BEGIN /etc/grub.d/12_menu_auto_hide ### --if [ x$feature_timeout_style = xy ] ; then -- if [ "${menu_show_once}" ]; then -- unset menu_show_once -- save_env menu_show_once -- set timeout_style=menu -- set timeout=60 -- elif [ "${menu_auto_hide}" -a "${menu_hide_ok}" = "1" ]; then -- set orig_timeout_style=${timeout_style} -- set orig_timeout=${timeout} -- if [ "${fastboot}" = "1" ]; then -- # timeout_style=menu + timeout=0 avoids the countdown code keypress check -- set timeout_style=menu -- set timeout=0 -- else -- set timeout_style=hidden -- set timeout=1 -- fi -- fi --fi --### END /etc/grub.d/12_menu_auto_hide ### -- --### BEGIN /etc/grub.d/20_linux_xen ### --### END /etc/grub.d/20_linux_xen ### -- --### BEGIN /etc/grub.d/20_ppc_terminfo ### --### END /etc/grub.d/20_ppc_terminfo ### -- --### BEGIN /etc/grub.d/30_uefi-firmware ### --### END /etc/grub.d/30_uefi-firmware ### -- --### BEGIN /etc/grub.d/40_custom ### --# This file provides an easy way to add custom menu entries. Simply type the --# menu entries you want to add after this comment. Be careful not to change --# the 'exec tail' line above. --### END /etc/grub.d/40_custom ### -- --### BEGIN /etc/grub.d/41_custom ### --if [ -f ${config_directory}/custom.cfg ]; then -- source ${config_directory}/custom.cfg --elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then -- source $prefix/custom.cfg; --fi --### END /etc/grub.d/41_custom ### -diff --git a/scripts/kbimg.sh b/scripts/kbimg.sh -deleted file mode 100644 -index 0f75f0d..0000000 ---- a/scripts/kbimg.sh -+++ /dev/null -@@ -1,402 +0,0 @@ --#!/bin/bash --## Copyright (c) Huawei Technologies Co., Ltd. 2022. 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. -- --set -e -- --NAME=KubeOS --REPO="" --VERSION="" --AGENT_PATH="" --PASSWD="" --DOCKER_IMG="" --DOCKERFILE="" --LOCK=./test.lock --ADMIN_CONTAINER_DIR=./admin-container --BOOT_MODE=efi -- --source common/globalVariables.sh &>/dev/null --source common/log.sh &>/dev/null --source common/utils.sh &>/dev/null --source create/rootfsCreate.sh &>/dev/null --source create/imageCreate.sh &>/dev/null --source 00bootup/Global.cfg &>/dev/null -- --function show_options() { -- cat << EOF -- --Usage : sh kbimg [COMMAND] [OPTIONS] -- --kbimg is a tool used to handle KubeOS image , like create KubeOS images -- --Commands: -- create create KubeOS images --Options: -- -h,--help show help information -- --Run 'kbimg COMMAND --help' for more information on a command. --EOF --} -- --function show_create_usage() { -- cat << EOF -- --Usage : kbimg create [COMMAND] [OPTIONS] -- --commands: -- upgrade-image create KubeOS OCI image used for installation and upgrade -- vm-image create KubeOS virtual machine image -- pxe-image create images required for KubeOS PXE installation on physical machines -- admin-image create KubeOS admin container OCI image used for debug of worker nodes in clusters --options: -- -h,--help show help information -- --Run 'kbimg create COMMAND --help' for more information on a command. --EOF --} -- --function show_upgrade_image_usage() { -- cat << EOF -- --Usage : kbimg create upgrade-image -p isopath -v osversion -b osagentdir -e ospassword -d repository/name:tag -- --options: -- -p repo path -- -v KubeOS version -- -b directory of os-agent binary -- -e os encrypted password -- -d docker image like repository/name:tag -- -l boot to legacy BIOS mode, if not specify, then UEFI mode -- -h,--help show help information --EOF --} -- --function show_vm_pxe_image_usage() { -- cat << EOF -- --Usage : kbimg create [vm-image|pxe-image] -p iso-path -v os-version -b os-agent-dir -e os-password -- or -- kbimg create [vm-image|pxe-image] -d repository/name:tag -- --options: -- -p repo path -- -v KubeOS version -- -b directory of os-agent binary -- -e os encrypted password -- -d docker image like repository/name:tag -- -l boot to legacy BIOS mode, if not specify, then UEFI mode -- -h,--help show help information --EOF --} -- --function show_admin_image_usage() { -- cat << EOF -- --Usage : kbimg create admin-image -f dockerfile-path -d repository/name:tag -- --options: -- -f Dockerfile path -- -d admin container image like repository/name:tag -- -h,--help show help information --EOF --} -- --function file_lock() { -- local lock_file=$1 -- exec {lock_fd}>"${lock_file}" -- flock -xn "${lock_fd}" --} -- --function test_lock() { -- file_lock "${LOCK}" -- if [ $? -ne 0 ]; then -- log_error_print "There is already an generate process running." -- exit 203 -- fi --} -- --function clean_space() { -- delete_dir "${RPM_ROOT}" -- delete_dir "${TMP_MOUNT_PATH}" -- delete_file os.tar -- rm -rf "${LOCK}" -- delete_file ${ADMIN_CONTAINER_DIR}/hostshell --} -- --function clean_img() { -- delete_file system.img -- delete_file update.img -- delete_file initramfs.img -- delete_file kubeos.tar --} -- --function verify_upgrade_image_input() { -- set +eE -- for i in "p" "v" "b" "e" "d" -- do -- echo "$@" | grep -q "\-$i " -- if [ "$?" -ne 0 ];then -- log_error_print "option -$i is mandatory, please check input" -- show_upgrade_image_usage -- exit 3 -- fi -- done -- set -eE -- while getopts "p:v:e:b:d:l" opt -- do -- case $opt in -- p) -- check_param $OPTARG -- REPO="$OPTARG" -- ;; -- v) -- check_param $OPTARG -- VERSION="$OPTARG" -- ;; -- b) -- check_param $OPTARG -- AGENT_PATH="$OPTARG" -- ;; -- e) -- # encrypted password contains special characters.,not verify. -- PASSWD="$OPTARG" -- ;; -- d) -- check_param $OPTARG -- DOCKER_IMG="$OPTARG" -- ;; -- l) -- BOOT_MODE=legacy -- ;; -- *) -- log_error_print "option $opt not found" -- show_upgrade_image_usage -- exit 3 -- ;; -- esac -- done --} -- --function verify_repo_input() { -- set +eE -- for i in "p" "v" "b" "e" -- do -- echo "$@" | grep -q "\-$i " -- if [ "$?" -ne 0 ];then -- log_error_print "option -$i is mandatory, please check input" -- show_vm_pxe_image_usage -- exit 3 -- fi -- done -- set -eE -- while getopts "p:v:e:b:l" opt -- do -- case $opt in -- p) -- check_param $OPTARG -- REPO="$OPTARG" -- ;; -- v) -- check_param $OPTARG -- VERSION="$OPTARG" -- ;; -- b) -- check_param $OPTARG -- AGENT_PATH="$OPTARG" -- ;; -- e) -- # encrypted password contains special characters.,not verify. -- PASSWD="$OPTARG" -- ;; -- l) -- BOOT_MODE=legacy -- ;; -- *) -- log_error_print "option $opt not found" -- show_vm_pxe_image_usage -- exit 3 -- ;; -- esac -- done --} -- --function verify_docker_input() { -- if [ $1 != "-d" ]; then -- log_error_print "option $1 not found" -- show_vm_pxe_image_usage -- exit 3 -- fi -- check_param $2 -- DOCKER_IMG=$2 --} -- --function verify_admin_input() { -- set +eE -- for i in "f" "d" -- do -- echo "$@" | grep -q "\-$i " -- if [ "$?" -ne 0 ];then -- log_error_print "option -$i is mandatory, please check input" -- show_admin_image_usage -- exit 3 -- fi -- done -- set -eE -- while getopts "f:d:" opt -- do -- case $opt in -- f) -- check_param $OPTARG -- DOCKERFILE="$OPTARG" -- ;; -- d) -- check_param $OPTARG -- DOCKER_IMG="$OPTARG" -- ;; -- *) -- log_error_print "option $opt not found" -- show_admin_image_usage -- exit 3 -- ;; -- esac -- done --} -- --function verify_create_input() { -- local ret= -- local cmd=$1 -- case $1 in -- "upgrade-image") -- shift -- if [ $# -eq 1 ]; then -- if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then -- show_upgrade_image_usage -- exit 0 -- fi -- fi -- if [[ $# -ne 10 && $# -ne 11 ]]; then -- log_error_print "the number of parameters is incorrect, please check it." -- show_upgrade_image_usage -- exit 3 -- fi -- check_disk_space "docker" -- verify_upgrade_image_input "$@" -- check_repo_path "${REPO}" -- check_binary_exist "${AGENT_PATH}" -- create_docker_image "${REPO}" "${VERSION}" "${AGENT_PATH}" "${PASSWD}" "${BOOT_MODE}" "${DOCKER_IMG}" -- ;; -- "vm-image") -- shift -- if [ $# -eq 1 ]; then -- if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then -- show_vm_pxe_image_usage -- exit 0 -- fi -- fi -- check_disk_space "vm" -- if [[ $# -eq 8 || $# -eq 9 ]]; then -- verify_repo_input "$@" -- check_repo_path "${REPO}" -- check_binary_exist "${AGENT_PATH}" -- create_vm_img "repo" "${REPO}" "${VERSION}" "${AGENT_PATH}" "${PASSWD}" "${BOOT_MODE}" -- elif [ $# -eq 2 ]; then -- verify_docker_input "$@" -- check_docker_exist "${DOCKER_IMG}" -- create_vm_img "docker" "${DOCKER_IMG}" -- else -- log_error_print "the number of parameters is incorrect, please check it." -- show_vm_pxe_image_usage -- exit 3 -- fi -- ;; -- "pxe-image") -- shift -- if [ $# -eq 1 ]; then -- if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then -- show_vm_pxe_image_usage -- exit 0 -- fi -- fi -- check_disk_space "pxe" -- check_conf_valid ${rootfs_name} ${disk} ${server_ip} ${local_ip} ${route_ip} ${netmask} ${net_name} -- if [ $# -eq 8 ]; then -- verify_repo_input "$@" -- check_repo_path "${REPO}" -- check_binary_exist "${AGENT_PATH}" -- create_pxe_img "repo" "${REPO}" "${VERSION}" "${AGENT_PATH}" "${PASSWD}" -- elif [ $# -eq 2 ]; then -- verify_docker_input "$@" -- check_docker_exist "${DOCKER_IMG}" -- create_pxe_img "docker" "${DOCKER_IMG}" -- else -- log_error_print "the number of parameters is incorrect, please check it." -- show_vm_pxe_image_usage -- exit 3 -- fi -- ;; -- "admin-image") -- shift -- if [ $# -eq 1 ]; then -- if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then -- show_admin_image_usage -- exit 0 -- fi -- fi -- if [ $# -ne 4 ]; then -- log_error_print "the number of parameters is incorrect, please check it." -- show_admin_image_usage -- exit 3 -- fi -- verify_admin_input "$@" -- check_docker_file "${DOCKERFILE}" -- create_admin_img "${DOCKERFILE}" "${DOCKER_IMG}" "${ADMIN_CONTAINER_DIR}" -- ;; -- "-h"|"--help") -- show_create_usage -- ;; -- *) -- log_error_print "error command $1 not found" -- show_create_usage -- exit 3 -- esac --} -- --function kubeos_image_main() { -- local ret= -- local cmd=$1 -- if [ "$#" -eq 1 ]; then -- case $1 in -- -h|--help) -- show_options -- exit 0;; -- *) -- log_error_print "params is invalid,please check it." -- show_options -- exit 3;; -- esac -- fi -- case $cmd in -- create) -- shift -- verify_create_input "$@" -- ;; -- *) -- log_error_print "command $1 not found" -- show_options -- exit 3 -- ;; -- esac --} -- --test_lock --trap clean_space EXIT --trap clean_img ERR -- --kubeos_image_main "$@" -diff --git a/scripts/rpmlist b/scripts/rpmlist -deleted file mode 100644 -index fb6f238..0000000 ---- a/scripts/rpmlist -+++ /dev/null -@@ -1,22 +0,0 @@ --kernel --passwd --dhcp --NetworkManager --openssh-server --docker --kubernetes-kubeadm --kubernetes-kubelet --containernetworking-plugins --socat --conntrack-tools --ebtables --ethtool --rsyslog --vi --net-tools --hwinfo --dracut --coreutils --gawk --parted --dosfstools -\ No newline at end of file -diff --git a/scripts/set_in_chroot.sh b/scripts/set_in_chroot.sh -deleted file mode 100644 -index 80b5a91..0000000 ---- a/scripts/set_in_chroot.sh -+++ /dev/null -@@ -1,20 +0,0 @@ --#!/bin/bash --ln -s /usr/lib/systemd/system/os-agent.service /usr/lib/systemd/system/multi-user.target.wants/os-agent.service --ln -s /usr/lib/systemd/system/kubelet.service /usr/lib/systemd/system/multi-user.target.wants/kubelet.service --if [ "$BOOT_MODE" = "legacy" ]; then -- ln -s /usr/lib/systemd/system/boot-grub2.mount /lib/systemd/system/local-fs.target.wants/boot-grub2.mount --else -- ln -s /usr/lib/systemd/system/boot-efi.mount /lib/systemd/system/local-fs.target.wants/boot-efi.mount --fi --ln -s /usr/lib/systemd/system/etc.mount /lib/systemd/system/local-fs.target.wants/etc.mount -- --str=`sed -n '/^root:/p' /etc/shadow | awk -F "root:" '{print $2}'` --umask 0666 --mv /etc/shadow /etc/shadow_bak --sed -i '/^root:/d' /etc/shadow_bak --echo "root:"${ROOT_PWD}${str:1} > /etc/shadow --cat /etc/shadow_bak >> /etc/shadow --rm -rf /etc/shadow_bak -- --dracut -f -v --add bootup /initramfs.img --kver `ls /lib/modules` --rm -rf /usr/lib/dracut/modules.d/00bootup -\ No newline at end of file --- -2.39.0 - diff --git a/0023-KubeOS-fix-proxy-upgrade-requeue-bug.patch b/0023-KubeOS-fix-proxy-upgrade-requeue-bug.patch deleted file mode 100644 index ae72d14cb5877788499cd6b7b765976b5296e6ac..0000000000000000000000000000000000000000 --- a/0023-KubeOS-fix-proxy-upgrade-requeue-bug.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 9a92903712509e32b9ea84f97e35c50b2152389d Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Tue, 5 Sep 2023 12:38:18 +0800 -Subject: [PATCH 1/3] KubeOS: fix proxy upgrade requeue bug - -fix the bug that proxy doesnt forget ratelimit after updating config - -Signed-off-by: Yuhang Wei ---- - cmd/proxy/controllers/os_controller.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/cmd/proxy/controllers/os_controller.go b/cmd/proxy/controllers/os_controller.go -index d7da343..1153419 100644 ---- a/cmd/proxy/controllers/os_controller.go -+++ b/cmd/proxy/controllers/os_controller.go -@@ -101,7 +101,7 @@ func (r *OSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re - if err = r.Update(ctx, osInstance); err != nil { - return values.RequeueNow, err - } -- return values.RequeueNow, nil -+ return values.Requeue, nil - } - if err := r.setConfig(ctx, osInstance, values.SysConfigName); err != nil { - return values.RequeueNow, err --- -2.34.1 - diff --git a/0024-KubeOS-fix-label-changed-after-upgrade.patch b/0024-KubeOS-fix-label-changed-after-upgrade.patch deleted file mode 100644 index 6003b1d74e100c1f37459e26db1de2c53798ffdd..0000000000000000000000000000000000000000 --- a/0024-KubeOS-fix-label-changed-after-upgrade.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 5fce81aeda6498425772d3af2bfa858ba8923140 Mon Sep 17 00:00:00 2001 -From: Yuhang Wei -Date: Tue, 5 Sep 2023 17:01:41 +0800 -Subject: [PATCH 2/3] KubeOS: fix label changed after upgrade - -When upgrading, the label of the new root partition are changed to the original disk information - -Signed-off-by: Yuhang Wei ---- - cmd/agent/server/utils.go | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/cmd/agent/server/utils.go b/cmd/agent/server/utils.go -index d2d0946..b4a19ff 100644 ---- a/cmd/agent/server/utils.go -+++ b/cmd/agent/server/utils.go -@@ -75,6 +75,9 @@ func deleteNewline(out string) string { - } - - func install(imagePath string, side string, next string) error { -+ if err := modifyImageLabel(imagePath, side, next); err != nil { -+ return err -+ } - if err := runCommand("dd", "if="+imagePath, "of="+side, "bs=8M"); err != nil { - return err - } -@@ -370,3 +373,10 @@ func getOCIImageDigest(containerRuntime string, imageName string) (string, error - } - return imageDigests, nil - } -+ -+func modifyImageLabel(imagePath, side, next string) error { -+ if err := runCommand("e2label", imagePath, "ROOT-"+next); err != nil { -+ return err -+ } -+ return nil -+} --- -2.34.1 - diff --git a/KubeOS.spec b/KubeOS.spec index 9b457d3ac8789ecc29e953b40c9afe5bf9615089..b7276aa097f84e32b1527bd738a5a852557da9d0 100644 --- a/KubeOS.spec +++ b/KubeOS.spec @@ -1,39 +1,17 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. Name: KubeOS -Version: 1.0.4 -Release: 4 +Version: 1.0.5 +Release: 1 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-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 -Patch23: 0023-KubeOS-fix-proxy-upgrade-requeue-bug.patch -Patch24: 0024-KubeOS-fix-label-changed-after-upgrade.patch +Patch1: 0001-build-rust-os-agent-remove-useless-dependency.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: make +BuildRequires: make rust cargo openssl-devel BuildRequires: golang >= 1.13 + %description This is an O&M platform used to update the whole OS as an entirety, it should be running in kubernetes environment. @@ -41,15 +19,11 @@ it should be running in kubernetes environment. %prep %autosetup -n %{name}-v%{version} -p1 -%package agent -Summary: agent provides os-agent and related service files which are needed on nodes -%description agent -The agent package includes os-agent and service files - -%package admin-container -Summary: admin-container contains hostshell and set-ssh-pub-key script and service file -%description admin-container -The agent package includes hostshell and set-ssh-pub-key script and service file +%package scripts +Summary: Scripts to build the os image and binaries of os-proxy and os-operator +Requires: qemu-img, parted, bc, tar, docker, dosfstools +%description scripts +The scripts package includes scripts which could build the os image and binaries of os-proxy and os-operator %define debug_package %{nil} %define __debug_install_post \ @@ -57,55 +31,110 @@ The agent package includes hostshell and set-ssh-pub-key script and service file %{nil} %build +mkdir ./KubeOS-Rust/.cargo +cat << EOF >> ./KubeOS-Rust/.cargo/config + +[source.crates-io] +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "vendor" +EOF + make %install +install -d %{buildroot}%{_bindir} +#install binary install -d -m 0740 %{buildroot}/opt/kubeOS/bin -install -p -m 0500 ./bin/proxy %{buildroot}/opt/kubeOS/bin +install -p -m 0500 ./bin/rust/release/os-agent %{buildroot}/opt/kubeOS/bin +install -p -m 0500 ./bin/rust/release/proxy %{buildroot}/opt/kubeOS/bin install -p -m 0500 ./bin/operator %{buildroot}/opt/kubeOS/bin - -#kubeos-agent -install -d %{buildroot}%{_bindir} -install -d %{buildroot}%{_prefix}/lib/systemd/system -install -p -m 0500 ./bin/os-agent %{buildroot}%{_bindir} -install -p -m 0600 ./files/boot-efi.mount %{buildroot}%{_prefix}/lib/systemd/system -install -p -m 0600 ./files/etc.mount %{buildroot}%{_prefix}/lib/systemd/system -install -p -m 0600 ./files/persist.mount %{buildroot}%{_prefix}/lib/systemd/system -install -p -m 0600 ./files/var.mount %{buildroot}%{_prefix}/lib/systemd/system -install -p -m 0600 ./files/os-agent.service %{buildroot}%{_prefix}/lib/systemd/system -install -p -m 0600 ./files/os-release %{buildroot}%{_prefix}/lib/ - -#kubeos-admin-container -install -p -m 0500 ./bin/hostshell %{buildroot}%{_bindir} -install -d %{buildroot}%{_prefix}/local/bin -install -p -m 0500 ./scripts/admin-container/set-ssh-pub-key.sh %{buildroot}%{_prefix}/local/bin -install -d %{buildroot}%{_prefix}/lib/sysmaster -install -p -m 0600 ./scripts/admin-container/set-ssh-pub-key.service %{buildroot}%{_prefix}/lib/sysmaster +install -p -m 0500 ./bin/hostshell %{buildroot}/opt/kubeOS/bin + +#install artifacts +install -d -m 0740 %{buildroot}/opt/kubeOS/scripts +install -p -m 0600 ./scripts/rpmlist %{buildroot}/opt/kubeOS/scripts +install -p -m 0500 ./scripts/kbimg.sh %{buildroot}/opt/kubeOS/scripts +install -p -m 0500 ./scripts/set_in_chroot.sh %{buildroot}/opt/kubeOS/scripts +install -p -m 0600 ./scripts/grub.cfg %{buildroot}/opt/kubeOS/scripts +install -p -m 0500 ./scripts/bootloader.sh %{buildroot}/opt/kubeOS/scripts +install -p -m 0500 ./scripts/Dockerfile %{buildroot}/opt/kubeOS/scripts + +install -d -m 0740 %{buildroot}/opt/kubeOS/scripts/common +install -p -m 0500 ./scripts/common/globalVariables.sh %{buildroot}/opt/kubeOS/scripts/common +install -p -m 0500 ./scripts/common/log.sh %{buildroot}/opt/kubeOS/scripts/common +install -p -m 0500 ./scripts/common/utils.sh %{buildroot}/opt/kubeOS/scripts/common + +install -d -m 0740 %{buildroot}/opt/kubeOS/scripts/create +install -p -m 0500 ./scripts/create/imageCreate.sh %{buildroot}/opt/kubeOS/scripts/create +install -p -m 0500 ./scripts/create/rootfsCreate.sh %{buildroot}/opt/kubeOS/scripts/create + +install -d -m 0740 %{buildroot}/opt/kubeOS/scripts/00bootup +install -p -m 0600 ./scripts/00bootup/Global.cfg %{buildroot}/opt/kubeOS/scripts/00bootup +install -p -m 0500 ./scripts/00bootup/module-setup.sh %{buildroot}/opt/kubeOS/scripts/00bootup +install -p -m 0500 ./scripts/00bootup/mount.sh %{buildroot}/opt/kubeOS/scripts/00bootup + +install -d -m 0740 %{buildroot}/opt/kubeOS/scripts/admin-container +install -p -m 0500 ./scripts/admin-container/set-ssh-pub-key.sh %{buildroot}/opt/kubeOS/scripts/admin-container +install -p -m 0600 ./scripts/admin-container/set-ssh-pub-key.service %{buildroot}/opt/kubeOS/scripts/admin-container +install -p -m 0500 ./scripts/admin-container/Dockerfile %{buildroot}/opt/kubeOS/scripts/admin-container + +install -d -m 0740 %{buildroot}/opt/kubeOS/files +install -p -m 0600 ./files/boot-efi.mount %{buildroot}/opt/kubeOS/files +install -p -m 0600 ./files/etc.mount %{buildroot}/opt/kubeOS/files +install -p -m 0600 ./files/persist.mount %{buildroot}/opt/kubeOS/files +install -p -m 0600 ./files/var.mount %{buildroot}/opt/kubeOS/files +install -p -m 0600 ./files/os-agent.service %{buildroot}/opt/kubeOS/files +install -p -m 0600 ./files/os-release %{buildroot}/opt/kubeOS/files %files +%defattr(-,root,root,0500) +%attr(0500,root,root) /opt/kubeOS/bin/os-agent +%attr(0500,root,root) /opt/kubeOS/bin/hostshell %attr(0500,root,root) /opt/kubeOS/bin/proxy %attr(0500,root,root) /opt/kubeOS/bin/operator - -%files agent -%attr(0500,root,root) %{_bindir}/os-agent +%attr(0600,root,root) /opt/kubeOS/files/boot-efi.mount +%attr(0600,root,root) /opt/kubeOS/files/etc.mount +%attr(0600,root,root) /opt/kubeOS/files/persist.mount +%attr(0600,root,root) /opt/kubeOS/files/var.mount +%attr(0600,root,root) /opt/kubeOS/files/os-agent.service +%attr(0600,root,root) /opt/kubeOS/files/os-release + +%files scripts %defattr(-,root,root,0500) -%attr(0600,root,root) %{_prefix}/lib/systemd/system/boot-efi.mount -%attr(0600,root,root) %{_prefix}/lib/systemd/system/etc.mount -%attr(0600,root,root) %{_prefix}/lib/systemd/system/persist.mount -%attr(0600,root,root) %{_prefix}/lib/systemd/system/var.mount -%attr(0600,root,root) %{_prefix}/lib/systemd/system/os-agent.service -%attr(0600,root,root) %{_prefix}/lib/os-release - -%files admin-container -%attr(0500,root,root) %{_bindir}/hostshell -%defattr(-,root,root,0500) -%attr(0500,root,root) %{_prefix}/local/bin/set-ssh-pub-key.sh -%attr(0600,root,root) %{_prefix}/lib/sysmaster/set-ssh-pub-key.service +%attr(0600,root,root) /opt/kubeOS/scripts/rpmlist +%attr(0500,root,root) /opt/kubeOS/scripts/kbimg.sh +%attr(0500,root,root) /opt/kubeOS/scripts/set_in_chroot.sh +%attr(0600,root,root) /opt/kubeOS/scripts/grub.cfg +%attr(0500,root,root) /opt/kubeOS/scripts/bootloader.sh +%attr(0500,root,root) /opt/kubeOS/scripts/Dockerfile + +%attr(0500,root,root) /opt/kubeOS/scripts/common/globalVariables.sh +%attr(0500,root,root) /opt/kubeOS/scripts/common/log.sh +%attr(0500,root,root) /opt/kubeOS/scripts/common/utils.sh + +%attr(0500,root,root) /opt/kubeOS/scripts/create/imageCreate.sh +%attr(0500,root,root) /opt/kubeOS/scripts/create/rootfsCreate.sh + +%attr(0600,root,root) /opt/kubeOS/scripts/00bootup/Global.cfg +%attr(0500,root,root) /opt/kubeOS/scripts/00bootup/module-setup.sh +%attr(0500,root,root) /opt/kubeOS/scripts/00bootup/mount.sh + +%attr(0500,root,root) /opt/kubeOS/scripts/admin-container/set-ssh-pub-key.sh +%attr(0500,root,root) /opt/kubeOS/scripts/admin-container/Dockerfile +%attr(0600,root,root) /opt/kubeOS/scripts/admin-container/set-ssh-pub-key.service %clean rm -rfv %{buildroot} %changelog +* Wed Jan 10 2024 Yuhang Wei - 1.0.5-1 +- Type:requirement +- CVE:NA +- SUG:restart +- DESC:update version to 1.0.5.1 + * Tue Sep 05 2023 Yuhang Wei - 1.0.4-4 - Type:requirement - CVE:NA diff --git a/v1.0.4.tar.gz b/v1.0.4.tar.gz deleted file mode 100644 index 601b8bdd2a51b1a88a0ec93f83ff8a98513b2646..0000000000000000000000000000000000000000 Binary files a/v1.0.4.tar.gz and /dev/null differ diff --git a/v1.0.5.tar.gz b/v1.0.5.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6c7ae5f02eafba231e4dbfe69eea0f70082c22da Binary files /dev/null and b/v1.0.5.tar.gz differ