2021-11-11 13:40:14 +08:00
|
|
|
/*
|
|
|
|
|
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 query
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
stdctx "context"
|
|
|
|
|
|
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
2021-11-24 11:09:50 +08:00
|
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
2021-11-11 13:40:14 +08:00
|
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
|
|
|
|
|
|
|
"github.com/oam-dev/kubevela/pkg/cue/model/value"
|
|
|
|
|
"github.com/oam-dev/kubevela/pkg/multicluster"
|
|
|
|
|
wfContext "github.com/oam-dev/kubevela/pkg/workflow/context"
|
|
|
|
|
"github.com/oam-dev/kubevela/pkg/workflow/providers"
|
|
|
|
|
"github.com/oam-dev/kubevela/pkg/workflow/types"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
// ProviderName is provider name for install.
|
|
|
|
|
ProviderName = "query"
|
2021-11-24 11:09:50 +08:00
|
|
|
// HelmReleaseKind is the kind of HelmRelease
|
|
|
|
|
HelmReleaseKind = "HelmRelease"
|
2021-11-11 13:40:14 +08:00
|
|
|
)
|
|
|
|
|
|
2021-11-24 11:09:50 +08:00
|
|
|
var fluxcdGroupVersion = schema.GroupVersion{Group: "helm.toolkit.fluxcd.io", Version: "v2beta1"}
|
|
|
|
|
|
2021-11-11 13:40:14 +08:00
|
|
|
type provider struct {
|
|
|
|
|
cli client.Client
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AppResources represent resources created by app
|
|
|
|
|
type AppResources struct {
|
2021-11-18 11:53:38 +08:00
|
|
|
Revision int64 `json:"revision"`
|
|
|
|
|
PublishVersion string `json:"publishVersion"`
|
2021-11-21 14:56:01 +08:00
|
|
|
DeployVersion string `json:"deployVersion"`
|
2021-11-18 11:53:38 +08:00
|
|
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
|
|
|
|
Components []Component `json:"components"`
|
2021-11-11 13:40:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Component group resources rendered by ApplicationComponent
|
|
|
|
|
type Component struct {
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
Resources []Resource `json:"resources"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resource refer to an object with cluster info
|
|
|
|
|
type Resource struct {
|
|
|
|
|
Cluster string `json:"cluster"`
|
|
|
|
|
Object *unstructured.Unstructured `json:"object"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Option is the query option
|
|
|
|
|
type Option struct {
|
2021-11-21 14:56:01 +08:00
|
|
|
Name string `json:"name"`
|
|
|
|
|
Namespace string `json:"namespace"`
|
|
|
|
|
Components []string `json:"components,omitempty"`
|
|
|
|
|
Filter ClusterFilter `json:"filter,omitempty"`
|
|
|
|
|
EnableHistoryQuery bool `json:"enableHistoryQuery,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ClusterFilter filter resource created by component
|
|
|
|
|
type ClusterFilter struct {
|
|
|
|
|
Cluster string `json:"cluster,omitempty"`
|
|
|
|
|
ClusterNamespace string `json:"clusterNamespace,omitempty"`
|
2021-11-11 13:40:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListResourcesInApp lists CRs created by Application
|
|
|
|
|
func (h *provider) ListResourcesInApp(ctx wfContext.Context, v *value.Value, act types.Action) error {
|
|
|
|
|
val, err := v.LookupValue("app")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
opt := Option{}
|
|
|
|
|
if err = val.UnmarshalTo(&opt); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2021-11-18 11:53:38 +08:00
|
|
|
collector := NewAppCollector(h.cli, opt)
|
2021-11-11 13:40:14 +08:00
|
|
|
appResList, err := collector.CollectResourceFromApp()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return v.FillObject(err.Error(), "err")
|
|
|
|
|
}
|
|
|
|
|
return v.FillObject(appResList, "list")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (h *provider) CollectPods(ctx wfContext.Context, v *value.Value, act types.Action) error {
|
|
|
|
|
val, err := v.LookupValue("value")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
cluster, err := v.GetString("cluster")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
obj := new(unstructured.Unstructured)
|
|
|
|
|
if err = val.UnmarshalTo(obj); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 11:53:38 +08:00
|
|
|
var pods []*unstructured.Unstructured
|
|
|
|
|
var collector PodCollector
|
|
|
|
|
|
|
|
|
|
switch obj.GroupVersionKind() {
|
2021-11-24 11:09:50 +08:00
|
|
|
case fluxcdGroupVersion.WithKind(HelmReleaseKind):
|
2021-11-18 11:53:38 +08:00
|
|
|
collector = helmReleasePodCollector
|
|
|
|
|
default:
|
|
|
|
|
collector = NewPodCollector(obj.GroupVersionKind())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pods, err = collector(h.cli, obj, cluster)
|
2021-11-11 13:40:14 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return v.FillObject(err.Error(), "err")
|
|
|
|
|
}
|
|
|
|
|
return v.FillObject(pods, "list")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (h *provider) SearchEvents(ctx wfContext.Context, v *value.Value, act types.Action) error {
|
|
|
|
|
val, err := v.LookupValue("value")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
cluster, err := v.GetString("cluster")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
obj := new(unstructured.Unstructured)
|
|
|
|
|
if err = val.UnmarshalTo(obj); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
listCtx := multicluster.ContextWithClusterName(stdctx.Background(), cluster)
|
|
|
|
|
fieldSelector := getEventFieldSelector(obj)
|
|
|
|
|
eventList := corev1.EventList{}
|
|
|
|
|
listOpts := []client.ListOption{
|
|
|
|
|
client.InNamespace(obj.GetNamespace()),
|
|
|
|
|
client.MatchingFieldsSelector{
|
|
|
|
|
Selector: fieldSelector,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
if err := h.cli.List(listCtx, &eventList, listOpts...); err != nil {
|
|
|
|
|
return v.FillObject(err.Error(), "err")
|
|
|
|
|
}
|
|
|
|
|
return v.FillObject(eventList.Items, "list")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Install register handlers to provider discover.
|
|
|
|
|
func Install(p providers.Providers, cli client.Client) {
|
|
|
|
|
prd := &provider{
|
|
|
|
|
cli: cli,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.Register(ProviderName, map[string]providers.Handler{
|
|
|
|
|
"listResourcesInApp": prd.ListResourcesInApp,
|
|
|
|
|
"collectPods": prd.CollectPods,
|
|
|
|
|
"searchEvents": prd.SearchEvents,
|
|
|
|
|
})
|
|
|
|
|
}
|