github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/bench/tpch.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 bench 21 22 import ( 23 "context" 24 "fmt" 25 "strings" 26 27 "github.com/spf13/cobra" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 30 "k8s.io/apimachinery/pkg/runtime" 31 "k8s.io/cli-runtime/pkg/genericiooptions" 32 cmdutil "k8s.io/kubectl/pkg/cmd/util" 33 "k8s.io/kubectl/pkg/util/templates" 34 35 "github.com/apecloud/kubebench/api/v1alpha1" 36 37 "github.com/1aal/kubeblocks/pkg/cli/cluster" 38 "github.com/1aal/kubeblocks/pkg/cli/types" 39 ) 40 41 var ( 42 tpchDriverMap = map[string]string{ 43 "mysql": "mysql", 44 } 45 tpchSupportedDrivers = []string{"mysql"} 46 ) 47 48 var tpchExample = templates.Examples(` 49 # tpch on a cluster, that will exec for all steps, cleanup, prepare and run 50 kbcli bench tpch mytest --cluster mycluster --user xxx --password xxx --database mydb 51 52 # tpch on a cluster with run, just run by running the test 53 kbcli bench tpch run mytest --cluster mycluster --user xxx --password xxx --database mydb 54 `) 55 56 type TpchOptions struct { 57 BenchBaseOptions 58 } 59 60 func NewTpchCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command { 61 o := &TpchOptions{ 62 BenchBaseOptions: BenchBaseOptions{ 63 IOStreams: streams, 64 factory: f, 65 }, 66 } 67 cmd := &cobra.Command{ 68 Use: "tpch [Step] [BenchmarkName]", 69 Short: "Run tpch benchmark", 70 Example: tpchExample, 71 Run: func(cmd *cobra.Command, args []string) { 72 cmdutil.CheckErr(o.Complete(args)) 73 cmdutil.CheckErr(o.Validate()) 74 cmdutil.CheckErr(o.Run()) 75 }, 76 } 77 78 o.AddFlags(cmd) 79 80 return cmd 81 } 82 83 func (o *TpchOptions) Complete(args []string) error { 84 var err error 85 var driver string 86 var host string 87 var port int 88 89 if err = o.BenchBaseOptions.BaseComplete(); err != nil { 90 return err 91 } 92 93 o.Step, o.name = parseStepAndName(args, "tpch") 94 95 o.namespace, _, err = o.factory.ToRawKubeConfigLoader().Namespace() 96 if err != nil { 97 return err 98 } 99 100 if o.dynamic, err = o.factory.DynamicClient(); err != nil { 101 return err 102 } 103 104 if o.client, err = o.factory.KubernetesClientSet(); err != nil { 105 return err 106 } 107 108 if o.ClusterName != "" { 109 clusterGetter := cluster.ObjectsGetter{ 110 Client: o.client, 111 Dynamic: o.dynamic, 112 Name: o.ClusterName, 113 Namespace: o.namespace, 114 GetOptions: cluster.GetOptions{ 115 WithClusterDef: true, 116 WithService: true, 117 WithPod: true, 118 WithEvent: true, 119 WithPVC: true, 120 WithDataProtection: true, 121 }, 122 } 123 if o.ClusterObjects, err = clusterGetter.Get(); err != nil { 124 return err 125 } 126 driver, host, port, err = getDriverAndHostAndPort(o.Cluster, o.Services) 127 if err != nil { 128 return err 129 } 130 } 131 132 // don't overwrite the driver if it's already set 133 if v, ok := tpchDriverMap[driver]; ok && o.Driver == "" { 134 o.Driver = v 135 } 136 137 // don't overwrite the host and port if they are already set 138 if o.Host == "" && o.Port == 0 { 139 o.Host = host 140 o.Port = port 141 } 142 143 return nil 144 } 145 146 func (o *TpchOptions) Validate() error { 147 if err := o.BenchBaseOptions.BaseValidate(); err != nil { 148 return err 149 } 150 151 var supported bool 152 for _, v := range tpchDriverMap { 153 if o.Driver == v { 154 supported = true 155 break 156 } 157 } 158 if !supported { 159 return fmt.Errorf("tpch now only supports drivers in [%s], current cluster driver is %s", 160 strings.Join(tpchSupportedDrivers, ", "), o.Driver) 161 } 162 163 if o.User == "" { 164 return fmt.Errorf("user is required") 165 } 166 167 if o.Database == "" { 168 return fmt.Errorf("database is required") 169 } 170 171 return nil 172 } 173 174 func (o *TpchOptions) Run() error { 175 tpch := v1alpha1.Tpch{ 176 TypeMeta: metav1.TypeMeta{ 177 Kind: "Tpch", 178 APIVersion: types.TpchGVR().GroupVersion().String(), 179 }, 180 ObjectMeta: metav1.ObjectMeta{ 181 Name: o.name, 182 Namespace: o.namespace, 183 }, 184 Spec: v1alpha1.TpchSpec{ 185 BenchCommon: v1alpha1.BenchCommon{ 186 ExtraArgs: o.ExtraArgs, 187 Step: o.Step, 188 Tolerations: o.Tolerations, 189 Target: v1alpha1.Target{ 190 Driver: o.Driver, 191 Host: o.Host, 192 Port: o.Port, 193 User: o.User, 194 Password: o.Password, 195 Database: o.Database, 196 }, 197 }, 198 }, 199 } 200 201 obj := &unstructured.Unstructured{ 202 Object: map[string]interface{}{}, 203 } 204 data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tpch) 205 if err != nil { 206 return err 207 } 208 obj.SetUnstructuredContent(data) 209 210 obj, err = o.dynamic.Resource(types.TpchGVR()).Namespace(o.namespace).Create(context.TODO(), obj, metav1.CreateOptions{}) 211 if err != nil { 212 return err 213 } 214 215 fmt.Fprintf(o.Out, "%s %s created\n", obj.GetKind(), obj.GetName()) 216 return nil 217 }