mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 12:06:38 +00:00
vela adopt support multi-cluster adoption (#5635)
Signed-off-by: Basuotian <basuoluomiu@gmail.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import "list"
|
||||
metadata: {
|
||||
name: string
|
||||
namespace?: string
|
||||
annotations?: [string]: string
|
||||
...
|
||||
}
|
||||
...
|
||||
@@ -30,6 +31,12 @@ import "list"
|
||||
properties?: {...}
|
||||
}
|
||||
|
||||
#WorkflowStep: {
|
||||
type: string
|
||||
name: string
|
||||
properties?: {...}
|
||||
}
|
||||
|
||||
#Application: {
|
||||
apiVersion: "core.oam.dev/v1beta1"
|
||||
kind: "Application"
|
||||
@@ -42,7 +49,9 @@ import "list"
|
||||
spec: {
|
||||
components: [...#Component]
|
||||
policies?: [...#Policy]
|
||||
workflow?: {...}
|
||||
workflow?: {
|
||||
steps: [...#WorkflowStep]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +60,7 @@ import "list"
|
||||
type: *"native" | "helm" | string
|
||||
appName: string
|
||||
appNamespace: string
|
||||
resources: [...#Resource]
|
||||
resources: [...#Resource]
|
||||
...
|
||||
}
|
||||
|
||||
@@ -77,8 +86,10 @@ import "list"
|
||||
_category: *"unknown" | string
|
||||
for key, kinds in resourceCategoryMap if list.Contains(kinds, r.kind) {
|
||||
_category: key
|
||||
}
|
||||
},
|
||||
_cluster: r.metadata.annotations["app.oam.dev/cluster"]
|
||||
}]
|
||||
_clusters: [ for r in _resources {r._cluster} ]
|
||||
resourceMap: {
|
||||
for key, val in resourceCategoryMap {
|
||||
"\(key)": [ for r in _resources if r._category == key {r}]
|
||||
@@ -100,6 +111,7 @@ import "list"
|
||||
apiVersion: r.apiVersion
|
||||
kind: r.kind
|
||||
metadata: name: r.metadata.name
|
||||
metadata: annotations: "app.oam.dev/cluster": "\(r._cluster)"
|
||||
}]
|
||||
},
|
||||
if len(resourceMap.ns) > 0 {
|
||||
@@ -109,6 +121,7 @@ import "list"
|
||||
apiVersion: r.apiVersion
|
||||
kind: r.kind
|
||||
metadata: name: r.metadata.name
|
||||
metadata: annotations: "app.oam.dev/cluster": "\(r._cluster)"
|
||||
}]
|
||||
},
|
||||
for r in resourceMap.workload + resourceMap.service {
|
||||
@@ -134,6 +147,7 @@ import "list"
|
||||
if r.metadata.namespace != _|_ {
|
||||
metadata: namespace: r.metadata.namespace
|
||||
}
|
||||
metadata: annotations: "app.oam.dev/cluster": "\(r._cluster)"
|
||||
}]
|
||||
},
|
||||
for kind, rs in unknownByKinds {
|
||||
@@ -143,10 +157,23 @@ import "list"
|
||||
apiVersion: r.apiVersion
|
||||
kind: r.kind
|
||||
metadata: name: r.metadata.name
|
||||
metadata: annotations: "app.oam.dev/cluster": "\(r._cluster)"
|
||||
}]
|
||||
},
|
||||
]
|
||||
|
||||
clusterCompMap: {
|
||||
for cluster in _clusters {
|
||||
"\(cluster)": [ for comp in comps if comp.properties.objects[0].metadata.annotations["app.oam.dev/cluster"] == cluster {comp.name} ]
|
||||
}
|
||||
}
|
||||
|
||||
compClusterMap: {
|
||||
for comp in comps {
|
||||
"\(comp.name)": comp.properties.objects[0].metadata.annotations["app.oam.dev/cluster"]
|
||||
}
|
||||
}
|
||||
|
||||
$returns: #Application & {
|
||||
metadata: {
|
||||
name: $args.appName
|
||||
@@ -154,7 +181,7 @@ import "list"
|
||||
labels: "app.oam.dev/adopt": $args.type
|
||||
}
|
||||
spec: components: comps
|
||||
spec: policies: [
|
||||
spec: policies: [
|
||||
{
|
||||
type: $args.mode
|
||||
name: $args.mode
|
||||
@@ -162,6 +189,11 @@ import "list"
|
||||
selector: componentNames: [ for comp in spec.components {comp.name}]
|
||||
}]
|
||||
},
|
||||
for cluster, comp in clusterCompMap if (len(clusterCompMap) < 2) && (cluster != "local") {
|
||||
type: "topology"
|
||||
name: "topology-" + cluster
|
||||
properties: clusters: [cluster]
|
||||
},
|
||||
if $args.mode == "take-over" {
|
||||
type: "garbage-collect"
|
||||
name: "garbage-collect"
|
||||
@@ -177,5 +209,11 @@ import "list"
|
||||
selector: resourceTypes: ["CustomResourceDefinition"]
|
||||
}]
|
||||
}]
|
||||
spec: workflow: steps: [for comp, c in compClusterMap if len(clusterCompMap) > 1 {
|
||||
type: "apply-component"
|
||||
name: "apply-component-" + comp
|
||||
properties: component: comp
|
||||
properties: cluster: c
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
-13
@@ -50,6 +50,8 @@ import (
|
||||
"github.com/kubevela/pkg/util/resourcetopology"
|
||||
velaslices "github.com/kubevela/pkg/util/slices"
|
||||
|
||||
"github.com/kubevela/pkg/multicluster"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
@@ -63,14 +65,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
adoptTypeNative = "native"
|
||||
adoptTypeHelm = "helm"
|
||||
adoptModeReadOnly = v1alpha1.ReadOnlyPolicyType
|
||||
adoptModeTakeOver = v1alpha1.TakeOverPolicyType
|
||||
helmDriverEnvKey = "HELM_DRIVER"
|
||||
defaultHelmDriver = "secret"
|
||||
adoptCUETempVal = "adopt"
|
||||
adoptCUETempFunc = "#Adopt"
|
||||
adoptTypeNative = "native"
|
||||
adoptTypeHelm = "helm"
|
||||
adoptModeReadOnly = v1alpha1.ReadOnlyPolicyType
|
||||
adoptModeTakeOver = v1alpha1.TakeOverPolicyType
|
||||
helmDriverEnvKey = "HELM_DRIVER"
|
||||
defaultHelmDriver = "secret"
|
||||
adoptCUETempVal = "adopt"
|
||||
adoptCUETempFunc = "#Adopt"
|
||||
defaultLocalCluster = "local"
|
||||
)
|
||||
|
||||
//go:embed adopt-templates/default.cue
|
||||
@@ -87,7 +90,8 @@ var (
|
||||
type resourceRef struct {
|
||||
schema.GroupVersionKind
|
||||
apitypes.NamespacedName
|
||||
Arg string
|
||||
Cluster string
|
||||
Arg string
|
||||
}
|
||||
|
||||
// AdoptOptions options for vela adopt command
|
||||
@@ -151,7 +155,7 @@ func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command,
|
||||
return nil, fmt.Errorf("no mappings found for resource %s: %w", arg, err)
|
||||
}
|
||||
mapping := mappings[0]
|
||||
or := &resourceRef{GroupVersionKind: gvk, Arg: arg}
|
||||
or := &resourceRef{GroupVersionKind: gvk, Cluster: defaultLocalCluster, Arg: arg}
|
||||
switch len(parts) {
|
||||
case 2:
|
||||
or.Name = parts[1]
|
||||
@@ -164,8 +168,12 @@ func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command,
|
||||
case 3:
|
||||
or.Namespace = parts[1]
|
||||
or.Name = parts[2]
|
||||
case 4:
|
||||
or.Cluster = parts[1]
|
||||
or.Namespace = parts[2]
|
||||
or.Name = parts[3]
|
||||
default:
|
||||
return nil, fmt.Errorf("resource should be like <type>/<name> or <type>/<namespace>/<name>")
|
||||
return nil, fmt.Errorf("resource should be like <type>/<name> or <type>/<namespace>/<name> or <type>/<cluster>/<namespace>/<name>")
|
||||
}
|
||||
return or, nil
|
||||
}
|
||||
@@ -435,9 +443,13 @@ func (opt *AdoptOptions) loadNative(f velacmd.Factory, cmd *cobra.Command) error
|
||||
for _, ref := range opt.NativeResourceRefs {
|
||||
obj := &unstructured.Unstructured{}
|
||||
obj.SetGroupVersionKind(ref.GroupVersionKind)
|
||||
if err := f.Client().Get(cmd.Context(), apitypes.NamespacedName{Namespace: ref.Namespace, Name: ref.Name}, obj); err != nil {
|
||||
return fmt.Errorf("failed to get resource for %s: %w", ref.Arg, err)
|
||||
if err := f.Client().Get(multicluster.WithCluster(cmd.Context(), ref.Cluster), apitypes.NamespacedName{Namespace: ref.Namespace, Name: ref.Name}, obj); err != nil {
|
||||
return fmt.Errorf("fail to get resource for %s: %w", ref.Arg, err)
|
||||
}
|
||||
annos := map[string]string{
|
||||
oam.LabelAppCluster: ref.Cluster,
|
||||
}
|
||||
obj.SetAnnotations(annos)
|
||||
opt.Resources = append(opt.Resources, obj)
|
||||
}
|
||||
return nil
|
||||
@@ -463,6 +475,10 @@ func (opt *AdoptOptions) loadHelm() error {
|
||||
klog.Warningf("unable to decode object %s: %s", val, err)
|
||||
continue
|
||||
}
|
||||
annos := map[string]string{
|
||||
oam.LabelAppCluster: defaultLocalCluster,
|
||||
}
|
||||
obj.SetAnnotations(annos)
|
||||
objs = append(objs, obj)
|
||||
}
|
||||
opt.Resources = objs
|
||||
|
||||
Reference in New Issue
Block a user