This is an automated email from the ASF dual-hosted git repository.

zhongxjian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git


The following commit(s) were added to refs/heads/master by this push:
     new 2faf17b6 [operator] Changing the directory structure
2faf17b6 is described below

commit 2faf17b6dd04bae0befcc5a3521b3fe5da2f02fd
Author: mfordjody <[email protected]>
AuthorDate: Fri Dec 13 17:55:29 2024 +0800

    [operator] Changing the directory structure
---
 operator/cmd/validation/validation.go              |  11 +
 operator/manifest/common.go                        | 141 ----
 operator/manifest/common_test.go                   |  85 --
 operator/manifest/manifest.go                      |  63 --
 operator/manifest/render/render.go                 | 422 ----------
 operator/manifest/render/render_test.go            | 907 ---------------------
 operator/manifest/render/testchart/.helmignore     |  23 -
 operator/manifest/render/testchart/Chart.yaml      |  39 -
 .../manifest/render/testchart/templates/NOTES.txt  |  22 -
 .../render/testchart/templates/_helpers.tpl        |  62 --
 .../render/testchart/templates/deployment.yaml     |  76 --
 .../manifest/render/testchart/templates/hpa.yaml   |  43 -
 .../render/testchart/templates/ingress.yaml        |  76 --
 .../render/testchart/templates/service.yaml        |  30 -
 .../render/testchart/templates/serviceaccount.yaml |  27 -
 .../testchart/templates/tests/test-connection.yaml |  30 -
 operator/manifest/render/testchart/values.yaml     |  97 ---
 operator/manifest/tree.go                          | 566 -------------
 operator/manifest/util.go                          |  62 --
 operator/{manifest => pkg}/render/manifest.go      |   2 +-
 20 files changed, 12 insertions(+), 2772 deletions(-)

diff --git a/operator/cmd/validation/validation.go 
b/operator/cmd/validation/validation.go
index 7e6fbefc..f0d30cf4 100644
--- a/operator/cmd/validation/validation.go
+++ b/operator/cmd/validation/validation.go
@@ -4,9 +4,13 @@ import (
        "bytes"
        "encoding/json"
        "github.com/apache/dubbo-kubernetes/operator/pkg/apis"
+       "github.com/apache/dubbo-kubernetes/operator/pkg/util"
        "github.com/apache/dubbo-kubernetes/operator/pkg/values"
+       "sigs.k8s.io/yaml"
 )
 
+type Warnings = util.Errors
+
 func ParseAndValidateDubboOperator(dopMap values.Map) (Warnings, util.Errors) {
        dop := &apis.DubboOperator{}
        dec := json.NewDecoder(bytes.NewBufferString(dopMap.JSON()))
@@ -30,3 +34,10 @@ func validateValues(raw *apis.DubboOperator) (Warnings, 
util.Errors) {
        }
        return nil, nil
 }
