diff --git a/references/cli/adopt-templates/default.cue b/references/cli/adopt-templates/default.cue index 28095e84c..ba94b1844 100644 --- a/references/cli/adopt-templates/default.cue +++ b/references/cli/adopt-templates/default.cue @@ -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 + }] } -} +} \ No newline at end of file diff --git a/references/cli/adopt.go b/references/cli/adopt.go index abca3d7bc..fe34ddfc6 100644 --- a/references/cli/adopt.go +++ b/references/cli/adopt.go @@ -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 / or //") + return nil, fmt.Errorf("resource should be like / or // or ///") } 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