github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/fault/fault_stress.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 fault
    21  
    22  import (
    23  	"fmt"
    24  
    25  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    26  	"github.com/spf13/cobra"
    27  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/cli-runtime/pkg/genericiooptions"
    30  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    31  	"k8s.io/kubectl/pkg/util/templates"
    32  
    33  	"github.com/1aal/kubeblocks/pkg/cli/create"
    34  )
    35  
    36  var faultStressExample = templates.Examples(`
    37  	# Affects the first container in default namespace's all pods.Making CPU load up to 50%, and the memory up to 100MB. 
    38  	kbcli fault stress --cpu-worker=2 --cpu-load=50 --memory-worker=1 --memory-size=100Mi
    39  
    40  	# Affects the first container in mycluster-mysql-0 pod. Making the CPU load up to 50%, and the memory up to 500MB.
    41  	kbcli fault stress mycluster-mysql-0 --cpu-worker=2 --cpu-load=50
    42  	
    43  	# Affects the mysql container in mycluster-mysql-0 pod. Making the memory up to 500MB.
    44  	kbcli fault stress mycluster-mysql-0 --memory-worker=2 --memory-size=500Mi  -c=mysql
    45  `)
    46  
    47  type CPU struct {
    48  	Workers int `json:"workers"`
    49  	Load    int `json:"load"`
    50  }
    51  
    52  type Memory struct {
    53  	Workers int    `json:"workers"`
    54  	Size    string `json:"size"`
    55  }
    56  
    57  type Stressors struct {
    58  	CPU    `json:"cpu"`
    59  	Memory `json:"memory"`
    60  }
    61  
    62  type StressChaosOptions struct {
    63  	Stressors      `json:"stressors"`
    64  	ContainerNames []string `json:"containerNames,omitempty"`
    65  
    66  	FaultBaseOptions
    67  }
    68  
    69  func NewStressChaosOptions(f cmdutil.Factory, streams genericiooptions.IOStreams, action string) *StressChaosOptions {
    70  	o := &StressChaosOptions{
    71  		FaultBaseOptions: FaultBaseOptions{
    72  			CreateOptions: create.CreateOptions{
    73  				Factory:         f,
    74  				IOStreams:       streams,
    75  				CueTemplateName: CueTemplateStressChaos,
    76  				GVR:             GetGVR(Group, Version, ResourceStressChaos),
    77  			},
    78  			Action: action,
    79  		},
    80  	}
    81  	o.CreateOptions.PreCreate = o.PreCreate
    82  	o.CreateOptions.Options = o
    83  	return o
    84  }
    85  
    86  func NewStressChaosCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
    87  	o := NewStressChaosOptions(f, streams, "")
    88  	cmd := o.NewCobraCommand(Stress, StressShort)
    89  
    90  	o.AddCommonFlag(cmd, f)
    91  	return cmd
    92  }
    93  
    94  func (o *StressChaosOptions) NewCobraCommand(use, short string) *cobra.Command {
    95  	return &cobra.Command{
    96  		Use:     use,
    97  		Short:   short,
    98  		Example: faultStressExample,
    99  		Run: func(cmd *cobra.Command, args []string) {
   100  			o.Args = args
   101  			cmdutil.CheckErr(o.CreateOptions.Complete())
   102  			cmdutil.CheckErr(o.Validate())
   103  			cmdutil.CheckErr(o.Complete())
   104  			cmdutil.CheckErr(o.Run())
   105  		},
   106  	}
   107  }
   108  
   109  func (o *StressChaosOptions) AddCommonFlag(cmd *cobra.Command, f cmdutil.Factory) {
   110  	o.FaultBaseOptions.AddCommonFlag(cmd)
   111  
   112  	cmd.Flags().IntVar(&o.CPU.Workers, "cpu-worker", 0, `Specifies the number of threads that exert CPU pressure.`)
   113  	cmd.Flags().IntVar(&o.CPU.Load, "cpu-load", 0, `Specifies the percentage of CPU occupied. 0 means no extra load added, 100 means full load. The total load is workers * load.`)
   114  	cmd.Flags().IntVar(&o.Memory.Workers, "memory-worker", 0, `Specifies the number of threads that apply memory pressure.`)
   115  	cmd.Flags().StringVar(&o.Memory.Size, "memory-size", "", `Specify the size of the allocated memory or the percentage of the total memory, and the sum of the allocated memory is size. For example:256MB or 25%`)
   116  	cmd.Flags().StringArrayVarP(&o.ContainerNames, "container", "c", nil, "The name of the container, such as mysql, prometheus.If it's empty, the first container will be injected.")
   117  
   118  	// register flag completion func
   119  	registerFlagCompletionFunc(cmd, f)
   120  }
   121  
   122  func (o *StressChaosOptions) Validate() error {
   123  	if o.Memory.Workers == 0 && o.CPU.Workers == 0 {
   124  		return fmt.Errorf("the CPU or Memory workers must have at least one greater than 0, Use --cpu-workers or --memory-workers to specify")
   125  	}
   126  
   127  	return o.BaseValidate()
   128  }
   129  
   130  func (o *StressChaosOptions) Complete() error {
   131  	return o.BaseComplete()
   132  }
   133  
   134  func (o *StressChaosOptions) PreCreate(obj *unstructured.Unstructured) error {
   135  	c := &v1alpha1.StressChaos{}
   136  	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, c); err != nil {
   137  		return err
   138  	}
   139  
   140  	data, e := runtime.DefaultUnstructuredConverter.ToUnstructured(c)
   141  	if e != nil {
   142  		return e
   143  	}
   144  	obj.SetUnstructuredContent(data)
   145  	return nil
   146  }