diff --git a/go.mod b/go.mod index 382f7c2975..fe46ac4ca2 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/docker/distribution v2.8.2+incompatible github.com/docker/docker v23.0.1+incompatible github.com/docker/go-connections v0.4.0 - github.com/envoyproxy/go-control-plane v0.10.3 + github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f github.com/gin-gonic/gin v1.9.1 github.com/go-co-op/gocron v1.17.0 github.com/go-ldap/ldap/v3 v3.3.0 @@ -39,8 +39,8 @@ require ( github.com/go-sql-driver/mysql v1.7.1 github.com/godoes/gorm-dameng v0.0.8 github.com/golang-jwt/jwt v3.2.2+incompatible - github.com/golang/protobuf v1.5.3 - github.com/google/gnostic v0.6.9 + github.com/golang/protobuf v1.5.4 + github.com/google/gnostic-models v0.6.8 github.com/google/go-github/v35 v35.3.0 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.0 @@ -67,11 +67,12 @@ require ( github.com/onsi/ginkgo/v2 v2.12.1 github.com/onsi/gomega v1.27.10 github.com/opencontainers/go-digest v1.0.0 + github.com/openkruise/kruise-api v1.6.0 github.com/otiai10/copy v1.7.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pingcap/tidb/parser v0.0.0-20230922051344-241e8464cde0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.15.1 + github.com/prometheus/client_golang v1.16.0 github.com/redis/go-redis/v9 v9.2.1 github.com/rfyiamcool/cronlib v1.2.1 github.com/robfig/cron/v3 v3.0.1 @@ -84,7 +85,6 @@ require ( github.com/stretchr/testify v1.9.0 github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a github.com/swaggo/gin-swagger v1.5.3 - github.com/swaggo/swag v1.16.3 github.com/tidwall/gjson v1.14.3 github.com/traefik/yaegi v0.16.1 github.com/xanzy/go-gitlab v0.73.1 @@ -93,13 +93,14 @@ require ( golang.org/x/crypto v0.23.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/net v0.25.0 - golang.org/x/oauth2 v0.5.0 - golang.org/x/sync v0.6.0 + golang.org/x/oauth2 v0.17.0 + golang.org/x/sync v0.7.0 golang.org/x/text v0.15.0 - google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 - google.golang.org/grpc v1.53.0 - google.golang.org/protobuf v1.30.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc + google.golang.org/grpc v1.56.3 + google.golang.org/protobuf v1.35.1 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df + gopkg.in/ini.v1 v1.67.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -108,22 +109,22 @@ require ( helm.sh/helm/v3 v3.12.3 istio.io/api v0.0.0-20221109202042-b9e5d446a83d istio.io/client-go v1.16.0 - k8s.io/api v0.27.7 - k8s.io/apiextensions-apiserver v0.27.7 - k8s.io/apimachinery v0.27.7 - k8s.io/cli-runtime v0.27.3 - k8s.io/client-go v0.27.7 + k8s.io/api v0.28.2 + k8s.io/apiextensions-apiserver v0.28.2 + k8s.io/apimachinery v0.28.2 + k8s.io/cli-runtime v0.28.2 + k8s.io/client-go v0.28.2 k8s.io/helm v2.17.0+incompatible - k8s.io/klog/v2 v2.100.1 - k8s.io/kubectl v0.27.3 - k8s.io/metrics v0.27.3 - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 - sigs.k8s.io/controller-runtime v0.15.3 + k8s.io/klog/v2 v2.120.1 + k8s.io/kubectl v0.28.2 + k8s.io/metrics v0.28.2 + k8s.io/utils v0.0.0-20230726121419-3b25d923346b + sigs.k8s.io/controller-runtime v0.16.2 sigs.k8s.io/yaml v1.4.0 ) require ( - cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute v1.20.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect @@ -157,12 +158,12 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/clbanning/mxj/v2 v2.5.5 // indirect github.com/cloudflare/circl v1.3.3 // indirect - github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b // indirect + github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect github.com/containerd/containerd v1.7.0 // indirect github.com/containerd/typeurl v1.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect @@ -173,9 +174,9 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect github.com/dsnet/compress v0.0.1 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/emicklei/go-restful/v3 v3.10.1 // indirect - github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect @@ -190,7 +191,7 @@ require ( github.com/go-asn1-ber/asn1-ber v1.5.1 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.0.5 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -206,21 +207,22 @@ require ( github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - github.com/golang/glog v1.0.0 // indirect + github.com/golang/glog v1.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/flatbuffers v1.12.1 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v29 v29.0.2 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect + github.com/google/s2a-go v0.1.4 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/googleapis/gax-go/v2 v2.11.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -249,7 +251,7 @@ require ( github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/locker v1.0.1 // indirect @@ -271,11 +273,11 @@ require ( github.com/pingcap/errors v0.11.5-0.20210425183316-da1aaba5fb63 // indirect github.com/pingcap/failpoint v0.0.0-20220801062533-2eaa32854a6c // indirect github.com/pingcap/log v1.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.3.4 // indirect github.com/quic-go/quic-go v0.39.0 // indirect @@ -290,6 +292,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.2.0 // indirect + github.com/swaggo/swag v1.16.3 // indirect github.com/tdewolff/parse/v2 v2.7.11 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect @@ -307,41 +310,46 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/xlab/treeprint v1.1.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect - go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect + go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.3.0 // indirect golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect - golang.org/x/mod v0.16.0 // indirect - golang.org/x/sys v0.20.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.20.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.19.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect - google.golang.org/api v0.110.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + golang.org/x/tools v0.20.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/api v0.126.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect - k8s.io/apiserver v0.27.7 // indirect - k8s.io/component-base v0.27.7 // indirect - k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + k8s.io/apiserver v0.28.2 // indirect + k8s.io/component-base v0.28.2 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect oras.land/oras-go v1.2.3 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.2 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) // this is a fix for a broken docker package, reference: https://github.com/moby/moby/issues/42939 replace github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.9.0 replace github.com/docker/libnetwork => github.com/docker/libnetwork v0.8.0-dev.2.0.20220716072657-0dde5c895075 + +replace github.com/google/gnostic => github.com/google/gnostic v0.6.9 + +replace github.com/google/gnostic-models => github.com/google/gnostic-models v0.6.9 diff --git a/pkg/microservice/aslan/core/common/service/service.go b/pkg/microservice/aslan/core/common/service/service.go index 6b5d519614..7e95e06f76 100644 --- a/pkg/microservice/aslan/core/common/service/service.go +++ b/pkg/microservice/aslan/core/common/service/service.go @@ -18,8 +18,12 @@ package service import ( "bytes" + "context" "encoding/json" "fmt" + "github.com/koderover/zadig/v2/pkg/tool/clientmanager" + "github.com/openkruise/kruise-api/apps/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "net/url" "regexp" "strconv" @@ -1420,6 +1424,17 @@ func GetServiceImpl(serviceName string, serviceTmpl *commonmodels.Service, workL ret.Scales = append(ret.Scales, GetDeploymentWorkloadResource(d, inf, log)) ret.Workloads = append(ret.Workloads, ToDeploymentWorkload(d)) + case setting.CloneSet: + dc, err := clientmanager.NewKubeClientManager().GetKruiseClient(env.ClusterID) + if err != nil { + continue + } + d, err := dc.AppsV1alpha1().CloneSets(namespace).Get(context.Background(), u.GetName(), metav1.GetOptions{}) + if err != nil { + continue + } + ret.Scales = append(ret.Scales, GetCloneSetWorkloadResource(d, inf, log)) + ret.Workloads = append(ret.Workloads, ToCloneSetWorkload(d)) case setting.StatefulSet: sts, err := getter.GetStatefulSetByNameWWithCache(u.GetName(), namespace, inf) if err != nil { @@ -1494,6 +1509,15 @@ func GetDeploymentWorkloadResource(d *appsv1.Deployment, informer informers.Shar return wrapper.Deployment(d).WorkloadResource(pods) } +func GetCloneSetWorkloadResource(d *v1alpha1.CloneSet, informer informers.SharedInformerFactory, log *zap.SugaredLogger) *internalresource.Workload { + pods, err := getter.ListPodsWithCache(labels.SelectorFromValidatedSet(d.Spec.Selector.MatchLabels), informer) + if err != nil { + log.Warnf("Failed to get pods, err: %s", err) + } + + return wrapper.CloneSet(d).WorkloadResource(pods) +} + func getStatefulSetWorkloadResource(sts *appsv1.StatefulSet, informer informers.SharedInformerFactory, log *zap.SugaredLogger) *internalresource.Workload { pods, err := getter.ListPodsWithCache(labels.SelectorFromValidatedSet(sts.Spec.Selector.MatchLabels), informer) if err != nil { @@ -1548,6 +1572,20 @@ func ToDeploymentWorkload(v *appsv1.Deployment) *Workload { return workload } +func ToCloneSetWorkload(v *v1alpha1.CloneSet) *Workload { + workload := &Workload{ + Name: v.Name, + Spec: v.Spec.Template, + Selector: v.Spec.Selector, + Type: setting.CloneSet, + Images: wrapper.CloneSet(v).ImageInfos(), + Containers: wrapper.CloneSet(v).GetContainers(), + Ready: wrapper.CloneSet(v).Ready(), + Annotation: v.Annotations, + } + return workload +} + func toStsWorkload(v *appsv1.StatefulSet) *Workload { workload := &Workload{ Name: v.Name, diff --git a/pkg/microservice/aslan/core/common/util/service.go b/pkg/microservice/aslan/core/common/util/service.go index 2d0f6e0642..e6ea60e21d 100644 --- a/pkg/microservice/aslan/core/common/util/service.go +++ b/pkg/microservice/aslan/core/common/util/service.go @@ -155,7 +155,10 @@ func SetCurrentContainerImages(args *commonmodels.Service) error { return errors.New("nil Resource Kind") } - if resKind.Kind == setting.Deployment || resKind.Kind == setting.StatefulSet || resKind.Kind == setting.Job { + if resKind.Kind == setting.Deployment || + resKind.Kind == setting.StatefulSet || + resKind.Kind == setting.Job || + resKind.Kind == setting.CloneSet { containers, err := getContainers(yamlData) if err != nil { return fmt.Errorf("GetContainers error: %v", err) diff --git a/pkg/microservice/aslan/core/environment/service/export.go b/pkg/microservice/aslan/core/environment/service/export.go index 42d3e266a4..d47c6f1001 100644 --- a/pkg/microservice/aslan/core/environment/service/export.go +++ b/pkg/microservice/aslan/core/environment/service/export.go @@ -17,11 +17,16 @@ limitations under the License. package service import ( + "context" "github.com/koderover/zadig/v2/pkg/tool/clientmanager" + "github.com/openkruise/kruise-api/client/clientset/versioned" "go.uber.org/zap" "helm.sh/helm/v3/pkg/releaseutil" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/json" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" commonrepo "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/repository/mongodb" "github.com/koderover/zadig/v2/pkg/microservice/aslan/core/common/service/kube" @@ -65,6 +70,12 @@ func ExportYaml(envName, productName, serviceName, source string, production boo return res } + kruise, err := clientmanager.NewKubeClientManager().GetKruiseClient(env.ClusterID) + if err != nil { + log.Errorf("failed to get kruise for cluster %s", env.ClusterID) + return res + } + // needFetchByRenderedManifest happens when service is not deployed by zadig, or is not connected to zadig (when request comes from wd) needFetchByRenderedManifest := false @@ -79,6 +90,8 @@ func ExportYaml(envName, productName, serviceName, source string, production boo yamls = append(yamls, stss...) cronJobs := getCronJobYaml(kubeClient, namespace, selector, VersionLessThan121(clusterVersion), log) yamls = append(yamls, cronJobs...) + cloneSets := getKruiseYaml(kruise, namespace, selector, log) + yamls = append(yamls, cloneSets...) if len(deploys) == 0 && len(stss) == 0 && len(cronJobs) == 0 { if source == "wd" { needFetchByRenderedManifest = true @@ -168,6 +181,36 @@ func getDeploymentYaml(kubeClient client.Client, namespace string, selector labe return resources } +func getKruiseYaml(kubeClient versioned.Interface, namespace string, selector labels.Selector, log *zap.SugaredLogger) [][]byte { + listOptions := metav1.ListOptions{ + LabelSelector: selector.String(), + } + + resources, err := kubeClient.AppsV1alpha1().CloneSets(namespace).List(context.Background(), listOptions) + if err != nil { + log.Errorf("List CloneSet error: %v", err) + return nil + } + + var yamlBytes [][]byte + for _, item := range resources.Items { + jsonData, err := json.Marshal(item) + if err != nil { + log.Errorf("Failed to marshal CloneSet %s to JSON: %v", item.Name, err) + continue + } + + yamlData, err := yaml.JSONToYAML(jsonData) + if err != nil { + log.Errorf("Failed to convert CloneSet %s JSON to YAML: %v", item.Name, err) + continue + } + + yamlBytes = append(yamlBytes, yamlData) + } + return yamlBytes +} + func getStatefulSetYaml(kubeClient client.Client, namespace string, selector labels.Selector, log *zap.SugaredLogger) [][]byte { resources, err := getter.ListStatefulSetsYaml(namespace, selector, kubeClient) if err != nil { diff --git a/pkg/microservice/aslan/core/environment/service/service.go b/pkg/microservice/aslan/core/environment/service/service.go index 31d7fb6e8a..025bc663c7 100644 --- a/pkg/microservice/aslan/core/environment/service/service.go +++ b/pkg/microservice/aslan/core/environment/service/service.go @@ -71,15 +71,20 @@ func Scale(args *ScaleArgs, logger *zap.SugaredLogger) error { switch args.Type { case setting.Deployment: - err := updater.ScaleDeployment(namespace, args.Name, args.Number, kubeClient) + err = updater.ScaleDeployment(namespace, args.Name, args.Number, kubeClient) if err != nil { logger.Errorf("failed to scale %s/deploy/%s to %d", namespace, args.Name, args.Number) } case setting.StatefulSet: - err := updater.ScaleStatefulSet(namespace, args.Name, args.Number, kubeClient) + err = updater.ScaleStatefulSet(namespace, args.Name, args.Number, kubeClient) if err != nil { logger.Errorf("failed to scale %s/sts/%s to %d", namespace, args.Name, args.Number) } + case setting.CloneSet: + err = updater.ScaleCloneSet(namespace, args.Name, args.Number, kubeClient) + if err != nil { + logger.Errorf("failed to scale %s/cloneset/%s to %d", namespace, args.Name, args.Number) + } } return nil diff --git a/pkg/setting/consts.go b/pkg/setting/consts.go index b1319b780b..8c41fe8401 100644 --- a/pkg/setting/consts.go +++ b/pkg/setting/consts.go @@ -142,6 +142,7 @@ const ( PersistentVolumeClaim = "PersistentVolumeClaim" Service = "Service" Deployment = "Deployment" + CloneSet = "CloneSet" StatefulSet = "StatefulSet" Pod = "Pod" ReplicaSet = "ReplicaSet" diff --git a/pkg/shared/kube/wrapper/apireference.go b/pkg/shared/kube/wrapper/apireference.go index cac3ffb43d..d88e5a0e55 100644 --- a/pkg/shared/kube/wrapper/apireference.go +++ b/pkg/shared/kube/wrapper/apireference.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - openapi_v2 "github.com/google/gnostic/openapiv2" + openapi_v2 "github.com/google/gnostic-models/openapiv2" "k8s.io/apimachinery/pkg/runtime/schema" ) diff --git a/pkg/shared/kube/wrapper/cloneset.go b/pkg/shared/kube/wrapper/cloneset.go new file mode 100644 index 0000000000..a2cefc32a7 --- /dev/null +++ b/pkg/shared/kube/wrapper/cloneset.go @@ -0,0 +1,119 @@ +/* +Copyright 2021 The KodeRover 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 wrapper + +import ( + "github.com/openkruise/kruise-api/apps/v1alpha1" + corev1 "k8s.io/api/core/v1" + + "github.com/koderover/zadig/v2/pkg/setting" + "github.com/koderover/zadig/v2/pkg/shared/kube/resource" + "github.com/koderover/zadig/v2/pkg/util" +) + +// cloneset is the wrapper for v1alpha1.CloneSet type. +type cloneset struct { + *v1alpha1.CloneSet +} + +// CloneSet creates a wrapper for the given CloneSet object. +func CloneSet(c *v1alpha1.CloneSet) *cloneset { + if c == nil { + return nil + } + return &cloneset{ + CloneSet: c, + } +} + +// Unwrap returns the original v1alpha1.CloneSet object. +func (c *cloneset) Unwrap() *v1alpha1.CloneSet { + return c.CloneSet +} + +// Ready checks if the CloneSet is fully ready, which means: +// 1. Current replicas match desired replicas. +// 2. All replicas are ready. +// 3. All replicas are updated with the latest template. +func (c *cloneset) Ready() bool { + if c.Spec.Replicas == nil { + return false // Return false if desired replicas are not defined. + } + return c.Status.Replicas == *c.Spec.Replicas && + c.Status.ReadyReplicas == c.Status.Replicas && + c.Status.UpdatedReplicas == c.Status.Replicas +} + +// WorkloadResource creates a Workload representation for the CloneSet. +func (c *cloneset) WorkloadResource(pods []*corev1.Pod) *resource.Workload { + wl := &resource.Workload{ + Name: c.Name, + Type: setting.CloneSet, + Replicas: *c.Spec.Replicas, + Pods: make([]*resource.Pod, 0, len(pods)), + } + + // Add container images to the workload. + for _, container := range c.Spec.Template.Spec.Containers { + wl.Images = append(wl.Images, resource.ContainerImage{ + Name: container.Name, + Image: container.Image, + ImageName: util.ExtractImageName(container.Image), + }) + } + + // Add pod resources to the workload. + for _, pod := range pods { + wl.Pods = append(wl.Pods, Pod(pod).Resource()) + } + + return wl +} + +// Images returns the names of the containers in the CloneSet. +func (c *cloneset) Images() (images []string) { + for _, container := range c.Spec.Template.Spec.Containers { + images = append(images, container.Name) + } + return +} + +// ImageInfos returns the images used by the containers in the CloneSet. +func (c *cloneset) ImageInfos() (images []string) { + for _, container := range c.Spec.Template.Spec.Containers { + images = append(images, container.Image) + } + return +} + +// GetKind returns the kind of the CloneSet object. +func (c *cloneset) GetKind() string { + return c.Kind +} + +// GetContainers returns the container details of the CloneSet. +func (c *cloneset) GetContainers() []*resource.ContainerImage { + containers := make([]*resource.ContainerImage, 0, len(c.Spec.Template.Spec.Containers)) + for _, container := range c.Spec.Template.Spec.Containers { + containers = append(containers, &resource.ContainerImage{ + Name: container.Name, + Image: container.Image, + ImageName: util.ExtractImageName(container.Image), + }) + } + return containers +} diff --git a/pkg/tool/analysis/analysis.go b/pkg/tool/analysis/analysis.go index 4e7c4e8b10..1d2c753e85 100644 --- a/pkg/tool/analysis/analysis.go +++ b/pkg/tool/analysis/analysis.go @@ -22,7 +22,7 @@ import ( "strings" "sync" - openapi_v2 "github.com/google/gnostic/openapiv2" + openapi_v2 "github.com/google/gnostic-models/openapiv2" "github.com/koderover/zadig/v2/pkg/tool/cache" "github.com/koderover/zadig/v2/pkg/tool/llm" "github.com/koderover/zadig/v2/pkg/tool/log" @@ -99,7 +99,6 @@ func (a *Analysis) RunAnalysis(activeFilters []string) { openapiSchema := &openapi_v2.Document{} if a.WithDoc { var openApiErr error - openapiSchema, openApiErr = a.Client.Client.Discovery().OpenAPISchema() if openApiErr != nil { a.Errors = append(a.Errors, fmt.Sprintf("[KubernetesDoc] %s", openApiErr)) diff --git a/pkg/tool/analysis/ianalyzer.go b/pkg/tool/analysis/ianalyzer.go index 6ca304fb21..bf41c6cbea 100644 --- a/pkg/tool/analysis/ianalyzer.go +++ b/pkg/tool/analysis/ianalyzer.go @@ -18,7 +18,7 @@ package analysis import ( "context" - openapi_v2 "github.com/google/gnostic/openapiv2" + openapi_v2 "github.com/google/gnostic-models/openapiv2" "github.com/koderover/zadig/v2/pkg/tool/llm" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" diff --git a/pkg/tool/clientmanager/kube.go b/pkg/tool/clientmanager/kube.go index 7c3f0bfdf9..aa3f20677b 100644 --- a/pkg/tool/clientmanager/kube.go +++ b/pkg/tool/clientmanager/kube.go @@ -45,6 +45,7 @@ import ( "github.com/koderover/zadig/v2/pkg/setting" aslanClient "github.com/koderover/zadig/v2/pkg/shared/client/aslan" kubeclient "github.com/koderover/zadig/v2/pkg/shared/kube/client" + kruiseclientset "github.com/openkruise/kruise-api/client/clientset/versioned" ) var kubeClientManagerInstance *KubeClientManager @@ -57,6 +58,7 @@ var stopContext = ctrl.SetupSignalHandler() type KubeClientManager struct { controllerRuntimeClusterMap sync.Map kubernetesClientSetMap sync.Map + kruiseClientMap sync.Map metricsClientMap sync.Map istioClientSetMap sync.Map @@ -150,6 +152,59 @@ func (cm *KubeClientManager) GetKubernetesClientSet(clusterID string) (*kubernet return cli, err } +func (cm *KubeClientManager) GetKruiseClient(clusterID string) (kruiseclientset.Interface, error) { + clusterID = handleClusterID(clusterID) + + client, ok := cm.kruiseClientMap.Load(clusterID) + if ok { + return client.(*kruiseclientset.Clientset), nil + } + + if clusterID == setting.LocalClusterID { + cfg, err := rest.InClusterConfig() + if err != nil { + return nil, err + } + cli, err := kruiseclientset.NewForConfig(cfg) + if err == nil { + cm.kruiseClientMap.Store(clusterID, cli) + } + return cli, err + } + + clusterInfo, err := aslanClient.New(config.AslanServiceAddress()).GetClusterInfo(clusterID) + if err != nil { + return nil, err + } + if clusterInfo == nil { + return nil, fmt.Errorf("cluster %s not found", clusterID) + } + + if clusterInfo.Status != setting.Normal { + return nil, fmt.Errorf("unable to connect to cluster: %s, status: %s", clusterInfo.Name, clusterInfo.Status) + } + + var cfg *rest.Config + switch clusterInfo.Type { + case setting.AgentClusterType, "": + cfg = generateAgentRestConfig(clusterID, config.HubServerServiceAddress()) + case setting.KubeConfigClusterType: + cfg, err = generateRestConfigFromKubeConfig(clusterInfo.KubeConfig) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("failed to create kruise client: unknown cluster type: %s", clusterInfo.Type) + } + + cli, err := kruiseclientset.NewForConfig(cfg) + if err == nil { + cm.kruiseClientMap.Store(clusterID, cli) + } + + return cli, err +} + func (cm *KubeClientManager) GetKubernetesMetricsClient(clusterID string) (*metricsV1Beta1.MetricsV1beta1Client, error) { clusterID = handleClusterID(clusterID) @@ -414,6 +469,7 @@ func (cm *KubeClientManager) Clear(clusterID string) error { cm.controllerRuntimeClusterMap.Delete(clusterID) cm.kubernetesClientSetMap.Delete(clusterID) + cm.kruiseClientMap.Delete(clusterID) cm.metricsClientMap.Delete(clusterID) cm.istioClientSetMap.Delete(clusterID) diff --git a/pkg/tool/kube/updater/cloneset.go b/pkg/tool/kube/updater/cloneset.go new file mode 100644 index 0000000000..dfa583eb83 --- /dev/null +++ b/pkg/tool/kube/updater/cloneset.go @@ -0,0 +1,22 @@ +package updater + +import ( + "fmt" + "github.com/openkruise/kruise-api/apps/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func ScaleCloneSet(ns, name string, replicas int, cl client.Client) error { + patchBytes := []byte(fmt.Sprintf(`{"spec":{"replicas": %d}}`, replicas)) + return PatchCloneSet(ns, name, patchBytes, cl) +} + +func PatchCloneSet(ns, name string, patchBytes []byte, cl client.Client) error { + return patchObject(&v1alpha1.CloneSet{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: name, + }, + }, patchBytes, cl) +}