github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/builder/template/template.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package template
    21  
    22  import (
    23  	"os"
    24  	"path/filepath"
    25  
    26  	"github.com/spf13/cobra"
    27  	"k8s.io/cli-runtime/pkg/genericiooptions"
    28  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    29  	"k8s.io/kubectl/pkg/util/templates"
    30  
    31  	"github.com/1aal/kubeblocks/pkg/cli/util"
    32  	cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core"
    33  	"github.com/1aal/kubeblocks/pkg/constant"
    34  	viper "github.com/1aal/kubeblocks/pkg/viperx"
    35  )
    36  
    37  type renderTPLCmdOpts struct {
    38  	genericiooptions.IOStreams
    39  
    40  	Factory cmdutil.Factory
    41  	// dynamic dynamic.Interface
    42  
    43  	clusterYaml    string
    44  	clusterDef     string
    45  	clusterVersion string
    46  
    47  	outputDir       string
    48  	clearOutputDir  bool
    49  	helmOutputDir   string
    50  	helmTemplateDir string
    51  
    52  	opts RenderedOptions
    53  }
    54  
    55  func (o *renderTPLCmdOpts) complete() error {
    56  	if err := o.checkAndHelmTemplate(); err != nil {
    57  		return err
    58  	}
    59  
    60  	if o.helmOutputDir == "" {
    61  		return cfgcore.MakeError("helm template dir is empty")
    62  	}
    63  
    64  	if o.clearOutputDir && o.outputDir != "" {
    65  		_ = os.RemoveAll(o.outputDir)
    66  	}
    67  	if o.outputDir == "" {
    68  		o.outputDir = filepath.Join("./output", RandomString(6))
    69  	}
    70  	return nil
    71  }
    72  
    73  func (o *renderTPLCmdOpts) run() error {
    74  	viper.SetDefault(constant.KubernetesClusterDomainEnv, constant.DefaultDNSDomain)
    75  	workflow, err := NewWorkflowTemplateRender(o.helmOutputDir, o.opts, o.clusterDef, o.clusterVersion)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	return workflow.Do(o.outputDir)
    80  }
    81  
    82  var templateExamples = templates.Examples(`
    83      # builder template: Provides a mechanism to rendered template for ComponentConfigSpec and ComponentScriptSpec in the ClusterComponentDefinition.
    84      # builder template --helm deploy/redis --memory=64Gi --cpu=16 --replicas=3 --component-name=redis --config-spec=redis-replication-config  
    85  
    86      # build all configspec
    87      kbcli builder template --helm deploy/redis -a
    88  `)
    89  
    90  // buildReconfigureCommonFlags build common flags for reconfigure command
    91  func (o *renderTPLCmdOpts) buildTemplateFlags(cmd *cobra.Command) {
    92  	cmd.Flags().StringVar(&o.clusterYaml, "cluster", "", "the cluster yaml file")
    93  	cmd.Flags().StringVar(&o.clusterVersion, "cluster-version", "", "specify the cluster version name")
    94  	cmd.Flags().StringVar(&o.clusterDef, "cluster-definition", "", "specify the cluster definition name")
    95  	cmd.Flags().StringVarP(&o.outputDir, "output-dir", "o", "", "specify the output directory")
    96  
    97  	cmd.Flags().StringVar(&o.opts.ConfigSpec, "config-spec", "", "specify the config spec to be rendered")
    98  
    99  	// mock cluster object
   100  	cmd.Flags().Int32VarP(&o.opts.Replicas, "replicas", "r", 1, "specify the replicas of the component")
   101  	cmd.Flags().StringVar(&o.opts.DataVolumeName, "volume-name", "", "specify the data volume name of the component")
   102  	cmd.Flags().StringVar(&o.opts.ComponentName, "component-name", "", "specify the component name of the clusterdefinition")
   103  	cmd.Flags().StringVar(&o.helmTemplateDir, "helm", "", "specify the helm template dir")
   104  	cmd.Flags().StringVar(&o.helmOutputDir, "helm-output", "", "specify the helm template output dir")
   105  	cmd.Flags().StringVar(&o.opts.CPU, "cpu", "", "specify the cpu of the component")
   106  	cmd.Flags().StringVar(&o.opts.Memory, "memory", "", "specify the memory of the component")
   107  	cmd.Flags().BoolVar(&o.clearOutputDir, "clean", false, "specify whether to clear the output dir")
   108  }
   109  
   110  func (o *renderTPLCmdOpts) checkAndHelmTemplate() error {
   111  	if o.helmTemplateDir == "" || o.helmOutputDir != "" {
   112  		return nil
   113  	}
   114  
   115  	if o.helmTemplateDir != "" && o.helmOutputDir == "" {
   116  		o.helmOutputDir = filepath.Join("./helm-output", RandomString(6))
   117  	}
   118  
   119  	return HelmTemplate(o.helmTemplateDir, o.helmOutputDir)
   120  }
   121  
   122  func NewComponentTemplateRenderCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
   123  	o := &renderTPLCmdOpts{
   124  		Factory:   f,
   125  		IOStreams: streams,
   126  		opts: RenderedOptions{
   127  			// for mock cluster object
   128  			Namespace: "default",
   129  			Name:      "cluster-" + RandomString(6),
   130  		},
   131  	}
   132  	cmd := &cobra.Command{
   133  		Use:     "template",
   134  		Aliases: []string{"tpl"},
   135  		Short:   "tpl - a developer tool integrated with KubeBlocks that can help developers quickly generate rendered configurations or scripts based on Helm templates, and discover errors in the template before creating the database cluster.",
   136  		Example: templateExamples,
   137  		Run: func(cmd *cobra.Command, args []string) {
   138  			util.CheckErr(o.complete())
   139  			util.CheckErr(o.run())
   140  		},
   141  	}
   142  	o.buildTemplateFlags(cmd)
   143  	return cmd
   144  }