+
+func validateComponentNames(components *apis.DubboComponentSpec) error {
+       if components == nil {
+               return fmt.Errorf("components not found")
+       }
+       return nil
+}
diff --git a/operator/manifest/common.go b/operator/manifest/common.go
deleted file mode 100644
index 9234cf69..00000000
--- a/operator/manifest/common.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// 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 manifest
-
-import (
-       "fmt"
-       
"github.com/apache/dubbo-kubernetes/operator/pkg/apis/dubbo.apache.org/v1alpha1"
-       "github.com/apache/dubbo-kubernetes/operator/pkg/identifier"
-       util2 "github.com/apache/dubbo-kubernetes/operator/pkg/util"
-       "path"
-       "strings"
-)
-
-import (
-       "sigs.k8s.io/yaml"
-)
-
-func ReadOverlayProfileYaml(profilePath string, profile string) (string, 
error) {
-       filePath := path.Join(profilePath, profile+".yaml")
-       defaultPath := path.Join(profilePath, "default.yaml")
-       // overlay selected profile ont default profile
-       out, err := ReadAndOverlayYamls([]string{defaultPath, filePath})
-       if err != nil {
-               return "", err
-       }
-       // unmarshal and validate
-       tempOp := &v1alpha1.DubboConfig{}
-       if err := yaml.Unmarshal([]byte(out), tempOp); err != nil {
-               return "", fmt.Errorf("%s profile on default profile is wrong, 
err: %s", profile, err)
-       }
-       return out, nil
-}
-
-func ReadYamlAndProfile(filenames []string, setFlags []string) (string, 
string, error) {
-       mergedYaml, err := ReadAndOverlayYamls(filenames)
-       if err != nil {
-               return "", "", err
-       }
-       // unmarshal and validate
-       tempOp := &v1alpha1.DubboConfig{}
-       if err := yaml.Unmarshal([]byte(mergedYaml), tempOp); err != nil {
-               return "", "", fmt.Errorf("user specification is wrong, err: 
%s", err)
-       }
-       // get profile field and overlay with setFlags
-       profile := "default"
-       if opProfile := tempOp.GetProfile(); opProfile != "" {
-               profile = opProfile
-       }
-       if profileVal := GetValueFromSetFlags(setFlags, "profile"); profileVal 
!= "" {
-               profile = profileVal
-       }
-
-       return mergedYaml, profile, nil
-}
-
-func ReadAndOverlayYamls(filenames []string) (string, error) {
-       var output string
-       for _, filename := range filenames {
-               file, err := 
identifier.UnionFS.ReadFile(strings.TrimSpace(filename))
-               if err != nil {
-                       return "", err
-               }
-               // todo:// inspect that this file only contains one CR
-               output, err = util2.OverlayYAML(output, string(file))
-               if err != nil {
-                       return "", err
-               }
-       }
-       return output, nil
-}
-
-func OverlaySetFlags(base string, setFlags []string) (string, error) {
-       baseMap := make(map[string]interface{})
-       if err := yaml.Unmarshal([]byte(base), &baseMap); err != nil {
-               return "", err
-       }
-       for _, setFlag := range setFlags {
-               key, val := SplitSetFlag(setFlag)
-               pathCtx, _, err := GetPathContext(baseMap, 
util2.PathFromString(key), true)
-               if err != nil {
-                       return "", err
-               }
-               if err := WritePathContext(pathCtx, ParseValue(val), false); 
err != nil {
-                       return "", err
-               }
-       }
-       finalYaml, err := yaml.Marshal(baseMap)
-       if err != nil {
-               return "", err
-       }
-       return string(finalYaml), nil
-}
-
-// ReadProfilesNames reads all profiles in directory specified by profilesPath.
-// It does not traverse recursively.
-// It may add some filters in the future.
-func ReadProfilesNames(profilesPath string) ([]string, error) {
-       var res []string
-       dir, err := identifier.UnionFS.ReadDir(profilesPath)
-       if err != nil {
-               return nil, err
-       }
-       yamlSuffix := ".yaml"
-       for _, file := range dir {
-               if file.IsDir() {
-                       continue
-               }
-               if strings.HasSuffix(file.Name(), yamlSuffix) {
-                       res = append(res, strings.TrimSuffix(file.Name(), 
".yaml"))
-               }
-       }
-       return res, nil
-}
-
-// ReadProfileYaml reads profile yaml specified by profilePath/profile.yaml 
and validates the content.
-func ReadProfileYaml(profilePath string, profile string) (string, error) {
-       filePath := path.Join(profilePath, profile+".yaml")
-       out, err := ReadAndOverlayYamls([]string{filePath})
-       if err != nil {
-               return "", err
-       }
-       // unmarshal and validate
-       tempOp := &v1alpha1.DubboConfig{}
-       if err := yaml.Unmarshal([]byte(out), tempOp); err != nil {
-               return "", fmt.Errorf("%s profile is wrong, err: %s", profile, 
err)
-       }
-       return out, nil
-}
diff --git a/operator/manifest/common_test.go b/operator/manifest/common_test.go
deleted file mode 100644
index 36816c8c..00000000
--- a/operator/manifest/common_test.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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 manifest
-
-import (
-       "testing"
-)
-
-func TestOverlaySetFlags(t *testing.T) {
-       testBase := `spec:
-  components:
-    nacos:
-      enabled: true
-`
-       tests := []struct {
-               desc     string
-               base     string
-               setFlags []string
-               expect   string
-       }{
-               {
-                       desc: "create missing leaf",
-                       base: testBase,
-                       setFlags: []string{
-                               "spec.components.nacos.replicas=2",
-                       },
-                       expect: `spec:
-  components:
-    nacos:
-      enabled: true
-      replicas: 2
-`,
-               },
-               {
-                       desc: "create missing object",
-                       base: testBase,
-                       setFlags: []string{
-                               "spec.components.zookeeper.enabled=true",
-                               "spec.components.zookeeper.replicas=2",
-                       },
-                       expect: `spec:
-  components:
-    nacos:
-      enabled: true
-    zookeeper:
-      enabled: true
-      replicas: 2
-`,
-               },
-               {
-                       desc: "replace leaf",
-                       base: testBase,
-                       setFlags: []string{
-                               "spec.components.nacos.enabled=false",
-                       },
-                       expect: `spec:
-  components:
-    nacos:
-      enabled: false
-`,
-               },
-       }
-       for _, test := range tests {
-               res, err := OverlaySetFlags(test.base, test.setFlags)
-               if err != nil {
-                       t.Fatal(err)
-               }
-               if res != test.expect {
-                       t.Errorf("expect:\n%s\nbut got:\n%s\n", test.expect, 
res)
-               }
-       }
-}
diff --git a/operator/manifest/manifest.go b/operator/manifest/manifest.go
deleted file mode 100644
index 8d3fde4b..00000000
--- a/operator/manifest/manifest.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package manifest
-
-import (
-       "encoding/json"
-       "github.com/apache/dubbo-kubernetes/operator/pkg/component"
-       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-       "sigs.k8s.io/yaml"
-)
-
-type Manifest struct {
-       *unstructured.Unstructured
-       Content string
-}
-
-type ManifestSet struct {
-       Comps     component.Name
-       Manifests []Manifest
-}
-
-func FromJSON(j []byte) (Manifest, error) {
-       us := &unstructured.Unstructured{}
-       if err := json.Unmarshal(j, us); err != nil {
-               return Manifest{}, err
-       }
-       yml, err := yaml.Marshal(us)
-       if err != nil {
-               return Manifest{}, err
-       }
-       return Manifest{
-               Unstructured: us,
-               Content:      string(yml),
-       }, nil
-}
-
-func FromYAML(y []byte) (Manifest, error) {
-       us := &unstructured.Unstructured{}
-       if err := yaml.Unmarshal(y, us); err != nil {
-               return Manifest{}, err
-       }
-       return Manifest{
-               Unstructured: us,
-               Content:      string(y),
-       }, nil
-}
-
-func Parse(output []string) ([]Manifest, error) {
-       result := make([]Manifest, 0, len(output))
-       for _, m := range output {
-               mf, err := FromYAML([]byte(m))
-               if err != nil {
-                       return nil, err
-               }
-               if mf.GetObjectKind().GroupVersionKind().Kind == "" {
-                       continue
-               }
-               result = append(result, mf)
-       }
-       return result, nil
-}
-
-func ParseMultiple(output string) ([]Manifest, error) {
-       return Parse()
-}
diff --git a/operator/manifest/render/render.go 
b/operator/manifest/render/render.go
deleted file mode 100644
index 5d7673f7..00000000
--- a/operator/manifest/render/render.go
+++ /dev/null
@@ -1,422 +0,0 @@
-// 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 render
-
-import (
-       "errors"
-       "fmt"
-       "github.com/apache/dubbo-kubernetes/operator/manifest"
-       "github.com/apache/dubbo-kubernetes/operator/pkg/identifier"
-       "github.com/apache/dubbo-kubernetes/operator/pkg/util"
-       "io/fs"
-       "net/url"
-       "os"
-       "path"
-       "path/filepath"
-       "sort"
-       "strings"
-)
-
-import (
-       "helm.sh/helm/v3/pkg/action"
-       "helm.sh/helm/v3/pkg/chart"
-       "helm.sh/helm/v3/pkg/chart/loader"
-       "helm.sh/helm/v3/pkg/chartutil"
-       "helm.sh/helm/v3/pkg/cli"
-       "helm.sh/helm/v3/pkg/downloader"
-       "helm.sh/helm/v3/pkg/engine"
-       "helm.sh/helm/v3/pkg/getter"
-       "helm.sh/helm/v3/pkg/repo"
-
-       "sigs.k8s.io/yaml"
-)
-
-const (
-       YAMLSeparator       = "\n---\n"
-       NotesFileNameSuffix = ".txt"
-)
-
-var DefaultFilters = []util.FilterFunc{
-       util.LicenseFilter,
-       util.FormatterFilter,
-       util.ReserveEoFSpaceFilter,
-}
-
-// Renderer is responsible for rendering helm chart with new values.
-// For using RenderManifest, we must invoke Init firstly.
-type Renderer interface {
-       Init() error
-       RenderManifest(valsYaml string) (string, error)
-}
-
-type RendererOptions struct {
-       Name      string
-       Namespace string
-
-       // fields for LocalRenderer
-       // local file system containing the target chart
-       FS fs.FS
-       // chart relevant path to FS
-       Dir string
-
-       // fields for RemoteRenderer
-       // remote chart version
-       Version string
-       // remote chart repo url
-       RepoURL string
-}
-
-type RendererOption func(*RendererOptions)
-
-func WithName(name string) RendererOption {
-       return func(opts *RendererOptions) {
-               opts.Name = name
-       }
-}
-
-func WithNamespace(ns string) RendererOption {
-       return func(opts *RendererOptions) {
-               opts.Namespace = ns
-       }
-}
-
-func WithFS(f fs.FS) RendererOption {
-       return func(opts *RendererOptions) {
-               opts.FS = f
-       }
-}
-
-func WithDir(dir string) RendererOption {
-       return func(opts *RendererOptions) {
-               opts.Dir = dir
-       }
-}
-
-func WithVersion(version string) RendererOption {
-       return func(opts *RendererOptions) {
-               opts.Version = version
-       }
-}
-
-func WithRepoURL(repo string) RendererOption {
-       return func(opts *RendererOptions) {
-               opts.RepoURL = repo
-       }
-}
-
-// LocalRenderer load chart from local file system
-type LocalRenderer struct {
-       Opts    *RendererOptions
-       Chart   *chart.Chart
-       Started bool
-}
-
-func (lr *LocalRenderer) Init() error {
-       fileNames, err := getFileNames(lr.Opts.FS, lr.Opts.Dir)
-       if err != nil {
-               if os.IsNotExist(err) {
-                       return fmt.Errorf("chart of bootstrap %s doesn't 
exist", lr.Opts.Name)
-               }
-               return fmt.Errorf("getFileNames err: %s", err)
-       }
-       var files []*loader.BufferedFile
-       for _, fileName := range fileNames {
-               data, err := fs.ReadFile(lr.Opts.FS, fileName)
-               if err != nil {
-                       return fmt.Errorf("ReadFile %s err: %s", fileName, err)
-               }
-               // todo:// explain why we need to do this
-               name := manifest.StripPrefix(fileName, lr.Opts.Dir)
-               file := &loader.BufferedFile{
-                       Name: name,
-                       Data: data,
-               }
-               files = append(files, file)
-       }
-       newChart, err := loader.LoadFiles(files)
-       if err != nil {
-               return fmt.Errorf("load chart of bootstrap %s err: %s", 
lr.Opts.Name, err)
-       }
-       lr.Chart = newChart
-       lr.Started = true
-       return nil
-}
-
-func (lr *LocalRenderer) RenderManifest(valsYaml string) (string, error) {
-       if !lr.Started {
-               return "", errors.New("LocalRenderer has not been init")
-       }
-       return renderManifest(valsYaml, lr.Chart, true, lr.Opts, 
DefaultFilters...)
-}
-
-func NewLocalRenderer(opts ...RendererOption) (Renderer, error) {
-       newOpts := &RendererOptions{}
-       for _, opt := range opts {
-               opt(newOpts)
-       }
-
-       if err := verifyRendererOptions(newOpts); err != nil {
-               return nil, fmt.Errorf("verify err: %s", err)
-       }
-       return &LocalRenderer{
-               Opts: newOpts,
-       }, nil
-}
-
-type RemoteRenderer struct {
-       Opts    *RendererOptions
-       Chart   *chart.Chart
-       Started bool
-}
-
-func (rr *RemoteRenderer) initChartPathOptions() *action.ChartPathOptions {
-       // for now, using RepoURL and Version directly
-       return &action.ChartPathOptions{
-               RepoURL: rr.Opts.RepoURL,
-               Version: rr.Opts.Version,
-       }
-}
-
-func (rr *RemoteRenderer) Init() error {
-       cpOpts := rr.initChartPathOptions()
-       settings := cli.New()
-       // using release name as chart name by default
-       cp, err := locateChart(cpOpts, rr.Opts.Name, settings)
-       if err != nil {
-               return err
-       }
-
-       // Check chart dependencies to make sure all are present in /charts
-       chartRequested, err := loader.Load(cp)
-       if err != nil {
-               return err
-       }
-
-       if err := verifyInstallable(chartRequested); err != nil {
-               return err
-       }
-
-       rr.Chart = chartRequested
-       rr.Started = true
-
-       return nil
-}
-
-func (rr *RemoteRenderer) RenderManifest(valsYaml string) (string, error) {
-       if !rr.Started {
-               return "", errors.New("RemoteRenderer has not been init")
-       }
-       return renderManifest(valsYaml, rr.Chart, false, rr.Opts, 
DefaultFilters...)
-}
-
-func NewRemoteRenderer(opts ...RendererOption) (Renderer, error) {
-       newOpts := &RendererOptions{}
-       for _, opt := range opts {
-               opt(newOpts)
-       }
-
-       //if err := verifyRendererOptions(newOpts); err != nil {
-       //      return nil, NewLocalRendererErrMgr.WithDescF("verify err: %s", 
err)
-       //}
-       return &RemoteRenderer{
-               Opts: newOpts,
-       }, nil
-}
-
-func verifyRendererOptions(opts *RendererOptions) error {
-       if opts.Name == "" {
-               return errors.New("missing bootstrap name for Renderer")
-       }
-       if opts.Namespace == "" {
-               // logger.Log("using default namespace)
-               opts.Namespace = identifier.DubboDefaultNamespace
-       }
-       if opts.FS == nil {
-               return errors.New("missing chart FS for Renderer")
-       }
-       if opts.Dir == "" {
-               return errors.New("missing chart dir for Renderer")
-       }
-       return nil
-}
-
-// read all files recursively under root path from a certain local file system
-func getFileNames(f fs.FS, root string) ([]string, error) {
-       var fileNames []string
-       if err := fs.WalkDir(f, root, func(path string, d fs.DirEntry, err 
error) error {
-               if err != nil {
-                       return err
-               }
-               if d.IsDir() {
-                       return nil
-               }
-               fileNames = append(fileNames, path)
-               return nil
-       }); err != nil {
-               return nil, err
-       }
-       return fileNames, nil
-}
-
-func verifyInstallable(cht *chart.Chart) error {
-       typ := cht.Metadata.Type
-       if typ == "" || typ == "application" {
-               return nil
-       }
-       return fmt.Errorf("%s chart %s is not installable", typ, cht.Name())
-}
-
-func renderManifest(valsYaml string, cht *chart.Chart, builtIn bool, opts 
*RendererOptions, filters ...util.FilterFunc) (string, error) {
-       valsMap := make(map[string]any)
-       if err := yaml.Unmarshal([]byte(valsYaml), &valsMap); err != nil {
-               return "", fmt.Errorf("unmarshal failed err: %s", err)
-       }
-       RelOpts := chartutil.ReleaseOptions{
-               Name:      opts.Name,
-               Namespace: opts.Namespace,
-       }
-       // todo:// need to specify k8s version
-       caps := chartutil.DefaultCapabilities
-       // maybe we need a configuration to change this caps
-       resVals, err := chartutil.ToRenderValues(cht, valsMap, RelOpts, caps)
-       if err != nil {
-               return "", fmt.Errorf("ToRenderValues failed err: %s", err)
-       }
-       // todo: // explain why there is a hack way
-       if builtIn {
-               resVals["Values"].(chartutil.Values)["enabled"] = true
-       }
-       filesMap, err := engine.Render(cht, resVals)
-       if err != nil {
-               return "", fmt.Errorf("Render chart failed err: %s", err)
-       }
-       keys := make([]string, 0, len(filesMap))
-       for key := range filesMap {
-               // remove notation files such as Notes.txt
-               if strings.HasSuffix(key, NotesFileNameSuffix) {
-                       continue
-               }
-               keys = append(keys, key)
-       }
-       // to ensure that every manifest rendered by same values are the same
-       sort.Strings(keys)
-
-       var builder strings.Builder
-       for i := 0; i < len(keys); i++ {
-               file := filesMap[keys[i]]
-               file = util.ApplyFilters(file, filters...)
-               // ignore empty manifest
-               if file == "" {
-                       continue
-               }
-               // the formatted yaml file should terminate with a newline 
separator
-               if !strings.HasSuffix(file, YAMLSeparator) {
-                       // do not add the first newline separator
-                       file += YAMLSeparator[1:]
-               }
-               builder.WriteString(file)
-       }
-
-       return builder.String(), nil
-}
-
-// locateChart locate the target chart path by sequential orders:
-// 1. find local helm repository using "name-version.tgz" format
-// 2. using downloader to pull remote chart
-func locateChart(cpOpts *action.ChartPathOptions, name string, settings 
*cli.EnvSettings) (string, error) {
-       name = strings.TrimSpace(name)
-       version := strings.TrimSpace(cpOpts.Version)
-
-       // check if it's in Helm's chart cache
-       // cacheName is hardcoded as format of helm. eg: grafana-6.31.1.tgz
-       cacheName := name + "-" + cpOpts.Version + ".tgz"
-       cachePath := path.Join(settings.RepositoryCache, cacheName)
-       if _, err := os.Stat(cachePath); err == nil {
-               abs, err := filepath.Abs(cachePath)
-               if err != nil {
-                       return abs, err
-               }
-               if cpOpts.Verify {
-                       if _, err := downloader.VerifyChart(abs, 
cpOpts.Keyring); err != nil {
-                               return "", err
-                       }
-               }
-               return abs, nil
-       }
-
-       dl := downloader.ChartDownloader{
-               Out:     os.Stdout,
-               Keyring: cpOpts.Keyring,
-               Getters: getter.All(settings),
-               Options: []getter.Option{
-                       
getter.WithPassCredentialsAll(cpOpts.PassCredentialsAll),
-                       getter.WithTLSClientConfig(cpOpts.CertFile, 
cpOpts.KeyFile, cpOpts.CaFile),
-                       
getter.WithInsecureSkipVerifyTLS(cpOpts.InsecureSkipTLSverify),
-               },
-               RepositoryConfig: settings.RepositoryConfig,
-               RepositoryCache:  settings.RepositoryCache,
-       }
-
-       if cpOpts.Verify {
-               dl.Verify = downloader.VerifyAlways
-       }
-       if cpOpts.RepoURL != "" {
-               chartURL, err := 
repo.FindChartInAuthAndTLSAndPassRepoURL(cpOpts.RepoURL, cpOpts.Username, 
cpOpts.Password, name, version,
-                       cpOpts.CertFile, cpOpts.KeyFile, cpOpts.CaFile, 
cpOpts.InsecureSkipTLSverify, cpOpts.PassCredentialsAll, getter.All(settings))
-               if err != nil {
-                       return "", err
-               }
-               name = chartURL
-
-               // Only pass the user/pass on when the user has said to or when 
the
-               // location of the chart repo and the chart are the same domain.
-               u1, err := url.Parse(cpOpts.RepoURL)
-               if err != nil {
-                       return "", err
-               }
-               u2, err := url.Parse(chartURL)
-               if err != nil {
-                       return "", err
-               }
-
-               // Host on URL (returned from url.Parse) contains the port if 
present.
-               // This check ensures credentials are not passed between 
different
-               // services on different ports.
-               if cpOpts.PassCredentialsAll || (u1.Scheme == u2.Scheme && 
u1.Host == u2.Host) {
-                       dl.Options = append(dl.Options, 
getter.WithBasicAuth(cpOpts.Username, cpOpts.Password))
-               } else {
-                       dl.Options = append(dl.Options, 
getter.WithBasicAuth("", ""))
-               }
-       } else {
-               dl.Options = append(dl.Options, 
getter.WithBasicAuth(cpOpts.Username, cpOpts.Password))
-       }
-
-       // if RepositoryCache doesn't exist, create it
-       if err := os.MkdirAll(settings.RepositoryCache, 0o755); err != nil {
-               return "", err
-       }
-
-       filename, _, err := dl.DownloadTo(name, version, 
settings.RepositoryCache)
-       if err != nil {
-               return "", err
-       }
-
-       lname, err := filepath.Abs(filename)
-       if err != nil {
-               return filename, err
-       }
-       return lname, nil
-}
diff --git a/operator/manifest/render/render_test.go 
b/operator/manifest/render/render_test.go
deleted file mode 100644
index 64fd04ca..00000000
--- a/operator/manifest/render/render_test.go
+++ /dev/null
@@ -1,907 +0,0 @@
-// 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 render
-
-import (
-       "github.com/apache/dubbo-kubernetes/operator/pkg/identifier"
-       "os"
-       "testing"
-)
-
-const (
-       TestDir       string = "testchart"
-       TestName      string = "nginx"
-       TestNamespace string = "dubbo-operator"
-)
-
-var TestFS = os.DirFS(".")
-
-func TestNewLocalRenderer(t *testing.T) {
-       tests := []struct {
-               desc    string
-               opts    []RendererOption
-               wantErr bool
-       }{
-               {
-                       desc: "correct invocation",
-                       opts: []RendererOption{
-                               WithName(TestName),
-                               WithNamespace(TestNamespace),
-                               WithFS(TestFS),
-                               WithDir(TestDir),
-                       },
-               },
-               {
-                       desc:    "missing name",
-                       opts:    []RendererOption{},
-                       wantErr: true,
-               },
-               {
-                       desc: "missing chart FS",
-                       opts: []RendererOption{
-                               WithName(TestName),
-                               WithNamespace(TestNamespace),
-                       },
-                       wantErr: true,
-               },
-               {
-                       desc: "missing chart dir",
-                       opts: []RendererOption{
-                               WithName(TestName),
-                               WithNamespace(TestNamespace),
-                               WithFS(TestFS),
-                       },
-                       wantErr: true,
-               },
-               {
-                       desc: "using default namespace",
-                       opts: []RendererOption{
-                               WithName(TestName),
-                               WithFS(TestFS),
-                               WithDir(TestDir),
-                       },
-               },
-       }
-
-       for _, test := range tests {
-               _, err := NewLocalRenderer(test.opts...)
-               if err != nil {
-                       if !test.wantErr {
-                               t.Errorf("NewLocalRenderer failed, err: %s", 
err)
-                               return
-                       }
-               }
-       }
-}
-
-func TestLocalRenderer_RenderManifest(t *testing.T) {
-       renderer, err := NewLocalRenderer(
-               WithName(TestName),
-               WithNamespace(identifier.DubboDefaultNamespace),
-               WithFS(TestFS),
-               WithDir(TestDir))
-       if err != nil {
-               t.Fatalf("NewLocalRenderer failed, err: %s", err)
-       }
-       if err := renderer.Init(); err != nil {
-               t.Fatalf("LocalRenderer Init failed, err: %s", err)
-       }
-       tests := []struct {
-               vals   string
-               expect string
-       }{
-               {
-                       vals: "",
-                       expect: `apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: nginx-testchart
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      app.kubernetes.io/name: testchart
-      app.kubernetes.io/instance: nginx
-  template:
-    metadata:
-      labels:
-        app.kubernetes.io/name: testchart
-        app.kubernetes.io/instance: nginx
-    spec:
-      serviceAccountName: nginx-testchart
-      securityContext: {}
-      containers:
-        - name: testchart
-          securityContext: {}
-          image: "nginx:1.16.0"
-          imagePullPolicy: IfNotPresent
-          ports:
-            - name: http
-              containerPort: 80
-              protocol: TCP
-          livenessProbe:
-            httpGet:
-              path: /
-              port: http
-          readinessProbe:
-            httpGet:
-              path: /
-              port: http
-          resources: {}
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: nginx-testchart
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
-spec:
-  type: ClusterIP
-  ports:
-    - port: 80
-      targetPort: http
-      protocol: TCP
-      name: http
-  selector:
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
----
-kind: ServiceAccount
-metadata:
-  name: nginx-testchart
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
----
-apiVersion: v1
-kind: Pod
-metadata:
-  name: "nginx-testchart-test-storage"
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
-  annotations:
-    "helm.sh/hook": test
-spec:
-  containers:
-    - name: wget
-      image: busybox
-      command: ['wget']
-      args: ['nginx-testchart:80']
-  restartPolicy: Never
----
-`,
-               },
-               {
-                       vals: `
-resources:
-  limits:
-    cpu: 100m
-    memory: 128Mi
-  requests:
-    cpu: 100m
-    memory: 128Mi
-`,
-                       expect: `apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: nginx-testchart
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      app.kubernetes.io/name: testchart
-      app.kubernetes.io/instance: nginx
-  template:
-    metadata:
-      labels:
-        app.kubernetes.io/name: testchart
-        app.kubernetes.io/instance: nginx
-    spec:
-      serviceAccountName: nginx-testchart
-      securityContext: {}
-      containers:
-        - name: testchart
-          securityContext: {}
-          image: "nginx:1.16.0"
-          imagePullPolicy: IfNotPresent
-          ports:
-            - name: http
-              containerPort: 80
-              protocol: TCP
-          livenessProbe:
-            httpGet:
-              path: /
-              port: http
-          readinessProbe:
-            httpGet:
-              path: /
-              port: http
-          resources:
-            limits:
-              cpu: 100m
-              memory: 128Mi
-            requests:
-              cpu: 100m
-              memory: 128Mi
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: nginx-testchart
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
-spec:
-  type: ClusterIP
-  ports:
-    - port: 80
-      targetPort: http
-      protocol: TCP
-      name: http
-  selector:
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
----
-kind: ServiceAccount
-metadata:
-  name: nginx-testchart
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
----
-apiVersion: v1
-kind: Pod
-metadata:
-  name: "nginx-testchart-test-storage"
-  labels:
-    helm.sh/chart: testchart-0.1.0
-    app.kubernetes.io/name: testchart
-    app.kubernetes.io/instance: nginx
-    app.kubernetes.io/version: "1.16.0"
-    app.kubernetes.io/managed-by: Helm
-  annotations:
-    "helm.sh/hook": test
-spec:
-  containers:
-    - name: wget
-      image: busybox
-      command: ['wget']
-      args: ['nginx-testchart:80']
-  restartPolicy: Never
----
-`,
-               },
-       }
-
-       for _, test := range tests {
-               manifest, err := renderer.RenderManifest(test.vals)
-               if err != nil {
-                       t.Fatalf("LocalRenderer RenderManifest failed, err: 
%s", err)
-               }
-               if manifest != test.expect {
-                       t.Errorf("expect %s\nbut got %s\n", test.expect, 
manifest)
-               }
-       }
-}
-
-func TestRemoteRenderer_Init(t *testing.T) {
-       rr, err := NewRemoteRenderer([]RendererOption{
-               WithName("grafana"),
-               WithNamespace(TestNamespace),
-               WithRepoURL("https://grafana.github.io/helm-charts/";),
-               WithVersion("6.31.1"),
-       }...)
-       if err != nil {
-               t.Fatalf("NewRemoteRenderer failed, err: %s", err)
-       }
-       if err := rr.Init(); err != nil {
-               t.Fatalf("RemoteRenderer failed, err: %s", err)
-       }
-}
-
-//dubbo TestRemoteRenderer_RenderManifest(t *testing.T) {
-//     renderer, err := NewRemoteRenderer([]RendererOption{
-//             WithName("grafana"),
-//             WithNamespace(TestNamespace),
-//             WithRepoURL("https://grafana.github.io/helm-charts/";),
-//             WithVersion("6.31.1"),
-//     }...)
-//     if err != nil {
-//             t.Fatalf("NewRemoteRenderer failed, err: %s", err)
-//     }
-//     if err := renderer.Init(); err != nil {
-//             t.Fatalf("RemoteRenderer failed, err: %s", err)
-//     }
-//     tests := []struct {
-//             vals   string
-//             expect string
-//     }{
-//             {
-//                     vals: "",
-//                     expect: `kind: ClusterRole
-//apiVersion: rbac.authorization.k8s.io/v1
-//metadata:
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//  name: grafana-clusterrole
-//rules: []
-//---
-//kind: ClusterRoleBinding
-//apiVersion: rbac.authorization.k8s.io/v1
-//metadata:
-//  name: grafana-clusterrolebinding
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//subjects:
-//  - kind: ServiceAccount
-//    name: grafana
-//    namespace: dubbo-operator
-//roleRef:
-//  kind: ClusterRole
-//  name: grafana-clusterrole
-//  apiGroup: rbac.authorization.k8s.io
-//---
-//apiVersion: v1
-//kind: ConfigMap
-//metadata:
-//  name: grafana
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//data:
-//  allow-snippet-annotations: "false"
-//  grafana.ini: |
-//    [analytics]
-//    check_for_updates = true
-//    [grafana_net]
-//    url = https://grafana.net
-//    [log]
-//    mode = console
-//    [paths]
-//    data = /var/lib/grafana/
-//    logs = /var/log/grafana
-//    plugins = /var/lib/grafana/plugins
-//    provisioning = /etc/grafana/provisioning
-//---
-//apiVersion: apps/v1
-//kind: Deployment
-//metadata:
-//  name: grafana
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//spec:
-//  replicas: 1
-//  revisionHistoryLimit: 10
-//  selector:
-//    matchLabels:
-//      app.kubernetes.io/name: grafana
-//      app.kubernetes.io/instance: grafana
-//  strategy:
-//    type: RollingUpdate
-//  template:
-//    metadata:
-//      labels:
-//        app.kubernetes.io/name: grafana
-//        app.kubernetes.io/instance: grafana
-//      annotations:
-//        checksum/config: 
437246927f77c7545ee3969448fa4813d7455f10583d7b2d93e89ed06d8c2259
-//        checksum/dashboards-json-config: 
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
-//        checksum/sc-dashboard-provider-config: 
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
-//        checksum/secret: 
974af8ad1507a390f6d207b529770645659e266a9aabafe285520782f9a92277
-//    spec:
-//
-//      serviceAccountName: grafana
-//      automountServiceAccountToken: true
-//      securityContext:
-//        fsGroup: 472
-//        runAsGroup: 472
-//        runAsUser: 472
-//      enableServiceLinks: true
-//      containers:
-//        - name: grafana
-//          image: "grafana/grafana:9.0.1"
-//          imagePullPolicy: IfNotPresent
-//          volumeMounts:
-//            - name: config
-//              mountPath: "/etc/grafana/grafana.ini"
-//              subPath: grafana.ini
-//            - name: storage
-//              mountPath: "/var/lib/grafana"
-//          ports:
-//            - name: service
-//              containerPort: 80
-//              protocol: TCP
-//            - name: grafana
-//              containerPort: 3000
-//              protocol: TCP
-//          env:
-//            - name: GF_SECURITY_ADMIN_USER
-//              valueFrom:
-//                secretKeyRef:
-//                  name: grafana
-//                  key: admin-user
-//            - name: GF_SECURITY_ADMIN_PASSWORD
-//              valueFrom:
-//                secretKeyRef:
-//                  name: grafana
-//                  key: admin-password
-//            - name: GF_PATHS_DATA
-//              value: /var/lib/grafana/
-//            - name: GF_PATHS_LOGS
-//              value: /var/log/grafana
-//            - name: GF_PATHS_PLUGINS
-//              value: /var/lib/grafana/plugins
-//            - name: GF_PATHS_PROVISIONING
-//              value: /etc/grafana/provisioning
-//          livenessProbe:
-//            failureThreshold: 10
-//            httpGet:
-//              path: /api/health
-//              port: 3000
-//            initialDelaySeconds: 60
-//            timeoutSeconds: 30
-//          readinessProbe:
-//            httpGet:
-//              path: /api/health
-//              port: 3000
-//          resources:
-//            {}
-//      volumes:
-//        - name: config
-//          configMap:
-//            name: grafana
-//        - name: storage
-//          emptyDir: {}
-//---
-//apiVersion: policy/v1beta1
-//kind: PodSecurityPolicy
-//metadata:
-//  name: grafana
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//  annotations:
-//    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 
'docker/default,runtime/default'
-//    seccomp.security.alpha.kubernetes.io/defaultProfileName:  
'docker/default'
-//    apparmor.security.beta.kubernetes.io/allowedProfileNames: 
'runtime/default'
-//    apparmor.security.beta.kubernetes.io/defaultProfileName:  
'runtime/default'
-//spec:
-//  privileged: false
-//  allowPrivilegeEscalation: false
-//  requiredDropCapabilities:
-//    # Default set from Docker, with DAC_OVERRIDE and CHOWN
-//      - ALL
-//  volumes:
-//    - 'configMap'
-//    - 'emptyDir'
-//    - 'projected'
-//    - 'csi'
-//    - 'secret'
-//    - 'downwardAPI'
-//    - 'persistentVolumeClaim'
-//  hostNetwork: false
-//  hostIPC: false
-//  hostPID: false
-//  runAsUser:
-//    rule: 'RunAsAny'
-//  seLinux:
-//    rule: 'RunAsAny'
-//  supplementalGroups:
-//    rule: 'MustRunAs'
-//    ranges:
-//      # Forbid adding the root group.
-//      - min: 1
-//        max: 65535
-//  fsGroup:
-//    rule: 'MustRunAs'
-//    ranges:
-//      # Forbid adding the root group.
-//      - min: 1
-//        max: 65535
-//  readOnlyRootFilesystem: false
-//---
-//apiVersion: rbac.authorization.k8s.io/v1
-//kind: Role
-//metadata:
-//  name: grafana
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//rules:
-//- apiGroups:      ['extensions']
-//  resources:      ['podsecuritypolicies']
-//  verbs:          ['use']
-//  resourceNames:  [grafana]
-//---
-//apiVersion: rbac.authorization.k8s.io/v1
-//kind: RoleBinding
-//metadata:
-//  name: grafana
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//roleRef:
-//  apiGroup: rbac.authorization.k8s.io
-//  kind: Role
-//  name: grafana
-//subjects:
-//- kind: ServiceAccount
-//  name: grafana
-//  namespace: dubbo-operator
-//---
-//apiVersion: v1
-//kind: Secret
-//metadata:
-//  name: grafana
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//type: Opaque
-//data:
-//  admin-user: "YWRtaW4="
-//  admin-password: "UTRGSmJCeGJIYmk4RzJLdW1ZSjNGRkE1bWdnVmVnZDQzdHJteEFWSQ=="
-//  ldap-toml: ""
-//---
-//apiVersion: v1
-//kind: Service
-//metadata:
-//  name: grafana
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//spec:
-//  type: ClusterIP
-//  ports:
-//    - name: service
-//      port: 80
-//      protocol: TCP
-//      targetPort: 3000
-//  selector:
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//---
-//apiVersion: v1
-//kind: ServiceAccount
-//metadata:
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//  name: grafana
-//  namespace: dubbo-operator
-//---
-//apiVersion: v1
-//kind: ConfigMap
-//metadata:
-//  name: grafana-test
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//data:
-//  run.sh: |-
-//    @test "Test Health" {
-//      url="http://grafana/api/health";
-//      code=$(wget --cp-server-response --spider --timeout 10 --tries 1 
${url} 2>&1 | awk '/^  HTTP/{print $2}')
-//      [ "$code" == "200" ]
-//    }
-//---
-//apiVersion: policy/v1beta1
-//kind: PodSecurityPolicy
-//metadata:
-//  name: grafana-test
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//spec:
-//  allowPrivilegeEscalation: true
-//  privileged: false
-//  hostNetwork: false
-//  hostIPC: false
-//  hostPID: false
-//  fsGroup:
-//    rule: RunAsAny
-//  seLinux:
-//    rule: RunAsAny
-//  supplementalGroups:
-//    rule: RunAsAny
-//  runAsUser:
-//    rule: RunAsAny
-//  volumes:
-//  - configMap
-//  - downwardAPI
-//  - emptyDir
-//  - projected
-//  - csi
-//  - secret
-//---
-//apiVersion: rbac.authorization.k8s.io/v1
-//kind: Role
-//metadata:
-//  name: grafana-test
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//rules:
-//- apiGroups:      ['policy']
-//  resources:      ['podsecuritypolicies']
-//  verbs:          ['use']
-//  resourceNames:  [grafana-test]
-//---
-//apiVersion: rbac.authorization.k8s.io/v1
-//kind: RoleBinding
-//metadata:
-//  name: grafana-test
-//  namespace: dubbo-operator
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//roleRef:
-//  apiGroup: rbac.authorization.k8s.io
-//  kind: Role
-//  name: grafana-test
-//subjects:
-//- kind: ServiceAccount
-//  name: grafana-test
-//  namespace: dubbo-operator
-//---
-//apiVersion: v1
-//kind: ServiceAccount
-//metadata:
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//  name: grafana-test
-//  namespace: dubbo-operator
-//---
-//apiVersion: v1
-//kind: Pod
-//metadata:
-//  name: grafana-test
-//  labels:
-//    helm.sh/chart: grafana-6.31.1
-//    app.kubernetes.io/name: grafana
-//    app.kubernetes.io/instance: grafana
-//    app.kubernetes.io/version: "9.0.1"
-//    app.kubernetes.io/managed-by: Helm
-//  annotations:
-//    "helm.sh/hook": test-success
-//    "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
-//  namespace: dubbo-operator
-//spec:
-//  serviceAccountName: grafana-test
-//  containers:
-//    - name: grafana-test
-//      image: "bats/bats:v1.4.1"
-//      imagePullPolicy: "IfNotPresent"
-//      command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"]
-//      volumeMounts:
-//        - mountPath: /tests
-//          name: tests
-//          readOnly: true
-//  volumes:
-//  - name: tests
-//    configMap:
-//      name: grafana-test
-//  restartPolicy: Never
-//---
-//`,
-//             },
-//             {
-//                     vals: `
-//testFramework:
-//  enabled: false
-//`,
-//                     expect: `apiVersion: apps/v1
-//kind: Deployment
-//metadata:
-//  name: nginx-testchart
-//  labels:
-//    helm.sh/chart: testchart-0.1.0
-//    app.kubernetes.io/name: testchart
-//    app.kubernetes.io/instance: nginx
-//    app.kubernetes.io/version: "1.16.0"
-//    app.kubernetes.io/managed-by: Helm
-//spec:
-//  replicas: 1
-//  selector:
-//    matchLabels:
-//      app.kubernetes.io/name: testchart
-//      app.kubernetes.io/instance: nginx
-//  template:
-//    metadata:
-//      labels:
-//        app.kubernetes.io/name: testchart
-//        app.kubernetes.io/instance: nginx
-//    spec:
-//      serviceAccountName: nginx-testchart
-//      securityContext:
-//        {}
-//      containers:
-//        - name: testchart
-//          securityContext:
-//            {}
-//          image: "nginx:1.16.0"
-//          imagePullPolicy: IfNotPresent
-//          ports:
-//            - name: http
-//              containerPort: 80
-//              protocol: TCP
-//          livenessProbe:
-//            httpGet:
-//              path: /
-//              port: http
-//          readinessProbe:
-//            httpGet:
-//              path: /
-//              port: http
-//          resources:
-//            limits:
-//              cpu: 100m
-//              memory: 128Mi
-//            requests:
-//              cpu: 100m
-//              memory: 128Mi
-//---
-//apiVersion: v1
-//kind: Service
-//metadata:
-//  name: nginx-testchart
-//  labels:
-//    helm.sh/chart: testchart-0.1.0
-//    app.kubernetes.io/name: testchart
-//    app.kubernetes.io/instance: nginx
-//    app.kubernetes.io/version: "1.16.0"
-//    app.kubernetes.io/managed-by: Helm
-//spec:
-//  type: ClusterIP
-//  ports:
-//    - port: 80
-//      targetPort: http
-//      protocol: TCP
-//      name: http
-//  selector:
-//    app.kubernetes.io/name: testchart
-//    app.kubernetes.io/instance: nginx
-//---
-//kind: ServiceAccount
-//metadata:
-//  name: nginx-testchart
-//  labels:
-//    helm.sh/chart: testchart-0.1.0
-//    app.kubernetes.io/name: testchart
-//    app.kubernetes.io/instance: nginx
-//    app.kubernetes.io/version: "1.16.0"
-//    app.kubernetes.io/managed-by: Helm
-//---
-//apiVersion: v1
-//kind: Pod
-//metadata:
-//  name: "nginx-testchart-test-storage"
-//  labels:
-//    helm.sh/chart: testchart-0.1.0
-//    app.kubernetes.io/name: testchart
-//    app.kubernetes.io/instance: nginx
-//    app.kubernetes.io/version: "1.16.0"
-//    app.kubernetes.io/managed-by: Helm
-//  annotations:
-//    "helm.sh/hook": test
-//spec:
-//  containers:
-//    - name: wget
-//      image: busybox
-//      command: ['wget']
-//      args: ['nginx-testchart:80']
-//  restartPolicy: Never
-//---
-//`,
-//             },
-//     }
-//
-//     for _, test := range tests {
-//             manifest, err := renderer.RenderManifest(test.vals)
-//             if err != nil {
-//                     t.Fatalf("RemoteRenderer RenderManifest failed, err: 
%s", err)
-//             }
-//             if manifest != test.expect {
-//                     t.Errorf("expect %s\nbut got %s\n", test.expect, 
manifest)
-//                     return
-//             }
-//     }
-//}
diff --git a/operator/manifest/render/testchart/.helmignore 
b/operator/manifest/render/testchart/.helmignore
deleted file mode 100644
index 0e8a0eb3..00000000
--- a/operator/manifest/render/testchart/.helmignore
+++ /dev/null
@@ -1,23 +0,0 @@
-# Patterns to ignore when building packages.
-# This supports shell glob matching, relative path matching, and
-# negation (prefixed with !). Only one pattern per line.
-.DS_Store
-# Common VCS dirs
-.git/
-.gitignore
-.bzr/
-.bzrignore
-.hg/
-.hgignore
-.svn/
-# Common backup files
-*.swp
-*.bak
-*.tmp
-*.orig
-*~
-# Various IDEs
-.project
-.idea/
-*.tmproj
-.vscode/
diff --git a/operator/manifest/render/testchart/Chart.yaml 
b/operator/manifest/render/testchart/Chart.yaml
deleted file mode 100644
index 853a3479..00000000
--- a/operator/manifest/render/testchart/Chart.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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: v2
-name: testchart
-description: A Helm chart for Kubernetes
-
-# A chart can be either an 'application' or a 'library' chart.
-#
-# Application charts are a collection of templates that can be packaged into 
versioned archives
-# to be deployed.
-#
-# Library charts provide useful utilities or functions for the chart 
developer. They're included as
-# a dependency of application charts to inject those utilities and functions 
into the rendering
-# pipeline. Library charts do not define any templates and therefore cannot be 
deployed.
-type: application
-
-# This is the chart version. This version number should be incremented each 
time you make changes
-# to the chart and its templates, including the app version.
-# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 0.1.0
-
-# This is the version number of the application being deployed. This version 
number should be
-# incremented each time you make changes to the application. Versions are not 
expected to
-# follow Semantic Versioning. They should reflect the version the application 
is using.
-# It is recommended to use it with quotes.
-appVersion: "1.16.0"
diff --git a/operator/manifest/render/testchart/templates/NOTES.txt 
b/operator/manifest/render/testchart/templates/NOTES.txt
deleted file mode 100644
index 45e51670..00000000
--- a/operator/manifest/render/testchart/templates/NOTES.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-1. Get the application URL by running these commands:
-{{- if .Values.ingress.enabled }}
-{{- range $host := .Values.ingress.hosts }}
-  {{- range .paths }}
-  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
-  {{- end }}
-{{- end }}
-{{- else if contains "NodePort" .Values.service.type }}
-  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o 
jsonpath="{.spec.ports[0].nodePort}" services {{ include "testchart.fullname" . 
}})
-  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o 
jsonpath="{.items[0].status.addresses[0].address}")
-  echo http://$NODE_IP:$NODE_PORT
-{{- else if contains "LoadBalancer" .Values.service.type }}
-     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
-           You can watch the status of by running 'kubectl get --namespace {{ 
.Release.Namespace }} svc -w {{ include "testchart.fullname" . }}'
-  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ 
include "testchart.fullname" . }} --template "{{"{{ range (index 
.status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
-  echo http://$SERVICE_IP:{{ .Values.service.port }}
-{{- else if contains "ClusterIP" .Values.service.type }}
-  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l 
"app.kubernetes.io/name={{ include "testchart.name" . 
}},app.kubernetes.io/instance={{ .Release.Name }}" -o 
jsonpath="{.items[0].metadata.name}")
-  export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} 
$POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
-  echo "Visit http://127.0.0.1:8080 to use your application"
-  kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 
8080:$CONTAINER_PORT
-{{- end }}
diff --git a/operator/manifest/render/testchart/templates/_helpers.tpl 
b/operator/manifest/render/testchart/templates/_helpers.tpl
deleted file mode 100644
index 4b0db05b..00000000
--- a/operator/manifest/render/testchart/templates/_helpers.tpl
+++ /dev/null
@@ -1,62 +0,0 @@
-{{/*
-Expand the name of the chart.
-*/}}
-{{- define "testchart.name" -}}
-{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Create a default fully qualified app name.
-We truncate at 63 chars because some Kubernetes name fields are limited to 
this (by the DNS naming spec).
-If release name contains chart name it will be used as a full name.
-*/}}
-{{- define "testchart.fullname" -}}
-{{- if .Values.fullnameOverride }}
-{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
-{{- else }}
-{{- $name := default .Chart.Name .Values.nameOverride }}
-{{- if contains $name .Release.Name }}
-{{- .Release.Name | trunc 63 | trimSuffix "-" }}
-{{- else }}
-{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
-{{- end }}
-{{- end }}
-{{- end }}
-
-{{/*
-Create chart name and version as used by the chart label.
-*/}}
-{{- define "testchart.chart" -}}
-{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 
trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Common labels
-*/}}
-{{- define "testchart.labels" -}}
-helm.sh/chart: {{ include "testchart.chart" . }}
-{{ include "testchart.selectorLabels" . }}
-{{- if .Chart.AppVersion }}
-app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
-{{- end }}
-app.kubernetes.io/managed-by: {{ .Release.Service }}
-{{- end }}
-
-{{/*
-Selector labels
-*/}}
-{{- define "testchart.selectorLabels" -}}
-app.kubernetes.io/name: {{ include "testchart.name" . }}
-app.kubernetes.io/instance: {{ .Release.Name }}
-{{- end }}
-
-{{/*
-Create the name of the service account to use
-*/}}
-{{- define "testchart.serviceAccountName" -}}
-{{- if .Values.serviceAccount.create }}
-{{- default (include "testchart.fullname" .) .Values.serviceAccount.name }}
-{{- else }}
-{{- default "default" .Values.serviceAccount.name }}
-{{- end }}
-{{- end }}
diff --git a/operator/manifest/render/testchart/templates/deployment.yaml 
b/operator/manifest/render/testchart/templates/deployment.yaml
deleted file mode 100644
index 4c86e0a2..00000000
--- a/operator/manifest/render/testchart/templates/deployment.yaml
+++ /dev/null
@@ -1,76 +0,0 @@
-# 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: apps/v1
-kind: Deployment
-metadata:
-  name: {{ include "testchart.fullname" . }}
-  labels:
-    {{- include "testchart.labels" . | nindent 4 }}
-spec:
-  {{- if not .Values.autoscaling.enabled }}
-  replicas: {{ .Values.replicaCount }}
-  {{- end }}
-  selector:
-    matchLabels:
-      {{- include "testchart.selectorLabels" . | nindent 6 }}
-  template:
-    metadata:
-      {{- with .Values.podAnnotations }}
-      annotations:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
-      labels:
-        {{- include "testchart.selectorLabels" . | nindent 8 }}
-    spec:
-      {{- with .Values.imagePullSecrets }}
-      imagePullSecrets:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
-      serviceAccountName: {{ include "testchart.serviceAccountName" . }}
-      securityContext:
-        {{- toYaml .Values.podSecurityContext | nindent 8 }}
-      containers:
-        - name: {{ .Chart.Name }}
-          securityContext:
-            {{- toYaml .Values.securityContext | nindent 12 }}
-          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | 
default .Chart.AppVersion }}"
-          imagePullPolicy: {{ .Values.image.pullPolicy }}
-          ports:
-            - name: http
-              containerPort: {{ .Values.service.port }}
-              protocol: TCP
-          livenessProbe:
-            httpGet:
-              path: /
-              port: http
-          readinessProbe:
-            httpGet:
-              path: /
-              port: http
-          resources:
-            {{- toYaml .Values.resources | nindent 12 }}
-      {{- with .Values.nodeSelector }}
-      nodeSelector:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
-      {{- with .Values.affinity }}
-      affinity:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
-      {{- with .Values.tolerations }}
-      tolerations:
-        {{- toYaml . | nindent 8 }}
-      {{- end }}
diff --git a/operator/manifest/render/testchart/templates/hpa.yaml 
b/operator/manifest/render/testchart/templates/hpa.yaml
deleted file mode 100644
index d57408d4..00000000
--- a/operator/manifest/render/testchart/templates/hpa.yaml
+++ /dev/null
@@ -1,43 +0,0 @@
-# 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.
-
-{{- if .Values.autoscaling.enabled }}
-apiVersion: autoscaling/v2beta1
-kind: HorizontalPodAutoscaler
-metadata:
-  name: {{ include "testchart.fullname" . }}
-  labels:
-    {{- include "testchart.labels" . | nindent 4 }}
-spec:
-  scaleTargetRef:
-    apiVersion: apps/v1
-    kind: Deployment
-    name: {{ include "testchart.fullname" . }}
-  minReplicas: {{ .Values.autoscaling.minReplicas }}
-  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
-  metrics:
-    {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
-    - type: Resource
-      resource:
-        name: cpu
-        targetAverageUtilization: {{ 
.Values.autoscaling.targetCPUUtilizationPercentage }}
-    {{- end }}
-    {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
-    - type: Resource
-      resource:
-        name: memory
-        targetAverageUtilization: {{ 
.Values.autoscaling.targetMemoryUtilizationPercentage }}
-    {{- end }}
-{{- end }}
diff --git a/operator/manifest/render/testchart/templates/ingress.yaml 
b/operator/manifest/render/testchart/templates/ingress.yaml
deleted file mode 100644
index ce1c3440..00000000
--- a/operator/manifest/render/testchart/templates/ingress.yaml
+++ /dev/null
@@ -1,76 +0,0 @@
-# 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.
-
-{{- if .Values.ingress.enabled -}}
-{{- $fullName := include "testchart.fullname" . -}}
-{{- $svcPort := .Values.service.port -}}
-{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" 
.Capabilities.KubeVersion.GitVersion)) }}
-  {{- if not (hasKey .Values.ingress.annotations 
"kubernetes.io/ingress.class") }}
-  {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" 
.Values.ingress.className}}
-  {{- end }}
-{{- end }}
-{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
-apiVersion: networking.k8s.io/v1
-{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
-apiVersion: networking.k8s.io/v1beta1
-{{- else -}}
-apiVersion: extensions/v1beta1
-{{- end }}
-kind: Ingress
-metadata:
-  name: {{ $fullName }}
-  labels:
-    {{- include "testchart.labels" . | nindent 4 }}
-  {{- with .Values.ingress.annotations }}
-  annotations:
-    {{- toYaml . | nindent 4 }}
-  {{- end }}
-spec:
-  {{- if and .Values.ingress.className (semverCompare ">=1.18-0" 
.Capabilities.KubeVersion.GitVersion) }}
-  ingressClassName: {{ .Values.ingress.className }}
-  {{- end }}
-  {{- if .Values.ingress.tls }}
-  tls:
-    {{- range .Values.ingress.tls }}
-    - hosts:
-        {{- range .hosts }}
-        - {{ . | quote }}
-        {{- end }}
-      secretName: {{ .secretName }}
-    {{- end }}
-  {{- end }}
-  rules:
-    {{- range .Values.ingress.hosts }}
-    - host: {{ .host | quote }}
-      http:
-        paths:
-          {{- range .paths }}
-          - path: {{ .path }}
-            {{- if and .pathType (semverCompare ">=1.18-0" 
$.Capabilities.KubeVersion.GitVersion) }}
-            pathType: {{ .pathType }}
-            {{- end }}
-            backend:
-              {{- if semverCompare ">=1.19-0" 
$.Capabilities.KubeVersion.GitVersion }}
-              service:
-                name: {{ $fullName }}
-                port:
-                  number: {{ $svcPort }}
-              {{- else }}
-              serviceName: {{ $fullName }}
-              servicePort: {{ $svcPort }}
-              {{- end }}
-          {{- end }}
-    {{- end }}
-{{- end }}
diff --git a/operator/manifest/render/testchart/templates/service.yaml 
b/operator/manifest/render/testchart/templates/service.yaml
deleted file mode 100644
index 53da2abf..00000000
--- a/operator/manifest/render/testchart/templates/service.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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: Service
-metadata:
-  name: {{ include "testchart.fullname" . }}
-  labels:
-    {{- include "testchart.labels" . | nindent 4 }}
-spec:
-  type: {{ .Values.service.type }}
-  ports:
-    - port: {{ .Values.service.port }}
-      targetPort: http
-      protocol: TCP
-      name: http
-  selector:
-    {{- include "testchart.selectorLabels" . | nindent 4 }}
diff --git a/operator/manifest/render/testchart/templates/serviceaccount.yaml 
b/operator/manifest/render/testchart/templates/serviceaccount.yaml
deleted file mode 100644
index 1fe47c05..00000000
--- a/operator/manifest/render/testchart/templates/serviceaccount.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.
-
-{{- if .Values.serviceAccount.create -}}
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: {{ include "testchart.serviceAccountName" . }}
-  labels:
-    {{- include "testchart.labels" . | nindent 4 }}
-  {{- with .Values.serviceAccount.annotations }}
-  annotations:
-    {{- toYaml . | nindent 4 }}
-  {{- end }}
-{{- end }}
diff --git 
a/operator/manifest/render/testchart/templates/tests/test-connection.yaml 
b/operator/manifest/render/testchart/templates/tests/test-connection.yaml
deleted file mode 100644
index d963d60b..00000000
--- a/operator/manifest/render/testchart/templates/tests/test-connection.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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: Pod
-metadata:
-  name: "{{ include "testchart.fullname" . }}-test-storage"
-  labels:
-    {{- include "testchart.labels" . | nindent 4 }}
-  annotations:
-    "helm.sh/hook": test
-spec:
-  containers:
-    - name: wget
-      image: busybox
-      command: ['wget']
-      args: ['{{ include "testchart.fullname" . }}:{{ .Values.service.port }}']
-  restartPolicy: Never
diff --git a/operator/manifest/render/testchart/values.yaml 
b/operator/manifest/render/testchart/values.yaml
deleted file mode 100644
index 77220982..00000000
--- a/operator/manifest/render/testchart/values.yaml
+++ /dev/null
@@ -1,97 +0,0 @@
-# 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.
-
-# Default values for testchart.
-# This is a YAML-formatted file.
-# Declare variables to be passed into your templates.
-
-replicaCount: 1
-
-image:
-  repository: nginx
-  pullPolicy: IfNotPresent
-  # Overrides the image tag whose default is the chart appVersion.
-  tag: ""
-
-imagePullSecrets: []
-nameOverride: ""
-fullnameOverride: ""
-
-serviceAccount:
-  # Specifies whether a service account should be created
-  create: true
-  # Annotations to add to the service account
-  annotations: {}
-  # The name of the service account to use.
-  # If not set and create is true, a name is generated using the fullname 
template
-  name: ""
-
-podAnnotations: {}
-
-podSecurityContext: {}
-  # fsGroup: 2000
-
-securityContext: {}
-  # capabilities:
-  #   drop:
-  #   - ALL
-  # readOnlyRootFilesystem: true
-  # runAsNonRoot: true
-  # runAsUser: 1000
-
-service:
-  type: ClusterIP
-  port: 80
-
-ingress:
-  enabled: false
-  className: ""
-  annotations: {}
-    # kubernetes.io/ingress.class: nginx
-    # kubernetes.io/tls-acme: "true"
-  hosts:
-    - host: chart-example.local
-      paths:
-        - path: /
-          pathType: ImplementationSpecific
-  tls: []
-  #  - secretName: chart-example-tls
-  #    hosts:
-  #      - chart-example.local
-
-resources: {}
-  # We usually recommend not to specify default resources and to leave this as 
a conscious
-  # choice for the user. This also increases chances charts run on 
environments with little
-  # resources, such as Minikube. If you do want to specify resources, 
uncomment the following
-  # lines, adjust them as necessary, and remove the curly braces after 
'resources:'.
-  # limits:
-  #   cpu: 100m
-  #   memory: 128Mi
-  # requests:
-  #   cpu: 100m
-  #   memory: 128Mi
-
-autoscaling:
-  enabled: false
-  minReplicas: 1
-  maxReplicas: 100
-  targetCPUUtilizationPercentage: 80
-  # targetMemoryUtilizationPercentage: 80
-
-nodeSelector: {}
-
-tolerations: []
-
-affinity: {}
diff --git a/operator/manifest/tree.go b/operator/manifest/tree.go
deleted file mode 100644
index 4446b9d2..00000000
--- a/operator/manifest/tree.go
+++ /dev/null
@@ -1,566 +0,0 @@
-// 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.
-
-// Copyright Istio Authors
-//
-// Licensed 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 manifest
-
-import (
-       "encoding/json"
-       "errors"
-       "fmt"
-       util2 "github.com/apache/dubbo-kubernetes/operator/pkg/util"
-       "reflect"
-       "regexp"
-       "strconv"
-       "strings"
-)
-
-import (
-       "gopkg.in/yaml.v3"
-
-       yaml2 "sigs.k8s.io/yaml"
-)
-
-// PathContext provides a means for traversing a tree towards the root.
-type PathContext struct {
-       // Parent in the Parent of this PathContext.
-       Parent *PathContext
-       // KeyToChild is the key required to reach the child.
-       KeyToChild interface{}
-       // Node is the actual Node in the data tree.
-       Node interface{}
-}
-
-// String implements the Stringer interface.
-func (nc *PathContext) String() string {
-       ret := "\n--------------- NodeContext ------------------\n"
-       if nc.Parent != nil {
-               ret += fmt.Sprintf("Parent.Node=\n%s\n", nc.Parent.Node)
-               ret += fmt.Sprintf("KeyToChild=%v\n", nc.Parent.KeyToChild)
-       }
-
-       ret += fmt.Sprintf("Node=\n%s\n", nc.Node)
-       ret += "----------------------------------------------\n"
-
-       return ret
-}
-
-// GetPathContext returns the PathContext for the Node which has the given 
path from root.
-// It returns false and no error if the given path is not found, or an error 
code in other error situations, like
-// a malformed path.
-// It also creates a tree of PathContexts during the traversal so that Parent 
nodes can be updated if required. This is
-// required when (say) appending to a list, where the parent list itself must 
be updated.
-func GetPathContext(root interface{}, path util2.Path, createMissing bool) 
(*PathContext, bool, error) {
-       return getPathContext(&PathContext{Node: root}, path, path, 
createMissing)
-}
-
-// WritePathContext writes the given value to the Node in the given 
PathContext.
-func WritePathContext(nc *PathContext, value interface{}, merge bool) error {
-       if !util2.IsValueNil(value) {
-               return setPathContext(nc, value, merge)
-       }
-
-       if nc.Parent == nil {
-               return errors.New("cannot delete root element")
-       }
-
-       switch {
-       case isSliceOrPtrInterface(nc.Parent.Node):
-               if err := util2.DeleteFromSlicePtr(nc.Parent.Node, 
nc.Parent.KeyToChild.(int)); err != nil {
-                       return err
-               }
-               if isMapOrInterface(nc.Parent.Parent.Node) {
-                       return util2.InsertIntoMap(nc.Parent.Parent.Node, 
nc.Parent.Parent.KeyToChild, nc.Parent.Node)
-               }
-               // TODO: The case of deleting a list.list.node element is not 
currently supported.
-               return fmt.Errorf("cannot delete path: unsupported 
parent.parent type %T for delete", nc.Parent.Parent.Node)
-       case util2.IsMap(nc.Parent.Node):
-               return util2.DeleteFromMap(nc.Parent.Node, nc.Parent.KeyToChild)
-       default:
-       }
-       return fmt.Errorf("cannot delete path: unsupported parent type %T for 
delete", nc.Parent.Node)
-}
-
-// WriteNode writes value to the tree in root at the given path, creating any 
required missing internal nodes in path.
-func WriteNode(root interface{}, path util2.Path, value interface{}) error {
-       pc, _, err := getPathContext(&PathContext{Node: root}, path, path, true)
-       if err != nil {
-               return err
-       }
-       return WritePathContext(pc, value, false)
-}
-
-// MergeNode merges value to the tree in root at the given path, creating any 
required missing internal nodes in path.
-func MergeNode(root interface{}, path util2.Path, value interface{}) error {
-       pc, _, err := getPathContext(&PathContext{Node: root}, path, path, true)
-       if err != nil {
-               return err
-       }
-       return WritePathContext(pc, value, true)
-}
-
-// Find returns the value at path from the given tree, or false if the path 
does not exist.
-// It behaves differently from GetPathContext in that it never creates map 
entries at the leaf and does not provide
-// a way to mutate the parent of the found node.
-func Find(inputTree map[string]interface{}, path util2.Path) (interface{}, 
bool, error) {
-       if len(path) == 0 {
-               return nil, false, fmt.Errorf("path is empty")
-       }
-       node, found := find(inputTree, path)
-       return node, found, nil
-}
-
-// Delete sets value at path of input untyped tree to nil
-func Delete(root map[string]interface{}, path util2.Path) (bool, error) {
-       pc, _, err := getPathContext(&PathContext{Node: root}, path, path, 
false)
-       if err != nil {
-               return false, err
-       }
-       return true, WritePathContext(pc, nil, false)
-}
-
-// getPathContext is the internal implementation of GetPathContext.
-// If createMissing is true, it creates any missing map (but NOT list) path 
entries in root.
-func getPathContext(nc *PathContext, fullPath, remainPath util2.Path, 
createMissing bool) (*PathContext, bool, error) {
-       if len(remainPath) == 0 {
-               return nc, true, nil
-       }
-       pe := remainPath[0]
-
-       if nc.Node == nil {
-               if !createMissing {
-                       return nil, false, fmt.Errorf("node %s is zero", pe)
-               }
-               if util2.IsNPathElement(pe) || util2.IsKVPathElement(pe) {
-                       nc.Node = []interface{}{}
-               } else {
-                       nc.Node = make(map[string]interface{})
-               }
-       }
-
-       v := reflect.ValueOf(nc.Node)
-       if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
-               v = v.Elem()
-       }
-       ncNode := v.Interface()
-
-       // For list types, we need a key to identify the selected list item. 
This can be either a value key of the
-       // form :matching_value in the case of a leaf list, or a matching 
key:value in the case of a non-leaf list.
-       if lst, ok := ncNode.([]interface{}); ok {
-               // If the path element has the form [N], a list element is 
being selected by index. Return the element at index
-               // N if it exists.
-               if util2.IsNPathElement(pe) {
-                       idx, err := util2.PathN(pe)
-                       if err != nil {
-                               return nil, false, fmt.Errorf("path %s, index 
%s: %s", fullPath, pe, err)
-                       }
-                       var foundNode interface{}
-                       if idx >= len(lst) || idx < 0 {
-                               if !createMissing {
-                                       return nil, false, fmt.Errorf("index %d 
exceeds list length %d at path %s", idx, len(lst), remainPath)
-                               }
-                               idx = len(lst)
-                               foundNode = make(map[string]interface{})
-                       } else {
-                               foundNode = lst[idx]
-                       }
-                       nn := &PathContext{
-                               Parent: nc,
-                               Node:   foundNode,
-                       }
-                       nc.KeyToChild = idx
-                       return getPathContext(nn, fullPath, remainPath[1:], 
createMissing)
-               }
-
-               // Otherwise the path element must have form [key:value]. In 
this case, go through all list elements, which
-               // must have map type, and try to find one which has a matching 
key:value.
-               for idx, le := range lst {
-                       // non-leaf list, expect to match item by key:value.
-                       if lm, ok := le.(map[interface{}]interface{}); ok {
-                               k, v, err := util2.PathKV(pe)
-                               if err != nil {
-                                       return nil, false, fmt.Errorf("path %s: 
%s", fullPath, err)
-                               }
-                               if stringsEqual(lm[k], v) {
-                                       nn := &PathContext{
-                                               Parent: nc,
-                                               Node:   lm,
-                                       }
-                                       nc.KeyToChild = idx
-                                       nn.KeyToChild = k
-                                       if len(remainPath) == 1 {
-                                               return nn, true, nil
-                                       }
-                                       return getPathContext(nn, fullPath, 
remainPath[1:], createMissing)
-                               }
-                               continue
-                       }
-                       // repeat of the block above for the case where tree 
unmarshals to map[string]interface{}. There doesn't
-                       // seem to be a way to merge this case into the above 
block.
-                       if lm, ok := le.(map[string]interface{}); ok {
-                               k, v, err := util2.PathKV(pe)
-                               if err != nil {
-                                       return nil, false, fmt.Errorf("path %s: 
%s", fullPath, err)
-                               }
-                               if stringsEqual(lm[k], v) {
-                                       nn := &PathContext{
-                                               Parent: nc,
-                                               Node:   lm,
-                                       }
-                                       nc.KeyToChild = idx
-                                       nn.KeyToChild = k
-                                       if len(remainPath) == 1 {
-                                               return nn, true, nil
-                                       }
-                                       return getPathContext(nn, fullPath, 
remainPath[1:], createMissing)
-                               }
-                               continue
-                       }
-                       // leaf list, expect path element [V], match based on 
value V.
-                       v, err := util2.PathV(pe)
-                       if err != nil {
-                               return nil, false, fmt.Errorf("path %s: %s", 
fullPath, err)
-                       }
-                       if matchesRegex(v, le) {
-                               nn := &PathContext{
-                                       Parent: nc,
-                                       Node:   le,
-                               }
-                               nc.KeyToChild = idx
-                               return getPathContext(nn, fullPath, 
remainPath[1:], createMissing)
-                       }
-               }
-               return nil, false, fmt.Errorf("path %s: element %s not found", 
fullPath, pe)
-       }
-
-       if util2.IsMap(ncNode) {
-               var nn interface{}
-               if m, ok := ncNode.(map[interface{}]interface{}); ok {
-                       nn, ok = m[pe]
-                       if !ok {
-                               // remainPath == 1 means the patch is creation 
of a new leaf.
-                               if createMissing || len(remainPath) == 1 {
-                                       m[pe] = 
make(map[interface{}]interface{})
-                                       nn = m[pe]
-                               } else {
-                                       return nil, false, fmt.Errorf("path not 
found at element %s in path %s", pe, fullPath)
-                               }
-                       }
-               }
-               if reflect.ValueOf(ncNode).IsNil() {
-                       ncNode = make(map[string]interface{})
-                       nc.Node = ncNode
-               }
-               if m, ok := ncNode.(map[string]interface{}); ok {
-                       nn, ok = m[pe]
-                       if !ok {
-                               // remainPath == 1 means the patch is creation 
of a new leaf.
-                               if createMissing || len(remainPath) == 1 {
-                                       nextElementNPath := len(remainPath) > 1 
&& util2.IsNPathElement(remainPath[1])
-                                       if nextElementNPath {
-                                               m[pe] = make([]interface{}, 0)
-                                       } else {
-                                               m[pe] = 
make(map[string]interface{})
-                                       }
-                                       nn = m[pe]
-                               } else {
-                                       return nil, false, fmt.Errorf("path not 
found at element %s in path %s", pe, fullPath)
-                               }
-                       }
-               }
-
-               npc := &PathContext{
-                       Parent: nc,
-                       Node:   nn,
-               }
-               // for slices, use the address so that the slice can be mutated.
-               if util2.IsSlice(nn) {
-                       npc.Node = &nn
-               }
-               nc.KeyToChild = pe
-               return getPathContext(npc, fullPath, remainPath[1:], 
createMissing)
-       }
-
-       return nil, false, fmt.Errorf("leaf type %T in non-leaf Node %s", 
nc.Node, remainPath)
-}
-
-// setPathContext writes the given value to the Node in the given PathContext,
-// enlarging all PathContext lists to ensure all indexes are valid.
-func setPathContext(nc *PathContext, value interface{}, merge bool) error {
-       processParent, err := setValueContext(nc, value, merge)
-       if err != nil || !processParent {
-               return err
-       }
-
-       // If the path included insertions, process them now
-       if nc.Parent.Parent == nil {
-               return nil
-       }
-       return setPathContext(nc.Parent, nc.Parent.Node, false) // note: tail 
recursive
-}
-
-// setValueContext writes the given value to the Node in the given PathContext.
-// If setting the value requires growing the final slice, grows it.
-func setValueContext(nc *PathContext, value interface{}, merge bool) (bool, 
error) {
-       if nc.Parent == nil {
-               return false, nil
-       }
-
-       vv, mapFromString := tryToUnmarshalStringToYAML(value)
-
-       switch parentNode := nc.Parent.Node.(type) {
-       case *interface{}:
-               switch vParentNode := (*parentNode).(type) {
-               case []interface{}:
-                       idx := nc.Parent.KeyToChild.(int)
-                       if idx == -1 {
-                               // Treat -1 as insert-at-end of list
-                               idx = len(vParentNode)
-                       }
-
-                       if idx >= len(vParentNode) {
-                               newElements := make([]interface{}, 
idx-len(vParentNode)+1)
-                               vParentNode = append(vParentNode, 
newElements...)
-                               *parentNode = vParentNode
-                       }
-
-                       merged, err := mergeConditional(vv, nc.Node, merge)
-                       if err != nil {
-                               return false, err
-                       }
-
-                       vParentNode[idx] = merged
-                       nc.Node = merged
-               default:
-                       return false, fmt.Errorf("don't know about vtype %T", 
vParentNode)
-               }
-       case map[string]interface{}:
-               key := nc.Parent.KeyToChild.(string)
-
-               // Update is treated differently depending on whether the value 
is a scalar or map type. If scalar,
-               // insert a new element into the terminal node, otherwise 
replace the terminal node with the new subtree.
-               if ncNode, ok := nc.Node.(*interface{}); ok && !mapFromString {
-                       switch vNcNode := (*ncNode).(type) {
-                       case []interface{}:
-                               switch vv.(type) {
-                               case map[string]interface{}:
-                                       // the vv is a map, and the node is a 
slice
-                                       mergedValue := append(vNcNode, vv)
-                                       parentNode[key] = mergedValue
-                               case *interface{}:
-                                       merged, err := mergeConditional(vv, 
vNcNode, merge)
-                                       if err != nil {
-                                               return false, err
-                                       }
-
-                                       parentNode[key] = merged
-                                       nc.Node = merged
-                               default:
-                                       // the vv is an basic JSON type (int, 
float, string, bool)
-                                       vv = append(vNcNode, vv)
-                                       parentNode[key] = vv
-                                       nc.Node = vv
-                               }
-                       default:
-                               return false, fmt.Errorf("don't know about vnc 
type %T", vNcNode)
-                       }
-               } else {
-                       // For map passed as string type, the root is the new 
key.
-                       if mapFromString {
-                               if err := util2.DeleteFromMap(nc.Parent.Node, 
nc.Parent.KeyToChild); err != nil {
-                                       return false, err
-                               }
-                               vm := vv.(map[string]interface{})
-                               newKey := getTreeRoot(vm)
-                               return false, 
util2.InsertIntoMap(nc.Parent.Node, newKey, vm[newKey])
-                       }
-                       parentNode[key] = vv
-                       nc.Node = vv
-               }
-       // TODO `map[interface{}]interface{}` is used by tests in 
operator/cmd/mesh, we should add our own tests
-       case map[interface{}]interface{}:
-               key := nc.Parent.KeyToChild.(string)
-               parentNode[key] = vv
-               nc.Node = vv
-       default:
-               return false, fmt.Errorf("don't know about type %T", parentNode)
-       }
-
-       return true, nil
-}
-
-// mergeConditional returns a merge of newVal and originalVal if merge is 
true, otherwise it returns newVal.
-func mergeConditional(newVal, originalVal interface{}, merge bool) 
(interface{}, error) {
-       if !merge || util2.IsValueNilOrDefault(originalVal) {
-               return newVal, nil
-       }
-       newS, err := yaml.Marshal(newVal)
-       if err != nil {
-               return nil, err
-       }
-       if util2.IsYAMLEmpty(string(newS)) {
-               return originalVal, nil
-       }
-       originalS, err := yaml.Marshal(originalVal)
-       if err != nil {
-               return nil, err
-       }
-       if util2.IsYAMLEmpty(string(originalS)) {
-               return newVal, nil
-       }
-
-       mergedS, err := util2.OverlayYAML(string(originalS), string(newS))
-       if err != nil {
-               return nil, err
-       }
-
-       if util2.IsMap(originalVal) {
-               // For JSON compatibility
-               out := make(map[string]interface{})
-               if err := yaml.Unmarshal([]byte(mergedS), &out); err != nil {
-                       return nil, err
-               }
-               return out, nil
-       }
-       // For scalars and slices, copy the type
-       out := originalVal
-       if err := yaml.Unmarshal([]byte(mergedS), &out); err != nil {
-               return nil, err
-       }
-       return out, nil
-}
-
-// find returns the value at path from the given tree, or false if the path 
does not exist.
-func find(treeNode interface{}, path util2.Path) (interface{}, bool) {
-       if len(path) == 0 || treeNode == nil {
-               return nil, false
-       }
-       switch nt := treeNode.(type) {
-       case map[interface{}]interface{}:
-               val := nt[path[0]]
-               if val == nil {
-                       return nil, false
-               }
-               if len(path) == 1 {
-                       return val, true
-               }
-               return find(val, path[1:])
-       case map[string]interface{}:
-               val := nt[path[0]]
-               if val == nil {
-                       return nil, false
-               }
-               if len(path) == 1 {
-                       return val, true
-               }
-               return find(val, path[1:])
-       case []interface{}:
-               idx, err := strconv.Atoi(path[0])
-               if err != nil {
-                       return nil, false
-               }
-               if idx >= len(nt) {
-                       return nil, false
-               }
-               val := nt[idx]
-               return find(val, path[1:])
-       default:
-               return nil, false
-       }
-}
-
-// stringsEqual reports whether the string representations of a and b are 
equal. a and b may have different types.
-func stringsEqual(a, b interface{}) bool {
-       return fmt.Sprint(a) == fmt.Sprint(b)
-}
-
-// matchesRegex reports whether str regex matches pattern.
-func matchesRegex(pattern, str interface{}) bool {
-       match, err := regexp.MatchString(fmt.Sprint(pattern), fmt.Sprint(str))
-       if err != nil {
-               // log.Errorf("bad regex expression %s", fmt.Sprint(pattern))
-               return false
-       }
-       return match
-}
-
-// isSliceOrPtrInterface reports whether v is a slice, a ptr to slice or 
interface to slice.
-func isSliceOrPtrInterface(v interface{}) bool {
-       vv := reflect.ValueOf(v)
-       if vv.Kind() == reflect.Ptr {
-               vv = vv.Elem()
-       }
-       if vv.Kind() == reflect.Interface {
-               vv = vv.Elem()
-       }
-       return vv.Kind() == reflect.Slice
-}
-
-// isMapOrInterface reports whether v is a map, or interface to a map.
-func isMapOrInterface(v interface{}) bool {
-       vv := reflect.ValueOf(v)
-       if vv.Kind() == reflect.Interface {
-               vv = vv.Elem()
-       }
-       return vv.Kind() == reflect.Map
-}
-
-// tryToUnmarshalStringToYAML tries to unmarshal something that may be a YAML 
list or map into a structure. If not
-// possible, returns original scalar value.
-func tryToUnmarshalStringToYAML(s interface{}) (interface{}, bool) {
-       // If value type is a string it could either be a literal string or a 
map type passed as a string. Try to unmarshal
-       // to discover it's the latter.
-       vv := s
-
-       if reflect.TypeOf(vv).Kind() == reflect.String {
-               sv := strings.Split(vv.(string), "\n")
-               // Need to be careful not to transform string literals into 
maps unless they really are maps, since scalar handling
-               // is different for inserts.
-               if len(sv) == 1 && strings.Contains(s.(string), ": ") ||
-                       len(sv) > 1 && strings.Contains(s.(string), ":") {
-                       nv := make(map[string]interface{})
-                       if err := json.Unmarshal([]byte(vv.(string)), &nv); err 
== nil {
-                               // treat JSON as string
-                               return vv, false
-                       }
-                       if err := yaml2.Unmarshal([]byte(vv.(string)), &nv); 
err == nil {
-                               return nv, true
-                       }
-               }
-       }
-       // looks like a literal or failed unmarshal, return original type.
-       return vv, false
-}
-
-// getTreeRoot returns the first key found in m. It assumes a single root tree.
-func getTreeRoot(m map[string]interface{}) string {
-       for k := range m {
-               return k
-       }
-       return ""
-}
diff --git a/operator/manifest/util.go b/operator/manifest/util.go
deleted file mode 100644
index 4ab436f5..00000000
--- a/operator/manifest/util.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 manifest
-
-import (
-       "strconv"
-       "strings"
-)
-
-// StripPrefix removes the given prefix from prefix.
-func StripPrefix(path, prefix string) string {
-       pl := len(strings.Split(prefix, "/"))
-       pv := strings.Split(path, "/")
-       return strings.Join(pv[pl:], "/")
-}
-
-func SplitSetFlag(flag string) (string, string) {
-       items := strings.Split(flag, "=")
-       if len(items) != 2 {
-               return flag, ""
-       }
-       return strings.TrimSpace(items[0]), strings.TrimSpace(items[1])
-}
-
-func GetValueFromSetFlags(setFlags []string, key string) string {
-       var res string
-       for _, setFlag := range setFlags {
-               k, v := SplitSetFlag(setFlag)
-               if k == key {
-                       res = v
-               }
-       }
-       return res
-}
-
-// ParseValue parses string into a value
-func ParseValue(valueStr string) interface{} {
-       var value interface{}
-       if v, err := strconv.Atoi(valueStr); err == nil {
-               value = v
-       } else if v, err := strconv.ParseFloat(valueStr, 64); err == nil {
-               value = v
-       } else if v, err := strconv.ParseBool(valueStr); err == nil {
-               value = v
-       } else {
-               value = strings.ReplaceAll(valueStr, "\\,", ",")
-       }
-       return value
-}
diff --git a/operator/manifest/render/manifest.go 
b/operator/pkg/render/manifest.go
similarity index 96%
rename from operator/manifest/render/manifest.go
rename to operator/pkg/render/manifest.go
index d407bb74..5efd3114 100644
--- a/operator/manifest/render/manifest.go
+++ b/operator/pkg/render/manifest.go
@@ -2,7 +2,7 @@ package render
 
 import (
        "fmt"
-       "github.com/apache/dubbo-kubernetes/operator/manifest"
+       "github.com/apache/dubbo-kubernetes/operator/cmd/validation"
        "github.com/apache/dubbo-kubernetes/operator/pkg/util/clog"
        "github.com/apache/dubbo-kubernetes/operator/pkg/values"
        "io"


Reply via email to