mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 03:56:36 +00:00
Chore: remove schematic kube and helm (#6099)
* Chore: remove unused code Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Chore: remove schematic Kube & Helm Signed-off-by: Somefive <yd219913@alibaba-inc.com> --------- Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
@@ -84,7 +84,7 @@ func RollbackApplicationWithRevision(ctx context.Context, cli client.Client, app
|
||||
|
||||
// freeze the application
|
||||
appKey := client.ObjectKeyFromObject(app)
|
||||
controllerRequirement, err := utils.FreezeApplication(ctx, cli, app, func() {
|
||||
controllerRequirement, err := FreezeApplication(ctx, cli, app, func() {
|
||||
app.Spec = matchedRev.Spec.Application.Spec
|
||||
oam.SetPublishVersion(app, publishVersion)
|
||||
})
|
||||
@@ -94,7 +94,7 @@ func RollbackApplicationWithRevision(ctx context.Context, cli client.Client, app
|
||||
|
||||
defer func() {
|
||||
// unfreeze application
|
||||
if err = utils.UnfreezeApplication(ctx, cli, app, nil, controllerRequirement); err != nil {
|
||||
if err = UnfreezeApplication(ctx, cli, app, nil, controllerRequirement); err != nil {
|
||||
klog.Errorf("failed to unfreeze application %s after update:%s", appKey, err.Error())
|
||||
}
|
||||
}()
|
||||
@@ -130,3 +130,27 @@ func RollbackApplicationWithRevision(ctx context.Context, cli client.Client, app
|
||||
}
|
||||
return matchedRev, app, nil
|
||||
}
|
||||
|
||||
// FreezeApplication freeze application to disable the reconciling process for it
|
||||
func FreezeApplication(ctx context.Context, cli client.Client, app *v1beta1.Application, mutate func()) (string, error) {
|
||||
return oam.GetControllerRequirement(app), _updateApplicationWithControllerRequirement(ctx, cli, app, mutate, "Disabled")
|
||||
}
|
||||
|
||||
// UnfreezeApplication unfreeze application to enable the reconciling process for it
|
||||
func UnfreezeApplication(ctx context.Context, cli client.Client, app *v1beta1.Application, mutate func(), originalControllerRequirement string) error {
|
||||
return _updateApplicationWithControllerRequirement(ctx, cli, app, mutate, originalControllerRequirement)
|
||||
}
|
||||
|
||||
func _updateApplicationWithControllerRequirement(ctx context.Context, cli client.Client, app *v1beta1.Application, mutate func(), controllerRequirement string) error {
|
||||
appKey := client.ObjectKeyFromObject(app)
|
||||
return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
if err := cli.Get(ctx, appKey, app); err != nil {
|
||||
return err
|
||||
}
|
||||
oam.SetControllerRequirement(app, controllerRequirement)
|
||||
if mutate != nil {
|
||||
mutate()
|
||||
}
|
||||
return cli.Update(ctx, app)
|
||||
})
|
||||
}
|
||||
@@ -16,20 +16,6 @@ limitations under the License.
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ResourceTrackerNotExistError identifies error caused by resourcetracker not exist
|
||||
type ResourceTrackerNotExistError struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// Error implement error interface
|
||||
func (err ResourceTrackerNotExistError) Error() string {
|
||||
return fmt.Sprintf("given resource tracker %q doesn't exist", err.Name)
|
||||
}
|
||||
|
||||
// ManagedResourceHasNoDataError identifies error caused by no data in maanged resource
|
||||
type ManagedResourceHasNoDataError struct{}
|
||||
|
||||
|
||||
@@ -19,32 +19,21 @@ package helm
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
types2 "k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
"helm.sh/helm/v3/pkg/cli"
|
||||
"helm.sh/helm/v3/pkg/getter"
|
||||
"helm.sh/helm/v3/pkg/release"
|
||||
"helm.sh/helm/v3/pkg/repo"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
|
||||
)
|
||||
|
||||
// VelaDebugLog defines an ENV to set vela helm install log to be debug
|
||||
const (
|
||||
VelaDebugLog = "VELA_DEBUG"
|
||||
userNameSecKey = "username"
|
||||
userPasswordSecKey = "password"
|
||||
caFileSecKey = "caFile"
|
||||
@@ -56,138 +45,6 @@ var (
|
||||
settings = cli.New()
|
||||
)
|
||||
|
||||
// Install will install helm chart
|
||||
func Install(ioStreams cmdutil.IOStreams, repoName, repoURL, chartName, version, namespace, releaseName string,
|
||||
vals map[string]interface{}) error {
|
||||
|
||||
if len(namespace) > 0 {
|
||||
args, err := common.InitBaseRestConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kubeClient, err := args.GetClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
exist, err := cmdutil.DoesNamespaceExist(kubeClient, namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
if err = cmdutil.NewNamespace(kubeClient, namespace); err != nil {
|
||||
return fmt.Errorf("create namespace (%s) failed for chart %s: %w", namespace, chartName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// check release running first before add repo and install chart
|
||||
if IsHelmReleaseRunning(releaseName, chartName, namespace, ioStreams) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !IsHelmRepositoryExist(repoName, repoURL) {
|
||||
err := AddHelmRepository(repoName, repoURL,
|
||||
"", "", "", "", "", false, ioStreams.Out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
chartClient, err := NewHelmInstall(version, namespace, releaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chartRequested, err := GetChart(chartClient, repoName+"/"+chartName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rel, err := chartClient.Run(chartRequested, vals)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ioStreams.Infof("Successfully installed chart (%s) with release name (%s)\n", chartName, rel.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uninstall will uninstall helm chart
|
||||
func Uninstall(ioStreams cmdutil.IOStreams, chartName, namespace, releaseName string) error {
|
||||
if !IsHelmReleaseRunning(releaseName, chartName, namespace, ioStreams) {
|
||||
return nil
|
||||
}
|
||||
uninstall, err := NewHelmUninstall(namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = uninstall.Run(releaseName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ioStreams.Infof("Successfully removed chart (%s) with release name (%s)\n", chartName, releaseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewHelmInstall will create a install client for helm install
|
||||
func NewHelmInstall(version, namespace, releaseName string) (*action.Install, error) {
|
||||
actionConfig := new(action.Configuration)
|
||||
if len(namespace) == 0 {
|
||||
namespace = types.DefaultKubeVelaNS
|
||||
}
|
||||
if err := actionConfig.Init(
|
||||
cmdutil.NewRestConfigGetter(namespace),
|
||||
namespace,
|
||||
os.Getenv("HELM_DRIVER"),
|
||||
debug,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := action.NewInstall(actionConfig)
|
||||
client.ReleaseName = releaseName
|
||||
// MUST set here, client didn't use namespace from configuration
|
||||
client.Namespace = namespace
|
||||
|
||||
if len(version) > 0 {
|
||||
client.Version = version
|
||||
} else {
|
||||
client.Version = types.DefaultKubeVelaVersion
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// NewHelmUninstall will create a helm uninstall client
|
||||
func NewHelmUninstall(namespace string) (*action.Uninstall, error) {
|
||||
actionConfig := new(action.Configuration)
|
||||
|
||||
if err := actionConfig.Init(
|
||||
cmdutil.NewRestConfigGetter(namespace),
|
||||
namespace,
|
||||
os.Getenv("HELM_DRIVER"),
|
||||
debug,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return action.NewUninstall(actionConfig), nil
|
||||
}
|
||||
|
||||
// IsHelmRepositoryExist will check help repo exists
|
||||
func IsHelmRepositoryExist(name, url string) bool {
|
||||
repos := GetHelmRepositoryList()
|
||||
for _, repo := range repos {
|
||||
if repo.Name == name && repo.URL == url {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetHelmRepositoryList get the helm repo list from default setting
|
||||
func GetHelmRepositoryList() []*repo.Entry {
|
||||
f, err := repo.LoadFile(settings.RepositoryConfig)
|
||||
if err == nil && len(f.Repositories) > 0 {
|
||||
return f.Repositories
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func debug(format string, v ...interface{}) {
|
||||
if settings.Debug {
|
||||
format = fmt.Sprintf("[debug] %s\n", format)
|
||||
@@ -195,53 +52,6 @@ func debug(format string, v ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// AddHelmRepository add helm repo
|
||||
func AddHelmRepository(name, url, username, password, certFile, keyFile, caFile string, insecureSkipTLSverify bool, out io.Writer) error {
|
||||
var f repo.File
|
||||
c := repo.Entry{
|
||||
Name: name,
|
||||
URL: url,
|
||||
Username: username,
|
||||
Password: password,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
CAFile: caFile,
|
||||
InsecureSkipTLSverify: insecureSkipTLSverify,
|
||||
}
|
||||
|
||||
r, err := repo.NewChartRepository(&c, getter.All(settings))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := r.DownloadIndexFile(); err != nil {
|
||||
return errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", url)
|
||||
}
|
||||
|
||||
f.Update(&c)
|
||||
|
||||
if err := f.WriteFile(settings.RepositoryConfig, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(out, "%q has been added to your repositories\n", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsHelmReleaseRunning check helm release running
|
||||
func IsHelmReleaseRunning(releaseName, chartName, ns string, streams cmdutil.IOStreams) bool {
|
||||
releases, err := GetHelmRelease(ns)
|
||||
if err != nil {
|
||||
streams.Error("get helm release err", err)
|
||||
return false
|
||||
}
|
||||
for _, r := range releases {
|
||||
if strings.Contains(r.Chart.ChartFullPath(), chartName) && r.Name == releaseName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetHelmRelease will get helm release
|
||||
func GetHelmRelease(ns string) ([]*release.Release, error) {
|
||||
actionConfig := new(action.Configuration)
|
||||
@@ -258,29 +68,6 @@ func GetHelmRelease(ns string) ([]*release.Release, error) {
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// GetChart will locate chart
|
||||
func GetChart(client *action.Install, name string) (*chart.Chart, error) {
|
||||
if os.Getenv(VelaDebugLog) != "" {
|
||||
settings.Debug = true
|
||||
}
|
||||
|
||||
chartPath, err := client.ChartPathOptions.LocateChart(name, settings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chartRequested, err := loader.Load(chartPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chartRequested, nil
|
||||
}
|
||||
|
||||
// InstallHelmChart will install helm chart from types.Chart
|
||||
func InstallHelmChart(ioStreams cmdutil.IOStreams, c types.Chart) error {
|
||||
return Install(ioStreams, c.Repo, c.URL, c.Name, c.Version, c.Namespace, c.Name, c.Values)
|
||||
}
|
||||
|
||||
// SetHTTPOption will read username and password from secret return a httpOption that contain these info.
|
||||
func SetHTTPOption(ctx context.Context, k8sClient client.Client, secretRef types2.NamespacedName) (*common.HTTPOption, error) {
|
||||
sec := v1.Secret{}
|
||||
|
||||
@@ -21,12 +21,6 @@ import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// DumpJSON returns the JSON encoding
|
||||
func DumpJSON(o interface{}) string {
|
||||
j, _ := json.Marshal(o)
|
||||
return string(j)
|
||||
}
|
||||
|
||||
// StrictUnmarshal unmarshal target structure and disallow unknown fields
|
||||
func StrictUnmarshal(bs []byte, dest interface{}) error {
|
||||
d := json.NewDecoder(bytes.NewReader(bs))
|
||||
|
||||
@@ -185,14 +185,6 @@ func GetUserInfoFromConfig(cfg *rest.Config) *authv1.UserInfo {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AutoSetSelfImpersonationInConfig set impersonate username and group to the identity in the original rest config
|
||||
func AutoSetSelfImpersonationInConfig(cfg *rest.Config) {
|
||||
if userInfo := GetUserInfoFromConfig(cfg); userInfo != nil {
|
||||
cfg.Impersonate.UserName = userInfo.Username
|
||||
cfg.Impersonate.Groups = append(cfg.Impersonate.Groups, userInfo.Groups...)
|
||||
}
|
||||
}
|
||||
|
||||
// CreateOrUpdate create or update a kubernetes object
|
||||
func CreateOrUpdate(ctx context.Context, cli client.Client, obj client.Object) (controllerutil.OperationResult, error) {
|
||||
bs, err := json.Marshal(obj)
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 The KubeVela 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 utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// EnablePprof listen to the pprofAddr and export the profiling results
|
||||
// If the errChan is nil, this function will panic when the listening error occurred.
|
||||
func EnablePprof(pprofAddr string, errChan chan error) {
|
||||
// Start pprof server if enabled
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
|
||||
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
mux.HandleFunc("/mem/stat", func(writer http.ResponseWriter, request *http.Request) {
|
||||
var ms runtime.MemStats
|
||||
runtime.ReadMemStats(&ms)
|
||||
bs, _ := json.Marshal(ms)
|
||||
_, _ = writer.Write(bs)
|
||||
})
|
||||
mux.HandleFunc("/gc", func(writer http.ResponseWriter, request *http.Request) {
|
||||
runtime.GC()
|
||||
})
|
||||
pprofServer := http.Server{
|
||||
Addr: pprofAddr,
|
||||
Handler: mux,
|
||||
ReadHeaderTimeout: 2 * time.Second,
|
||||
}
|
||||
|
||||
klog.InfoS("Starting debug HTTP server", "addr", pprofServer.Addr)
|
||||
|
||||
if err := pprofServer.ListenAndServe(); err != nil {
|
||||
klog.Error(err, "Failed to start debug HTTP server")
|
||||
if errChan != nil {
|
||||
errChan <- err
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2021 The KubeVela 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 utils
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// TryCancelRequest tries to cancel the request by traversing round trippers
|
||||
func TryCancelRequest(rt http.RoundTripper, req *http.Request) {
|
||||
type canceler interface {
|
||||
CancelRequest(*http.Request)
|
||||
}
|
||||
switch rt := rt.(type) {
|
||||
case canceler:
|
||||
rt.CancelRequest(req)
|
||||
case utilnet.RoundTripperWrapper:
|
||||
TryCancelRequest(rt.WrappedRoundTripper(), req)
|
||||
default:
|
||||
klog.Warningf("Unable to cancel request for %T", rt)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela 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 utils
|
||||
|
||||
import "strings"
|
||||
|
||||
// Sanitize the inputs by removing line endings
|
||||
func Sanitize(s string) string {
|
||||
s = strings.ReplaceAll(s, "\n", "")
|
||||
s = strings.ReplaceAll(s, "\r", "")
|
||||
return s
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela 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 utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSanitize(t *testing.T) {
|
||||
s := "abc\ndef\rgh"
|
||||
require.Equal(t, "abcdefgh", Sanitize(s))
|
||||
}
|
||||
@@ -18,9 +18,8 @@ package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
"github.com/kubevela/pkg/util/slices"
|
||||
)
|
||||
|
||||
// UISchema ui schema
|
||||
@@ -87,7 +86,7 @@ func (c Condition) Validate() error {
|
||||
if c.Action != "enable" && c.Action != "disable" && c.Action != "" {
|
||||
return fmt.Errorf("the action of the condition only supports enable, disable or leave it empty")
|
||||
}
|
||||
if c.Op != "" && !utils.StringsContain([]string{"==", "!=", "in"}, c.Op) {
|
||||
if c.Op != "" && !slices.Contains([]string{"==", "!=", "in"}, c.Op) {
|
||||
return fmt.Errorf("the op of the condition must be `==` 、`!=` and `in`")
|
||||
}
|
||||
return nil
|
||||
@@ -125,22 +124,6 @@ type Option struct {
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
// FirstUpper Sets the first letter of the string to upper.
|
||||
func FirstUpper(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(s[:1]) + s[1:]
|
||||
}
|
||||
|
||||
// FirstLower Sets the first letter of the string to lowercase.
|
||||
func FirstLower(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToLower(s[:1]) + s[1:]
|
||||
}
|
||||
|
||||
// GetDefaultUIType Set the default mapping for API Schema Type
|
||||
func GetDefaultUIType(apiType string, haveOptions bool, subType string, haveSub bool) string {
|
||||
switch apiType {
|
||||
@@ -170,15 +153,3 @@ func GetDefaultUIType(apiType string, haveOptions bool, subType string, haveSub
|
||||
return "Input"
|
||||
}
|
||||
}
|
||||
|
||||
// RenderLabel render option label
|
||||
func RenderLabel(source interface{}) string {
|
||||
switch v := source.(type) {
|
||||
case int:
|
||||
return fmt.Sprintf("%d", v)
|
||||
case string:
|
||||
return FirstUpper(v)
|
||||
default:
|
||||
return FirstUpper(fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
|
||||
+5
-129
@@ -17,128 +17,9 @@ limitations under the License.
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StringsContain strings contain
|
||||
func StringsContain(items []string, source string) bool {
|
||||
for _, item := range items {
|
||||
if item == source {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ThreeWaySliceCompare will compare two string slice, with the three return values: [both in A and B], [only in A], [only in B]
|
||||
func ThreeWaySliceCompare(a []string, b []string) ([]string, []string, []string) {
|
||||
m := make(map[string]struct{})
|
||||
for _, k := range b {
|
||||
m[k] = struct{}{}
|
||||
}
|
||||
|
||||
var AB, AO, BO []string
|
||||
for _, k := range a {
|
||||
_, ok := m[k]
|
||||
if !ok {
|
||||
AO = append(AO, k)
|
||||
continue
|
||||
}
|
||||
AB = append(AB, k)
|
||||
delete(m, k)
|
||||
}
|
||||
for k := range m {
|
||||
BO = append(BO, k)
|
||||
}
|
||||
sort.Strings(AB)
|
||||
sort.Strings(AO)
|
||||
sort.Strings(BO)
|
||||
return AB, AO, BO
|
||||
}
|
||||
|
||||
// EqualSlice checks if two slice are equal
|
||||
func EqualSlice(a, b []string) bool {
|
||||
sort.Strings(a)
|
||||
sort.Strings(b)
|
||||
return reflect.DeepEqual(a, b)
|
||||
}
|
||||
|
||||
// SliceIncludeSlice the slice include the b slice
|
||||
func SliceIncludeSlice(a, b []string) bool {
|
||||
if EqualSlice(a, b) {
|
||||
return true
|
||||
}
|
||||
for _, item := range b {
|
||||
if !StringsContain(a, item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ToString convery an interface to a string type.
|
||||
func ToString(i interface{}) string {
|
||||
if i == nil {
|
||||
return ""
|
||||
}
|
||||
v := reflect.ValueOf(i)
|
||||
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
i = v.Interface()
|
||||
switch s := i.(type) {
|
||||
case string:
|
||||
return s
|
||||
case bool:
|
||||
return strconv.FormatBool(s)
|
||||
case float64:
|
||||
return strconv.FormatFloat(s, 'f', -1, 64)
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(s), 'f', -1, 32)
|
||||
case int:
|
||||
return strconv.Itoa(s)
|
||||
case int64:
|
||||
return strconv.FormatInt(s, 10)
|
||||
case int32:
|
||||
return strconv.Itoa(int(s))
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(s), 10)
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(s), 10)
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint64:
|
||||
// nolint
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(s), 10)
|
||||
case []byte:
|
||||
return string(s)
|
||||
case nil:
|
||||
return ""
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// MapKey2Array convery map keys to array
|
||||
func MapKey2Array(source map[string]string) []string {
|
||||
var list []string
|
||||
for k := range source {
|
||||
list = append(list, k)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// GetBoxDrawingString get line drawing string, see https://en.wikipedia.org/wiki/Box-drawing_character
|
||||
// nolint:gocyclo
|
||||
func GetBoxDrawingString(up bool, down bool, left bool, right bool, padLeft int, padRight int) string {
|
||||
@@ -193,14 +74,9 @@ func GetBoxDrawingString(up bool, down bool, left bool, right bool, padLeft int,
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// JoinURL join baseURL and subPath to be new URL
|
||||
func JoinURL(baseURL, subPath string) (string, error) {
|
||||
parsedURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
parsedURL.RawPath = path.Join(parsedURL.RawPath, subPath)
|
||||
parsedURL.Path = path.Join(parsedURL.Path, subPath)
|
||||
URL := parsedURL.String()
|
||||
return URL, nil
|
||||
// Sanitize the inputs by removing line endings
|
||||
func Sanitize(s string) string {
|
||||
s = strings.ReplaceAll(s, "\n", "")
|
||||
s = strings.ReplaceAll(s, "\r", "")
|
||||
return s
|
||||
}
|
||||
|
||||
+4
-194
@@ -17,202 +17,12 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCompareSlice(t *testing.T) {
|
||||
caseA := []string{"c", "b", "a"}
|
||||
caseB := []string{"c", "b", "a"}
|
||||
gotab, gotao, gotbo := ThreeWaySliceCompare(caseA, caseB)
|
||||
assert.Equal(t, gotab, []string{"a", "b", "c"})
|
||||
assert.Equal(t, gotao, []string(nil))
|
||||
assert.Equal(t, gotbo, []string(nil))
|
||||
|
||||
caseA = []string{"c", "b"}
|
||||
caseB = []string{"c", "a"}
|
||||
gotab, gotao, gotbo = ThreeWaySliceCompare(caseA, caseB)
|
||||
assert.Equal(t, gotab, []string{"c"})
|
||||
assert.Equal(t, gotao, []string{"b"})
|
||||
assert.Equal(t, gotbo, []string{"a"})
|
||||
|
||||
caseA = []string{"c", "b"}
|
||||
caseB = nil
|
||||
gotab, gotao, gotbo = ThreeWaySliceCompare(caseA, caseB)
|
||||
assert.Equal(t, gotab, []string(nil))
|
||||
assert.Equal(t, gotao, []string{"b", "c"})
|
||||
assert.Equal(t, gotbo, []string(nil))
|
||||
|
||||
caseA = nil
|
||||
caseB = []string{"c", "b"}
|
||||
gotab, gotao, gotbo = ThreeWaySliceCompare(caseA, caseB)
|
||||
assert.Equal(t, gotab, []string(nil))
|
||||
assert.Equal(t, gotao, []string(nil))
|
||||
assert.Equal(t, gotbo, []string{"b", "c"})
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
caseA := []string{"c", "b", "a"}
|
||||
caseB := []string{"c", "b", "a"}
|
||||
assert.Equal(t, EqualSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{"c", "a", "b"}
|
||||
caseB = []string{"c", "b", "a"}
|
||||
assert.Equal(t, EqualSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{"c", "a", "b"}
|
||||
caseB = []string{"b", "a", "c"}
|
||||
assert.Equal(t, EqualSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{"c", "a", "b"}
|
||||
caseB = []string{"b", "a", "c", "d"}
|
||||
assert.Equal(t, EqualSlice(caseA, caseB), false)
|
||||
|
||||
caseA = []string{}
|
||||
caseB = []string{}
|
||||
assert.Equal(t, EqualSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{}
|
||||
caseB = []string{"b", "a", "c"}
|
||||
assert.Equal(t, EqualSlice(caseA, caseB), false)
|
||||
}
|
||||
|
||||
func TestSliceIncludeSlice(t *testing.T) {
|
||||
caseA := []string{"b", "a", "c"}
|
||||
caseB := []string{}
|
||||
assert.Equal(t, SliceIncludeSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{"b", "a", "c"}
|
||||
caseB = []string{"b"}
|
||||
assert.Equal(t, SliceIncludeSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{"b", "a", "c"}
|
||||
caseB = []string{"b", "c"}
|
||||
assert.Equal(t, SliceIncludeSlice(caseA, caseB), true)
|
||||
|
||||
caseA = []string{"b", "a", "c"}
|
||||
caseB = []string{"b", "c", "d"}
|
||||
assert.Equal(t, SliceIncludeSlice(caseA, caseB), false)
|
||||
|
||||
caseA = []string{"b", "a", "c"}
|
||||
caseB = []string{"b", "c", "a"}
|
||||
assert.Equal(t, SliceIncludeSlice(caseA, caseB), true)
|
||||
}
|
||||
|
||||
func TestJoinURL(t *testing.T) {
|
||||
|
||||
testcase := []struct {
|
||||
baseURL string
|
||||
subPath string
|
||||
expectedUrl string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
baseURL: "https://www.kubevela.com",
|
||||
subPath: "index.yaml",
|
||||
expectedUrl: "https://www.kubevela.com/index.yaml",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
baseURL: "http://www.kubevela.com",
|
||||
subPath: "index.yaml",
|
||||
expectedUrl: "http://www.kubevela.com/index.yaml",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
baseURL: "0x7f:",
|
||||
subPath: "index.yaml",
|
||||
expectedUrl: "",
|
||||
err: &url.Error{Op: "parse", URL: "0x7f:", Err: errors.New("first path segment in URL cannot contain colon")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcase {
|
||||
url, err := JoinURL(tc.baseURL, tc.subPath)
|
||||
assert.Equal(t, tc.expectedUrl, url)
|
||||
assert.Equal(t, tc.err, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
type Obj struct {
|
||||
k string
|
||||
}
|
||||
obj := &Obj{"foo"}
|
||||
boolPtr := true
|
||||
caseA := []struct {
|
||||
input interface{}
|
||||
expect string
|
||||
}{
|
||||
{int(666), "666"},
|
||||
{int8(6), "6"},
|
||||
{int16(6), "6"},
|
||||
{int32(6), "6"},
|
||||
{int64(6), "6"},
|
||||
{uint(6), "6"},
|
||||
{uint8(6), "6"},
|
||||
{uint16(6), "6"},
|
||||
{uint32(6), "6"},
|
||||
{uint64(6), "6"},
|
||||
{float32(3.14), "3.14"},
|
||||
{float64(3.14), "3.14"},
|
||||
{true, "true"},
|
||||
{false, "false"},
|
||||
{&boolPtr, "true"},
|
||||
{nil, ""},
|
||||
{[]byte("one time"), "one time"},
|
||||
{"one more time", "one more time"},
|
||||
{obj, ""},
|
||||
}
|
||||
|
||||
for _, test := range caseA {
|
||||
v := ToString(test.input)
|
||||
assert.Equal(t, test.expect, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringsContain(t *testing.T) {
|
||||
type args struct {
|
||||
items []string
|
||||
source string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "test empty items should not contain any string",
|
||||
args: args{
|
||||
items: []string{},
|
||||
source: "foo",
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "test items should contain source",
|
||||
args: args{
|
||||
items: []string{"foo", "bar"},
|
||||
source: "foo",
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "test items should not contain source",
|
||||
args: args{
|
||||
items: []string{"foo", "bar"},
|
||||
source: "baz",
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equalf(t, tt.want, StringsContain(tt.args.items, tt.args.source), "StringsContain(%v, %v)", tt.args.items, tt.args.source)
|
||||
})
|
||||
}
|
||||
func TestSanitize(t *testing.T) {
|
||||
s := "abc\ndef\rgh"
|
||||
require.Equal(t, "abcdefgh", Sanitize(s))
|
||||
}
|
||||
|
||||
@@ -54,15 +54,6 @@ func GetVelaHomeDir() (string, error) {
|
||||
return velaHome, nil
|
||||
}
|
||||
|
||||
// GetDefaultFrontendDir return default vela frontend dir
|
||||
func GetDefaultFrontendDir() (string, error) {
|
||||
home, err := GetVelaHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(home, "frontend"), nil
|
||||
}
|
||||
|
||||
// GetCapCenterDir return cap center dir
|
||||
func GetCapCenterDir() (string, error) {
|
||||
home, err := GetVelaHomeDir()
|
||||
|
||||
@@ -19,6 +19,7 @@ package utils
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
@@ -70,3 +71,15 @@ func IsValidURL(strURL string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// JoinURL join baseURL and subPath to be new URL
|
||||
func JoinURL(baseURL, subPath string) (string, error) {
|
||||
parsedURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
parsedURL.RawPath = path.Join(parsedURL.RawPath, subPath)
|
||||
parsedURL.Path = path.Join(parsedURL.Path, subPath)
|
||||
URL := parsedURL.String()
|
||||
return URL, nil
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ limitations under the License.
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -113,3 +115,37 @@ func TestIsValidURL(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJoinURL(t *testing.T) {
|
||||
testcase := []struct {
|
||||
baseURL string
|
||||
subPath string
|
||||
expectedUrl string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
baseURL: "https://www.kubevela.com",
|
||||
subPath: "index.yaml",
|
||||
expectedUrl: "https://www.kubevela.com/index.yaml",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
baseURL: "http://www.kubevela.com",
|
||||
subPath: "index.yaml",
|
||||
expectedUrl: "http://www.kubevela.com/index.yaml",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
baseURL: "0x7f:",
|
||||
subPath: "index.yaml",
|
||||
expectedUrl: "",
|
||||
err: &url.Error{Op: "parse", URL: "0x7f:", Err: fmt.Errorf("first path segment in URL cannot contain colon")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcase {
|
||||
url, err := JoinURL(tc.baseURL, tc.subPath)
|
||||
assert.Equal(t, tc.expectedUrl, url)
|
||||
assert.Equal(t, tc.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user