You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@yunikorn.apache.org by ch...@apache.org on 2024/01/14 18:06:12 UTC
(yunikorn-k8shim) branch master updated: [YUNIKORN-2287] Decompress function doesn't need to decode base64 (#752)
This is an automated email from the ASF dual-hosted git repository.
chia7712 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/yunikorn-k8shim.git
The following commit(s) were added to refs/heads/master by this push:
new 57f11dc3 [YUNIKORN-2287] Decompress function doesn't need to decode base64 (#752)
57f11dc3 is described below
commit 57f11dc351a8300f5374fd53b97426b2adf7632e
Author: PoAn Yang <pa...@apache.org>
AuthorDate: Mon Jan 15 02:05:53 2024 +0800
[YUNIKORN-2287] Decompress function doesn't need to decode base64 (#752)
Closes: #752
Signed-off-by: Chia-Ping Tsai <ch...@gmail.com>
---
pkg/common/utils/utils_test.go | 5 +-
pkg/conf/schedulerconf.go | 11 +-
pkg/conf/schedulerconf_test.go | 6 +-
test/e2e/configmap/configmap_suite_test.go | 88 ++++++++++++++++
test/e2e/configmap/configmap_test.go | 112 +++++++++++++++++++++
test/e2e/framework/configmanager/constants.go | 1 +
.../framework/helpers/yunikorn/rest_api_utils.go | 10 ++
test/e2e/framework/helpers/yunikorn/wrappers.go | 2 +
test/e2e/testdata/compressed_yunikorn-configs.yaml | 35 +++++++
test/e2e/testdata/yunikorn-configs.yaml | 32 ++++++
10 files changed, 284 insertions(+), 18 deletions(-)
diff --git a/pkg/common/utils/utils_test.go b/pkg/common/utils/utils_test.go
index 4f98d2bd..c7e8a45b 100644
--- a/pkg/common/utils/utils_test.go
+++ b/pkg/common/utils/utils_test.go
@@ -21,7 +21,6 @@ package utils
import (
"bytes"
"compress/gzip"
- "encoding/base64"
"fmt"
"strings"
"testing"
@@ -1059,11 +1058,9 @@ func TestGzipCompressedConfigMap(t *testing.T) {
if err := gzWriter.Close(); err != nil {
t.Fatal("expected nil, got error")
}
- encodedConfigString := make([]byte, base64.StdEncoding.EncodedLen(len(b.Bytes())))
- base64.StdEncoding.Encode(encodedConfigString, b.Bytes())
confMap := conf.FlattenConfigMaps([]*v1.ConfigMap{
{Data: map[string]string{}},
- {Data: map[string]string{conf.CMSvcClusterID: "new"}, BinaryData: map[string][]byte{"queues.yaml.gz": encodedConfigString}},
+ {Data: map[string]string{conf.CMSvcClusterID: "new"}, BinaryData: map[string][]byte{"queues.yaml.gz": b.Bytes()}},
})
config := GetCoreSchedulerConfigFromConfigMap(confMap)
assert.Equal(t, configs.DefaultSchedulerConfig, config)
diff --git a/pkg/conf/schedulerconf.go b/pkg/conf/schedulerconf.go
index b9d986ef..cd46c27e 100644
--- a/pkg/conf/schedulerconf.go
+++ b/pkg/conf/schedulerconf.go
@@ -21,7 +21,6 @@ package conf
import (
"bytes"
"compress/gzip"
- "encoding/base64"
"encoding/json"
"errors"
"flag"
@@ -452,18 +451,10 @@ func DumpConfiguration() {
func Decompress(key string, value []byte) (string, string) {
var uncompressedData string
- decodedValue := make([]byte, base64.StdEncoding.DecodedLen(len(value)))
- n, err := base64.StdEncoding.Decode(decodedValue, value)
- if err != nil {
- log.Log(log.ShimConfig).Error("failed to decode schedulerConfig entry", zap.Error(err))
- return "", ""
- }
- decodedValue = decodedValue[:n]
splitKey := strings.Split(key, ".")
compressionAlgo := splitKey[len(splitKey)-1]
if strings.EqualFold(compressionAlgo, constants.GzipSuffix) {
- reader := bytes.NewReader(decodedValue)
- gzReader, err := gzip.NewReader(reader)
+ gzReader, err := gzip.NewReader(bytes.NewReader(value))
if err != nil {
log.Log(log.ShimConfig).Error("failed to decompress decoded schedulerConfig entry", zap.Error(err))
return "", ""
diff --git a/pkg/conf/schedulerconf_test.go b/pkg/conf/schedulerconf_test.go
index e9c0a091..ef16dff3 100644
--- a/pkg/conf/schedulerconf_test.go
+++ b/pkg/conf/schedulerconf_test.go
@@ -87,9 +87,7 @@ func TestDecompress(t *testing.T) {
assert.NilError(t, err, "expected nil, got error")
t.Fatal("expected nil, got error")
}
- encodedConfigString := make([]byte, base64.StdEncoding.EncodedLen(len(b.Bytes())))
- base64.StdEncoding.Encode(encodedConfigString, b.Bytes())
- key, decodedConfigString := Decompress("queues.yaml."+constants.GzipSuffix, encodedConfigString)
+ key, decodedConfigString := Decompress("queues.yaml."+constants.GzipSuffix, b.Bytes())
assert.Equal(t, "queues.yaml", key)
assert.Equal(t, configs.DefaultSchedulerConfig, decodedConfigString)
}
@@ -97,7 +95,7 @@ func TestDecompress(t *testing.T) {
func TestDecompressUnknownKey(t *testing.T) {
encodedConfigString := make([]byte, base64.StdEncoding.EncodedLen(len([]byte(configs.DefaultSchedulerConfig))))
base64.StdEncoding.Encode(encodedConfigString, []byte(configs.DefaultSchedulerConfig))
- key, decodedConfigString := Decompress("queues.yaml.bin", encodedConfigString)
+ key, decodedConfigString := Decompress("queues.yaml.bin", []byte(configs.DefaultSchedulerConfig))
assert.Equal(t, "queues.yaml", key)
assert.Assert(t, len(decodedConfigString) == 0, "expected decodedConfigString to be nil")
}
diff --git a/test/e2e/configmap/configmap_suite_test.go b/test/e2e/configmap/configmap_suite_test.go
new file mode 100644
index 00000000..5257bfa6
--- /dev/null
+++ b/test/e2e/configmap/configmap_suite_test.go
@@ -0,0 +1,88 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package configmap
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/onsi/ginkgo/v2"
+ "github.com/onsi/ginkgo/v2/reporters"
+ "github.com/onsi/gomega"
+
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/configmanager"
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/helpers/common"
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/helpers/k8s"
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/helpers/yunikorn"
+)
+
+func init() {
+ configmanager.YuniKornTestConfig.ParseFlags()
+}
+
+func TestConfigMap(t *testing.T) {
+ ginkgo.ReportAfterSuite("TestConfigMap", func(report ginkgo.Report) {
+ err := common.CreateJUnitReportDir()
+ Ω(err).NotTo(gomega.HaveOccurred())
+ err = reporters.GenerateJUnitReportWithConfig(
+ report,
+ filepath.Join(configmanager.YuniKornTestConfig.LogDir, "TEST-configmap_junit.xml"),
+ reporters.JunitReportConfig{OmitSpecLabels: true},
+ )
+ Ω(err).NotTo(HaveOccurred())
+ })
+ gomega.RegisterFailHandler(ginkgo.Fail)
+ ginkgo.RunSpecs(t, "TestConfigMap", ginkgo.Label("TestConfigMap"))
+}
+
+var (
+ kClient k8s.KubeCtl
+ restClient yunikorn.RClient
+)
+
+var _ = BeforeSuite(func() {
+
+ kClient = k8s.KubeCtl{}
+ Ω(kClient.SetClient()).To(BeNil())
+
+ restClient = yunikorn.RClient{}
+ Ω(restClient).NotTo(BeNil())
+
+ yunikorn.EnsureYuniKornConfigsPresent()
+
+ By("Port-forward the scheduler pod")
+ err := kClient.PortForwardYkSchedulerPod()
+ Ω(err).NotTo(HaveOccurred())
+})
+
+var _ = AfterSuite(func() {})
+
+var Describe = ginkgo.Describe
+var It = ginkgo.It
+var By = ginkgo.By
+var BeforeEach = ginkgo.BeforeEach
+var AfterEach = ginkgo.AfterEach
+var BeforeSuite = ginkgo.BeforeSuite
+var AfterSuite = ginkgo.AfterSuite
+
+// Declarations for Gomega Matchers
+var Equal = gomega.Equal
+var Ω = gomega.Expect
+var BeNil = gomega.BeNil
+var HaveOccurred = gomega.HaveOccurred
diff --git a/test/e2e/configmap/configmap_test.go b/test/e2e/configmap/configmap_test.go
new file mode 100644
index 00000000..49aa2120
--- /dev/null
+++ b/test/e2e/configmap/configmap_test.go
@@ -0,0 +1,112 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package configmap
+
+import (
+ "bytes"
+ "compress/gzip"
+ "io"
+ "time"
+
+ v1 "k8s.io/api/core/v1"
+
+ "github.com/apache/yunikorn-core/pkg/common/configs"
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/configmanager"
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/helpers/k8s"
+ "github.com/apache/yunikorn-k8shim/test/e2e/framework/helpers/yunikorn"
+)
+
+var oldConfigMap = new(v1.ConfigMap)
+
+var _ = Describe("ConfigMap", func() {
+ BeforeEach(func() {
+ By("Get previous config")
+ var err error
+ oldConfigMap, err = kClient.GetConfigMaps(configmanager.YuniKornTestConfig.YkNamespace,
+ configmanager.DefaultYuniKornConfigMap)
+ Ω(err).NotTo(HaveOccurred())
+ Ω(oldConfigMap).NotTo(BeNil())
+ })
+
+ It("Verify_ConfigMap_File", func() {
+ configMap, err := k8s.GetConfigMapObj("../testdata/yunikorn-configs.yaml")
+ Ω(err).NotTo(HaveOccurred())
+ Ω(configMap).NotTo(BeNil())
+
+ By("Updating the config map with BinaryData")
+ configMap.Namespace = configmanager.YuniKornTestConfig.YkNamespace
+ _, err = kClient.UpdateConfigMap(configMap, configmanager.YuniKornTestConfig.YkNamespace)
+ Ω(err).NotTo(HaveOccurred())
+
+ queues := configMap.Data[configmanager.DefaultPolicyGroup]
+
+ schedulerConfig, err := configs.LoadSchedulerConfigFromByteArray([]byte(queues))
+ Ω(err).NotTo(HaveOccurred())
+ Ω(len(schedulerConfig.Partitions)).To(Equal(1))
+ Ω(len(schedulerConfig.Partitions[0].Queues)).To(Equal(1))
+
+ ts := schedulerConfig.Partitions[0].Queues[0].Properties["timestamp"]
+ err = yunikorn.WaitForQueueTS("root", ts, 30*time.Second)
+ Ω(err).NotTo(HaveOccurred())
+
+ checkSchedulerConfig(schedulerConfig)
+ })
+
+ It("Verify_Compressed_ConfigMap_File", func() {
+ configMap, err := k8s.GetConfigMapObj("../testdata/compressed_yunikorn-configs.yaml")
+ Ω(err).NotTo(HaveOccurred())
+ Ω(configMap).NotTo(BeNil())
+
+ By("Updating the config map with BinaryData")
+ configMap.Namespace = configmanager.YuniKornTestConfig.YkNamespace
+ _, err = kClient.UpdateConfigMap(configMap, configmanager.YuniKornTestConfig.YkNamespace)
+ Ω(err).NotTo(HaveOccurred())
+
+ queuesGz := configMap.BinaryData[configmanager.DefaultPolicyGroup+".gz"]
+ Ω(len(queuesGz)).NotTo(Equal(0))
+ gzReader, err := gzip.NewReader(bytes.NewReader(queuesGz))
+ Ω(err).NotTo(HaveOccurred())
+ decompressedBytes, err := io.ReadAll(gzReader)
+ Ω(err).NotTo(HaveOccurred())
+ err = gzReader.Close()
+ Ω(err).NotTo(HaveOccurred())
+
+ schedulerConfig, err := configs.LoadSchedulerConfigFromByteArray(decompressedBytes)
+ Ω(err).NotTo(HaveOccurred())
+ Ω(len(schedulerConfig.Partitions)).To(Equal(1))
+ Ω(len(schedulerConfig.Partitions[0].Queues)).To(Equal(1))
+
+ ts := schedulerConfig.Partitions[0].Queues[0].Properties["timestamp"]
+ err = yunikorn.WaitForQueueTS("root", ts, 30*time.Second)
+ Ω(err).NotTo(HaveOccurred())
+
+ checkSchedulerConfig(schedulerConfig)
+ })
+
+ AfterEach(func() {
+ yunikorn.RestoreConfigMapWrapper(oldConfigMap, "")
+ })
+})
+
+func checkSchedulerConfig(schedulerConfig *configs.SchedulerConfig) {
+ configDAOInfo, err := restClient.GetConfig()
+ Ω(err).NotTo(HaveOccurred())
+ Ω(configDAOInfo).NotTo(BeNil())
+ Ω(configDAOInfo.Partitions).To(Equal(schedulerConfig.Partitions))
+}
diff --git a/test/e2e/framework/configmanager/constants.go b/test/e2e/framework/configmanager/constants.go
index 0eeeda08..8b5cb791 100644
--- a/test/e2e/framework/configmanager/constants.go
+++ b/test/e2e/framework/configmanager/constants.go
@@ -39,6 +39,7 @@ const (
AppsPath = "ws/v1/partition/%s/queue/%s/applications"
AppPath = "ws/v1/partition/%s/queue/%s/application/%s"
CompletedAppsPath = "ws/v1/partition/%s/applications/completed"
+ ConfigPath = "ws/v1/config"
ClustersPath = "ws/v1/clusters"
NodesPath = "ws/v1/partition/%s/nodes"
UserUsagePath = "ws/v1/partition/%s/usage/user/%s"
diff --git a/test/e2e/framework/helpers/yunikorn/rest_api_utils.go b/test/e2e/framework/helpers/yunikorn/rest_api_utils.go
index 732807d2..1db748dd 100644
--- a/test/e2e/framework/helpers/yunikorn/rest_api_utils.go
+++ b/test/e2e/framework/helpers/yunikorn/rest_api_utils.go
@@ -110,6 +110,16 @@ func (c *RClient) GetQueues(partition string) (*dao.PartitionQueueDAOInfo, error
return queues, err
}
+func (c *RClient) GetConfig() (*dao.ConfigDAOInfo, error) {
+ req, err := c.newRequest("GET", configmanager.ConfigPath, nil)
+ if err != nil {
+ return nil, err
+ }
+ var config *dao.ConfigDAOInfo
+ _, err = c.do(req, &config)
+ return config, err
+}
+
func (c *RClient) GetHealthCheck() (dao.SchedulerHealthDAOInfo, error) {
req, err := c.newRequest("GET", configmanager.HealthCheckPath, nil)
if err != nil {
diff --git a/test/e2e/framework/helpers/yunikorn/wrappers.go b/test/e2e/framework/helpers/yunikorn/wrappers.go
index d11877c3..07476eb4 100644
--- a/test/e2e/framework/helpers/yunikorn/wrappers.go
+++ b/test/e2e/framework/helpers/yunikorn/wrappers.go
@@ -112,6 +112,7 @@ func UpdateCustomConfigMapWrapperWithMap(oldConfigMap *v1.ConfigMap, schedPolicy
for k, v := range customMap {
c.Data[k] = v
}
+ c.BinaryData = nil
var d, err3 = k.UpdateConfigMap(c, configmanager.YuniKornTestConfig.YkNamespace)
Ω(err3).NotTo(HaveOccurred())
Ω(d).NotTo(BeNil())
@@ -134,6 +135,7 @@ func RestoreConfigMapWrapper(oldConfigMap *v1.ConfigMap, annotation string) {
ts, tsErr := common.SetQueueTimestamp(oldSC, "default", "root")
Ω(tsErr).NotTo(HaveOccurred())
c.Data = oldConfigMap.Data
+ c.BinaryData = oldConfigMap.BinaryData
c.Data[configmanager.DefaultPolicyGroup], err = common.ToYAML(oldSC)
Ω(err).NotTo(HaveOccurred())
diff --git a/test/e2e/testdata/compressed_yunikorn-configs.yaml b/test/e2e/testdata/compressed_yunikorn-configs.yaml
new file mode 100644
index 00000000..24ede4ce
--- /dev/null
+++ b/test/e2e/testdata/compressed_yunikorn-configs.yaml
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: yunikorn-configs
+binaryData:
+# Following command is used to generate queues.yaml which is compressed by gzip and encoded by base64.
+# The result is like the value in queues.yaml.gz. If updating the queues.yaml, please also update the queues.yaml.gz.
+# echo "
+# partitions:
+# - name: default
+# queues:
+# - name: root
+# submitacl: '*'
+# parent: true
+# properties:
+# timestamp: '1257894000'
+# queues:
+# - name: parent
+# submitacl: '*'" | gzip | base64
+ queues.yaml.gz: H4sIANGBiWUAA2WO2wrCMBBE3/sV81YQhCiKmr9ZdQuB5mKy+/+maptK5/Hscma6RFmcuBiK7YA9Anm2ePJAOkolwEtZ+XOdMn/kGOWHgKJ374Qeo0W/6xdc3RzEQrJygzkmrp1NOUWc5yLkUzUcjufL9XYyxjTV/4j1kG/J6rCZ8wavmg4s5AAAAA==
diff --git a/test/e2e/testdata/yunikorn-configs.yaml b/test/e2e/testdata/yunikorn-configs.yaml
new file mode 100644
index 00000000..5cbf9e74
--- /dev/null
+++ b/test/e2e/testdata/yunikorn-configs.yaml
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: yunikorn-configs
+data:
+ queues.yaml: |
+ partitions:
+ - name: default
+ queues:
+ - name: root
+ submitacl: '*'
+ parent: true
+ properties:
+ timestamp: '1705067238'
+ queues:
+ - name: parent
+ submitacl: '*'
---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@yunikorn.apache.org
For additional commands, e-mail: issues-help@yunikorn.apache.org