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"