diff --git a/deploy/crds/kosmos.io_virtualclusters.yaml b/deploy/crds/kosmos.io_virtualclusters.yaml index aa88214bc..aa4f3b3be 100644 --- a/deploy/crds/kosmos.io_virtualclusters.yaml +++ b/deploy/crds/kosmos.io_virtualclusters.yaml @@ -51,6 +51,19 @@ spec: description: Kubeconfig is the kubeconfig of the virtual kubernetes's control plane type: string + pluginOptions: + description: datasource for plugin yaml + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array promotePolicies: description: PromotePolicies definites the policies for promote to the kubernetes's control plane diff --git a/examples/vitual-cluster-demo.yaml b/examples/vitual-cluster-demo.yaml index d4893a0ef..f7319cff8 100644 --- a/examples/vitual-cluster-demo.yaml +++ b/examples/vitual-cluster-demo.yaml @@ -13,3 +13,8 @@ spec: promoteResources: nodeInfos: - nodeName: nodeName1 + pluginOptions: + - name: accessKey + value: hello + - name: secretKey + value: world diff --git a/pkg/apis/kosmos/v1alpha1/virtualcluster_types.go b/pkg/apis/kosmos/v1alpha1/virtualcluster_types.go index 2c8b27e66..cd8b91dda 100644 --- a/pkg/apis/kosmos/v1alpha1/virtualcluster_types.go +++ b/pkg/apis/kosmos/v1alpha1/virtualcluster_types.go @@ -61,6 +61,17 @@ type VirtualClusterSpec struct { // the resources can be nodes or just cpu,memory or gpu resources // +optional PromoteResources PromoteResources `json:"promoteResources,omitempty"` + + // datasource for plugin yaml + // +optional + PluginOptions []PluginOptions `json:"pluginOptions,omitempty"` +} + +type PluginOptions struct { + // +required + Name string `json:"name"` + // +required + Value string `json:"value"` } type PromotePolicy struct { diff --git a/pkg/apis/kosmos/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/kosmos/v1alpha1/zz_generated.deepcopy.go index 1e482c9ae..c375988bc 100644 --- a/pkg/apis/kosmos/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/kosmos/v1alpha1/zz_generated.deepcopy.go @@ -1323,6 +1323,22 @@ func (in *NodeSelectorConverter) DeepCopy() *NodeSelectorConverter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PluginOptions) DeepCopyInto(out *PluginOptions) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginOptions. +func (in *PluginOptions) DeepCopy() *PluginOptions { + if in == nil { + return nil + } + out := new(PluginOptions) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodConvertPolicy) DeepCopyInto(out *PodConvertPolicy) { *out = *in @@ -1733,6 +1749,11 @@ func (in *VirtualClusterSpec) DeepCopyInto(out *VirtualClusterSpec) { } } in.PromoteResources.DeepCopyInto(&out.PromoteResources) + if in.PluginOptions != nil { + in, out := &in.PluginOptions, &out.PluginOptions + *out = make([]PluginOptions, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index defaec587..eb88b6d23 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -65,6 +65,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.NodeNameConverter": schema_pkg_apis_kosmos_v1alpha1_NodeNameConverter(ref), "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.NodeSelector": schema_pkg_apis_kosmos_v1alpha1_NodeSelector(ref), "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.NodeSelectorConverter": schema_pkg_apis_kosmos_v1alpha1_NodeSelectorConverter(ref), + "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PluginOptions": schema_pkg_apis_kosmos_v1alpha1_PluginOptions(ref), "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PodConvertPolicy": schema_pkg_apis_kosmos_v1alpha1_PodConvertPolicy(ref), "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PodConvertPolicyList": schema_pkg_apis_kosmos_v1alpha1_PodConvertPolicyList(ref), "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PodConvertPolicySpec": schema_pkg_apis_kosmos_v1alpha1_PodConvertPolicySpec(ref), @@ -2347,6 +2348,33 @@ func schema_pkg_apis_kosmos_v1alpha1_NodeSelectorConverter(ref common.ReferenceC } } +func schema_pkg_apis_kosmos_v1alpha1_PluginOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "value": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "value"}, + }, + }, + } +} + func schema_pkg_apis_kosmos_v1alpha1_PodConvertPolicy(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3020,11 +3048,25 @@ func schema_pkg_apis_kosmos_v1alpha1_VirtualClusterSpec(ref common.ReferenceCall Ref: ref("github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PromoteResources"), }, }, + "pluginOptions": { + SchemaProps: spec.SchemaProps{ + Description: "datasource for plugin yaml", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PluginOptions"), + }, + }, + }, + }, + }, }, }, }, Dependencies: []string{ - "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PromotePolicy", "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PromoteResources"}, + "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PluginOptions", "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PromotePolicy", "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1.PromoteResources"}, } } diff --git a/pkg/kubenest/init.go b/pkg/kubenest/init.go index b67099239..2cecd402b 100644 --- a/pkg/kubenest/init.go +++ b/pkg/kubenest/init.go @@ -38,6 +38,7 @@ type initData struct { hostPort int32 hostPortMap map[string]int32 kubeNestOptions *ko.KubeNestOptions + virtualCluster *v1alpha1.VirtualCluster } type InitOptions struct { @@ -184,6 +185,7 @@ func newRunData(opt *InitOptions) (*initData, error) { hostPort: opt.virtualCluster.Status.Port, hostPortMap: opt.virtualCluster.Status.PortMap, kubeNestOptions: opt.KubeNestOptions, + virtualCluster: opt.virtualCluster, }, nil } @@ -258,3 +260,16 @@ func (i initData) DynamicClient() *dynamic.DynamicClient { func (i initData) KubeNestOpt() *ko.KubeNestOptions { return i.kubeNestOptions } + +func (i initData) PluginOptions() map[string]string { + if i.virtualCluster.Spec.PluginOptions == nil { + return nil + } + + pluginOptoinsMapping := map[string]string{} + + for _, option := range i.virtualCluster.Spec.PluginOptions { + pluginOptoinsMapping[option.Name] = option.Value + } + return pluginOptoinsMapping +} diff --git a/pkg/kubenest/tasks/coredns.go b/pkg/kubenest/tasks/coredns.go index b38ee4b11..037873c7d 100644 --- a/pkg/kubenest/tasks/coredns.go +++ b/pkg/kubenest/tasks/coredns.go @@ -116,6 +116,9 @@ func runCoreDnsHostTask(r workflow.RunData) error { "Name": data.GetName(), "ImageRepository": imageRepository, } + for k, v := range data.PluginOptions() { + templatedMapping[k] = v + } err = applyYMLTemplate(dynamicClient, component.Path, templatedMapping) if err != nil { return err @@ -243,6 +246,9 @@ func runCoreDnsVirtualTask(r workflow.RunData) error { "MetricsPort": MetricsPort, "HostNodeAddress": HostNodeAddress, } + for k, v := range data.PluginOptions() { + templatedMapping[k] = v + } err = applyYMLTemplate(dynamicClient, component.Path, templatedMapping) if err != nil { return err diff --git a/pkg/kubenest/tasks/data.go b/pkg/kubenest/tasks/data.go index 7b9de7cae..02c9a37e2 100644 --- a/pkg/kubenest/tasks/data.go +++ b/pkg/kubenest/tasks/data.go @@ -24,4 +24,5 @@ type InitData interface { HostPortMap() map[string]int32 DynamicClient() *dynamic.DynamicClient KubeNestOpt() *ko.KubeNestOptions + PluginOptions() map[string]string } diff --git a/pkg/kubenest/tasks/manifests_components.go b/pkg/kubenest/tasks/manifests_components.go index 14446a4b7..a68cf846f 100644 --- a/pkg/kubenest/tasks/manifests_components.go +++ b/pkg/kubenest/tasks/manifests_components.go @@ -84,6 +84,10 @@ func applyComponentsManifests(r workflow.RunData) error { imageRepository, _ := util.GetImageMessage() templatedMapping["ImageRepository"] = imageRepository + for k, v := range data.PluginOptions() { + templatedMapping[k] = v + } + for _, component := range components { klog.V(2).Infof("Deploy component %s", component.Name) err = applyTemplatedManifests(component.Name, dynamicClient, component.Path, templatedMapping) diff --git a/pkg/kubenest/util/template.go b/pkg/kubenest/util/template.go index 43ebceb10..62effa72b 100644 --- a/pkg/kubenest/util/template.go +++ b/pkg/kubenest/util/template.go @@ -6,10 +6,21 @@ import ( "text/template" ) +// pluginOptions +func defaultValue(value interface{}, defaultVal string) string { + if str, ok := value.(string); ok && str != "" { + return str + } + return defaultVal +} + // ParseTemplate validates and parses passed as argument template func ParseTemplate(strtmpl string, obj interface{}) (string, error) { var buf bytes.Buffer - tmpl, err := template.New("template").Parse(strtmpl) + tmpl := template.New("template").Funcs(template.FuncMap{ + "defaultValue": defaultValue, + }) + tmpl, err := tmpl.Parse(strtmpl) if err != nil { return "", fmt.Errorf("error when parsing template, err: %w", err) }