From df37bde41ba74d4d2e4d82fdcce75eaf2293ca1e Mon Sep 17 00:00:00 2001 From: cuisongliu Date: Tue, 25 Jan 2022 22:00:37 +0800 Subject: [PATCH] feature(main): add cepctl feature (#65) * feature(main) add ctl feature --- .goreleaser.yml | 18 ++- client/cep.go | 51 +++++++ client/kube.go | 100 +++++++++++++ client/utils.go | 32 ++++ cmd/cepctl/app/client.go | 137 ++++++++++++++++++ cmd/cepctl/app/options/options.go | 100 +++++++++++++ cmd/cepctl/cepctl.go | 31 ++++ .../app/options/options.go | 2 +- cmd/{ => endpoints-operator}/app/server.go | 4 +- .../endpoints-operator.go | 2 +- controllers/run_probe.go | 2 +- go.mod | 2 + library/file/file.go | 29 ++++ library/go.mod | 2 +- library/go.sum | 2 - library/probe/exec/exec.go | 2 +- library/probe/http/http.go | 2 +- library/probe/tcp/tcp.go | 2 +- library/probe/udp/udp.go | 2 +- library/tools/tools.go | 53 ------- test/testhelper/kube.go | 82 ++++------- 21 files changed, 539 insertions(+), 118 deletions(-) create mode 100644 client/cep.go create mode 100644 client/kube.go create mode 100644 client/utils.go create mode 100644 cmd/cepctl/app/client.go create mode 100644 cmd/cepctl/app/options/options.go create mode 100644 cmd/cepctl/cepctl.go rename cmd/{ => endpoints-operator}/app/options/options.go (99%) rename cmd/{ => endpoints-operator}/app/server.go (97%) rename cmd/{ => endpoints-operator}/endpoints-operator.go (91%) create mode 100644 library/file/file.go delete mode 100644 library/tools/tools.go diff --git a/.goreleaser.yml b/.goreleaser.yml index fc2d6fb..aaa52dd 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -13,7 +13,23 @@ builds: goarch: - amd64 - arm64 - main: ./cmd + main: ./cmd/endpoints-operator + ldflags: + - -X github.com/sealyun/endpoints-operator/library/version.gitVersion={{.Version}} + - -X github.com/sealyun/endpoints-operator/library/version.gitCommit={{.ShortCommit}} + - -X github.com/sealyun/endpoints-operator/library/version.buildDate={{.Date}} + - -s -w + - env: + - CGO_ENABLED=0 + id: cepctl + binary: cepctl + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + main: ./cmd/cepctl ldflags: - -X github.com/sealyun/endpoints-operator/library/version.gitVersion={{.Version}} - -X github.com/sealyun/endpoints-operator/library/version.gitCommit={{.ShortCommit}} diff --git a/client/cep.go b/client/cep.go new file mode 100644 index 0000000..3020070 --- /dev/null +++ b/client/cep.go @@ -0,0 +1,51 @@ +// Copyright © 2022 The sealyun 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 client + +import ( + "context" + "github.com/sealyun/endpoints-operator/api/network/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" +) + +type Cep struct { + gvr schema.GroupVersionResource + client dynamic.Interface +} + +func NewCep(client dynamic.Interface) *Cep { + c := &Cep{} + c.gvr = schema.GroupVersionResource{Group: v1beta1.GroupName, Version: v1beta1.GroupVersion.Version, Resource: "clusterendpoints"} + //NewKubernetesClient(NewKubernetesOptions("", "")) + c.client = client + return c +} + +func (c *Cep) CreateCR(ctx context.Context, endpoint *v1beta1.ClusterEndpoint) error { + endpoint.APIVersion = v1beta1.GroupVersion.String() + endpoint.Kind = "ClusterEndpoint" + _, err := c.client.Resource(c.gvr).Namespace(endpoint.Namespace).Create(ctx, runtimeConvertUnstructured(endpoint), v1.CreateOptions{}) + return err +} + +func (c *Cep) DeleteCR(ctx context.Context, namespace, name string) error { + return c.client.Resource(c.gvr).Namespace(namespace).Delete(ctx, name, v1.DeleteOptions{}) +} + +func (c *Cep) DeleteCRs(ctx context.Context, namespace string, options v1.ListOptions) error { + return c.client.Resource(c.gvr).Namespace(namespace).DeleteCollection(ctx, v1.DeleteOptions{}, options) +} diff --git a/client/kube.go b/client/kube.go new file mode 100644 index 0000000..c60e08c --- /dev/null +++ b/client/kube.go @@ -0,0 +1,100 @@ +// Copyright © 2022 The sealyun 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 client + +import ( + "github.com/sealyun/endpoints-operator/library/file" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "os" + "path" +) + +type Client interface { + Kubernetes() kubernetes.Interface + KubernetesDynamic() dynamic.Interface + Config() *rest.Config +} + +type kubernetesClient struct { + // kubernetes client interface + k8s kubernetes.Interface + k8sDynamic dynamic.Interface + // discovery client + config *rest.Config +} + +type KubernetesOptions struct { + // kubernetes clientset qps + // +optional + QPS float32 `json:"qps,omitempty" yaml:"qps"` + // kubernetes clientset burst + // +optional + Burst int `json:"burst,omitempty" yaml:"burst"` + Kubeconfig string + Master string + Config *rest.Config `json:"-" yaml:"-"` +} + +// NewKubernetesOptions returns a `zero` instance +func NewKubernetesOptions(kubeConfig, master string) *KubernetesOptions { + kubeconfigPath := os.Getenv(clientcmd.RecommendedConfigPathEnvVar) + if kubeConfig == "" && kubeconfigPath != "" { + kubeConfig = kubeconfigPath + } + if kubeconfigPath == "" { + kubeConfig = path.Join(file.GetUserHomeDir(), clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName) + } + return &KubernetesOptions{ + QPS: 1e6, + Burst: 1e6, + Kubeconfig: kubeConfig, + Master: master, + } +} + +// NewKubernetesClient creates a KubernetesClient +func NewKubernetesClient(options *KubernetesOptions) Client { + config := options.Config + var err error + if config == nil { + config, err = clientcmd.BuildConfigFromFlags(options.Master, options.Kubeconfig) + if err != nil { + return nil + } + } + config.QPS = options.QPS + config.Burst = options.Burst + var k kubernetesClient + k.k8s = kubernetes.NewForConfigOrDie(config) + k.k8sDynamic = dynamic.NewForConfigOrDie(config) + k.config = config + + return &k +} + +func (k *kubernetesClient) Kubernetes() kubernetes.Interface { + return k.k8s +} + +func (k *kubernetesClient) Config() *rest.Config { + return k.config +} + +func (k *kubernetesClient) KubernetesDynamic() dynamic.Interface { + return k.k8sDynamic +} diff --git a/client/utils.go b/client/utils.go new file mode 100644 index 0000000..a95d184 --- /dev/null +++ b/client/utils.go @@ -0,0 +1,32 @@ +// Copyright © 2022 The sealyun 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 client + +import ( + "github.com/sealyun/endpoints-operator/library/convert" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" +) + +func runtimeConvertUnstructured(from runtime.Object) *unstructured.Unstructured { + to, ok := from.(*unstructured.Unstructured) + if ok { + return to + } + if to, err := convert.ResourceToUnstructured(from); err == nil { + return to + } + return nil +} diff --git a/cmd/cepctl/app/client.go b/cmd/cepctl/app/client.go new file mode 100644 index 0000000..cc8d56e --- /dev/null +++ b/cmd/cepctl/app/client.go @@ -0,0 +1,137 @@ +/* +Copyright 2022 The sealyun 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 app + +import ( + "context" + "errors" + "fmt" + "github.com/sealyun/endpoints-operator/api/network/v1beta1" + "github.com/sealyun/endpoints-operator/client" + "github.com/sealyun/endpoints-operator/cmd/cepctl/app/options" + "github.com/spf13/cobra" + v1 "k8s.io/api/core/v1" + v1opts "k8s.io/apimachinery/pkg/apis/meta/v1" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/json" + cliflag "k8s.io/component-base/cli/flag" + "k8s.io/component-base/term" + "k8s.io/klog/v2" + "os" + "sigs.k8s.io/yaml" +) + +func NewCommand() *cobra.Command { + s := options.NewOptions() + + cmd := &cobra.Command{ + Use: "cepctl", + Short: "cepctl is cli for cluster-endpoint", + Run: func(cmd *cobra.Command, args []string) { + if errs := s.Validate(); len(errs) != 0 { + klog.Error(utilerrors.NewAggregate(errs)) + os.Exit(1) + } + if err := run(s, context.Background()); err != nil { + klog.Error(err) + os.Exit(1) + } + }, + SilenceUsage: true, + } + + fs := cmd.Flags() + namedFlagSets := s.Flags() + + for _, f := range namedFlagSets.FlagSets { + fs.AddFlagSet(f) + } + + usageFmt := "Usage:\n %s\n" + cols, _, _ := term.TerminalSize(cmd.OutOrStdout()) + cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { + _, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine()) + cliflag.PrintSections(cmd.OutOrStdout(), namedFlagSets, cols) + }) + return cmd +} + +func run(s *options.Options, ctx context.Context) error { + cli := client.NewKubernetesClient(client.NewKubernetesOptions(s.KubeConfig, s.Master)) + if cli == nil { + return errors.New("build kube client error") + } + cep := &v1beta1.ClusterEndpoint{} + cep.Namespace = s.Namespace + cep.Name = s.Name + cep.Spec.PeriodSeconds = s.PeriodSeconds + svc, err := cli.Kubernetes().CoreV1().Services(s.Namespace).Get(ctx, s.Name, v1opts.GetOptions{}) + if err != nil { + return err + } + klog.V(4).InfoS("get service", "name", s.Name, "namespace", s.Namespace, "spec", svc.Spec) + if svc.Spec.ClusterIP == v1.ClusterIPNone { + return errors.New("not support clusterIP=None service") + } + ports := make([]v1beta1.ServicePort, len(svc.Spec.Ports)) + for i, p := range svc.Spec.Ports { + enable := s.Probe + ports[i] = v1beta1.ServicePort{ + Handler: v1beta1.Handler{ + TCPSocket: &v1beta1.TCPSocketAction{Enable: enable}, + }, + TimeoutSeconds: 1, + SuccessThreshold: 1, + FailureThreshold: 3, + Name: p.Name, + Protocol: p.Protocol, + Port: p.Port, + TargetPort: p.TargetPort.IntVal, + } + } + cep.Spec.Ports = ports + cep.Spec.ClusterIP = svc.Spec.ClusterIP + ep, _ := cli.Kubernetes().CoreV1().Endpoints(s.Namespace).Get(ctx, s.Name, v1opts.GetOptions{}) + if ep != nil { + klog.V(4).InfoS("get endpoint", "name", s.Name, "namespace", s.Namespace, "subsets", ep.Subsets) + if len(ep.Subsets) > 1 { + return errors.New("not support endpoint subsets length more than 1. Please spilt it") + } + cep.Spec.Hosts = convertAddress(ep.Subsets[0].Addresses) + } + configJson, _ := json.Marshal(cep) + configYaml, _ := yaml.Marshal(cep) + klog.V(4).InfoS("generator cep", "name", s.Name, "namespace", s.Namespace, "config", string(configJson)) + + if s.Output == "yaml" { + println(string(configYaml)) + return nil + } + if s.Output == "json" { + println(string(configJson)) + return nil + } + return nil +} + +func convertAddress(addresses []v1.EndpointAddress) []string { + eas := make([]string, 0) + for _, s := range addresses { + eas = append(eas, s.IP) + } + return eas +} diff --git a/cmd/cepctl/app/options/options.go b/cmd/cepctl/app/options/options.go new file mode 100644 index 0000000..2448a64 --- /dev/null +++ b/cmd/cepctl/app/options/options.go @@ -0,0 +1,100 @@ +// Copyright © 2022 The sealyun 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 options + +import ( + "errors" + "flag" + "fmt" + "github.com/sealyun/endpoints-operator/library/file" + cliflag "k8s.io/component-base/cli/flag" + "k8s.io/klog/v2" + "path" + "strings" +) + +type Options struct { + // Master is used to override the kubeconfig's URL to the apiserver. + Master string + //KubeConfig is the path to a KubeConfig file. + KubeConfig string + Name string + Namespace string + PeriodSeconds int32 + Probe bool + Output string +} + +func NewOptions() *Options { + s := &Options{ + Master: "", + KubeConfig: path.Join(file.GetUserHomeDir(), ".kube", "config"), + PeriodSeconds: 10, + Name: "", + Probe: false, + Namespace: "default", + Output: "", + } + return s +} + +func (s *Options) Flags() cliflag.NamedFlagSets { + fss := cliflag.NamedFlagSets{} + + kube := fss.FlagSet("kube") + kube.StringVar(&s.KubeConfig, "kubeconfig", s.KubeConfig, "Path to kubeconfig file with authorization information (the master location can be overridden by the master flag).") + kube.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).") + + cep := fss.FlagSet("cep") + cep.StringVar(&s.Name, "service-name", s.Name, "Sync cap from service name.") + cep.StringVar(&s.Namespace, "service-namespace", s.Namespace, "Sync cap from service namespace.") + cep.StringVarP(&s.Output, "output", "o", s.Output, "output json|yaml. if not set,will create cep to kubernetes") + + probe := fss.FlagSet("probe") + probe.Int32Var(&s.PeriodSeconds, "periodSeconds", s.PeriodSeconds, "How often (in seconds) to perform the probe.Default is 10.") + probe.BoolVar(&s.Probe, "probe", s.Probe, "When set value is true,add default probe of tcpAction.") + + kfs := fss.FlagSet("klog") + local := flag.NewFlagSet("klog", flag.ExitOnError) + klog.InitFlags(local) + local.VisitAll(func(fl *flag.Flag) { + fl.Name = strings.Replace(fl.Name, "_", "-", -1) + kfs.AddGoFlag(fl) + }) + + return fss +} + +func (s *Options) Validate() []error { + var errs []error + if s.PeriodSeconds < 0 { + errs = append(errs, errors.New("param periodSeconds must more than zero")) + } + if !file.Exist(s.KubeConfig) { + errs = append(errs, fmt.Errorf("kubeconfig path %s is not exist", s.KubeConfig)) + } + if len(s.Name) == 0 { + errs = append(errs, errors.New("service name must not empty")) + } + if len(s.Namespace) == 0 { + errs = append(errs, errors.New("service namespace must not empty")) + } + if len(s.Output) != 0 { + if s.Output != "yaml" && s.Output != "json" { + errs = append(errs, errors.New("output must be is yaml or json")) + } + } + return errs +} diff --git a/cmd/cepctl/cepctl.go b/cmd/cepctl/cepctl.go new file mode 100644 index 0000000..41fcfc4 --- /dev/null +++ b/cmd/cepctl/cepctl.go @@ -0,0 +1,31 @@ +/* +Copyright 2022 The sealyun 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 main + +import ( + "github.com/sealyun/endpoints-operator/cmd/cepctl/app" + "os" +) + +func main() { + + command := app.NewCommand() + + if err := command.Execute(); err != nil { + os.Exit(1) + } +} diff --git a/cmd/app/options/options.go b/cmd/endpoints-operator/app/options/options.go similarity index 99% rename from cmd/app/options/options.go rename to cmd/endpoints-operator/app/options/options.go index 9d5cc86..17b40ae 100644 --- a/cmd/app/options/options.go +++ b/cmd/endpoints-operator/app/options/options.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/pflag" "k8s.io/client-go/tools/leaderelection" cliflag "k8s.io/component-base/cli/flag" - "k8s.io/klog" + "k8s.io/klog/v2" ) type Options struct { diff --git a/cmd/app/server.go b/cmd/endpoints-operator/app/server.go similarity index 97% rename from cmd/app/server.go rename to cmd/endpoints-operator/app/server.go index 63afdff..efef20f 100644 --- a/cmd/app/server.go +++ b/cmd/endpoints-operator/app/server.go @@ -17,18 +17,18 @@ package app import ( "context" "fmt" + "github.com/sealyun/endpoints-operator/cmd/endpoints-operator/app/options" "github.com/sealyun/endpoints-operator/controllers" "k8s.io/component-base/term" "net/http" "os" - "github.com/sealyun/endpoints-operator/cmd/app/options" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" cliflag "k8s.io/component-base/cli/flag" - "k8s.io/klog" "k8s.io/klog/klogr" + "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager/signals" diff --git a/cmd/endpoints-operator.go b/cmd/endpoints-operator/endpoints-operator.go similarity index 91% rename from cmd/endpoints-operator.go rename to cmd/endpoints-operator/endpoints-operator.go index 56aa39a..bceb412 100644 --- a/cmd/endpoints-operator.go +++ b/cmd/endpoints-operator/endpoints-operator.go @@ -17,7 +17,7 @@ limitations under the License. package main import ( - "github.com/sealyun/endpoints-operator/cmd/app" + "github.com/sealyun/endpoints-operator/cmd/endpoints-operator/app" "os" ) diff --git a/controllers/run_probe.go b/controllers/run_probe.go index 17c79fc..530e512 100644 --- a/controllers/run_probe.go +++ b/controllers/run_probe.go @@ -37,7 +37,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" urutime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/klog" + "k8s.io/klog/v2" ) type work struct { diff --git a/go.mod b/go.mod index c165f0e..381e771 100644 --- a/go.mod +++ b/go.mod @@ -14,5 +14,7 @@ require ( k8s.io/client-go v0.21.1 k8s.io/component-base v0.21.1 k8s.io/klog v1.0.0 + k8s.io/klog/v2 v2.8.0 sigs.k8s.io/controller-runtime v0.9.0 + sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/library/file/file.go b/library/file/file.go new file mode 100644 index 0000000..22b1c22 --- /dev/null +++ b/library/file/file.go @@ -0,0 +1,29 @@ +// Copyright © 2022 The sealyun 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 file + +import ( + "os" +) + +func GetUserHomeDir() string { + home, _ := os.UserHomeDir() + return home +} + +func Exist(path string) bool { + _, err := os.Stat(path) + return err == nil || os.IsExist(err) +} diff --git a/library/go.mod b/library/go.mod index aae106f..499e596 100644 --- a/library/go.mod +++ b/library/go.mod @@ -11,7 +11,7 @@ require ( k8s.io/api v0.21.1 k8s.io/apimachinery v0.21.1 k8s.io/client-go v0.21.1 - k8s.io/klog v1.0.0 + k8s.io/klog/v2 v2.8.0 k8s.io/utils v0.0.0-20210527160623-6fdb442a123b sigs.k8s.io/controller-runtime v0.9.0 ) diff --git a/library/go.sum b/library/go.sum index ab0a145..711cd2c 100644 --- a/library/go.sum +++ b/library/go.sum @@ -716,8 +716,6 @@ k8s.io/component-base v0.21.1 h1:iLpj2btXbR326s/xNQWmPNGu0gaYSjzn7IN/5i28nQw= k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= diff --git a/library/probe/exec/exec.go b/library/probe/exec/exec.go index 7776738..34eb3ad 100644 --- a/library/probe/exec/exec.go +++ b/library/probe/exec/exec.go @@ -21,7 +21,7 @@ import ( "github.com/sealyun/endpoints-operator/library/ioutils" "github.com/sealyun/endpoints-operator/library/probe" - "k8s.io/klog" + "k8s.io/klog/v2" "k8s.io/utils/exec" ) diff --git a/library/probe/http/http.go b/library/probe/http/http.go index 4b79bff..8cf5dec 100644 --- a/library/probe/http/http.go +++ b/library/probe/http/http.go @@ -23,7 +23,7 @@ import ( "github.com/sealyun/endpoints-operator/library/io" "github.com/sealyun/endpoints-operator/library/probe" "github.com/sealyun/endpoints-operator/library/version" - "k8s.io/klog" + "k8s.io/klog/v2" "net/http" "net/url" "time" diff --git a/library/probe/tcp/tcp.go b/library/probe/tcp/tcp.go index fedbe23..4851751 100644 --- a/library/probe/tcp/tcp.go +++ b/library/probe/tcp/tcp.go @@ -18,7 +18,7 @@ package tcp import ( "github.com/sealyun/endpoints-operator/library/probe" - "k8s.io/klog" + "k8s.io/klog/v2" "net" "strconv" "time" diff --git a/library/probe/udp/udp.go b/library/probe/udp/udp.go index 7fafe59..17c8cfd 100644 --- a/library/probe/udp/udp.go +++ b/library/probe/udp/udp.go @@ -18,7 +18,7 @@ package udp import ( "github.com/sealyun/endpoints-operator/library/probe" - "k8s.io/klog" + "k8s.io/klog/v2" "net" "strconv" "time" diff --git a/library/tools/tools.go b/library/tools/tools.go deleted file mode 100644 index 2b9e001..0000000 --- a/library/tools/tools.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2022 The sealyun 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 tools - -import ( - "context" - "fmt" - "github.com/go-logr/logr" -) - -// Helper functions to check and remove string from a slice of strings. -func ContainsString(slice []string, s string) bool { - for _, item := range slice { - if item == s { - return true - } - } - return false -} - -func RemoveString(slice []string, s string) (result []string) { - for _, item := range slice { - if item == s { - continue - } - result = append(result, item) - } - return -} - -func GetLoggerOrDie(ctx context.Context, valKey string) logr.Logger { - logger, ok := ctx.Value(valKey).(logr.Logger) - if !ok { - panic("context didn't contain logger") - } - return logger -} - -func FinalizerName(module, kind string) string { - return fmt.Sprintf("%s.sealyun.com/%s.finalizers", module, kind) -} diff --git a/test/testhelper/kube.go b/test/testhelper/kube.go index be89c91..52bc437 100644 --- a/test/testhelper/kube.go +++ b/test/testhelper/kube.go @@ -1,72 +1,48 @@ -/* -Copyright 2022 cuisongliu@qq.com. - -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. -*/ +// Copyright © 2022 The sealyun 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 testhelper import ( + "context" "fmt" "github.com/sealyun/endpoints-operator/api/network/v1beta1" - "github.com/sealyun/endpoints-operator/library/convert" + "github.com/sealyun/endpoints-operator/client" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/dynamic" - ctrl "sigs.k8s.io/controller-runtime" + "sync" "testing" ) -var gvr = schema.GroupVersionResource{Group: v1beta1.GroupName, Version: v1beta1.GroupVersion.Version, Resource: "clusterendpoints"} - -func client() dynamic.Interface { - return dynamic.NewForConfigOrDie(ctrl.GetConfigOrDie()) -} - -func runtimeConvertUnstructured(from runtime.Object) *unstructured.Unstructured { - to, ok := from.(*unstructured.Unstructured) - if ok { - return to - } - if to, err := convert.ResourceToUnstructured(from); err == nil { - return to - } - return nil -} - -func CreateCR(endpoint *v1beta1.ClusterEndpoint) error { - endpoint.APIVersion = v1beta1.GroupVersion.String() - endpoint.Kind = "ClusterEndpoint" - _, err := client().Resource(gvr).Namespace(endpoint.Namespace).Create(runtimeConvertUnstructured(endpoint), v1.CreateOptions{}) - return err -} +var once sync.Once +var cep *client.Cep -func DeleteCR(namespace, name string) error { - return client().Resource(gvr).Namespace(namespace).Delete(name, &v1.DeleteOptions{}) -} - -func DeleteCRs(namespace string, options v1.ListOptions) error { - return client().Resource(gvr).Namespace(namespace).DeleteCollection(&v1.DeleteOptions{}, options) +func cepClient() { + once.Do(func() { + op := client.NewKubernetesOptions("", "") + c := client.NewKubernetesClient(op) + cep = client.NewCep(c.KubernetesDynamic()) + }) } func CreateTestCRs(num int, prefix string, ep *v1beta1.ClusterEndpoint, t *testing.T) { + ctx := context.Background() + cepClient() ep.Labels = map[string]string{"test": prefix} for i := 0; i < num; i++ { ep.Name = fmt.Sprintf("%s-%d", prefix, i) - err := CreateCR(ep.DeepCopy()) + err := cep.CreateCR(ctx, ep.DeepCopy()) if err != nil { t.Errorf("%s create failed: %v", ep.Name, err) continue @@ -77,7 +53,9 @@ func CreateTestCRs(num int, prefix string, ep *v1beta1.ClusterEndpoint, t *testi func DeleteTestCRs(prefix, namespace string, t *testing.T) { m := map[string]string{"test": prefix} - err := DeleteCRs(namespace, v1.ListOptions{ + cepClient() + ctx := context.Background() + err := cep.DeleteCRs(ctx, namespace, v1.ListOptions{ LabelSelector: labels.FormatLabels(m), }) if err != nil {