...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/debug/iochaos.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/debug

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package debug
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/hasura/go-graphql-client"
    24  
    25  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    26  	"github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/common"
    27  	ctrlclient "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/client"
    28  )
    29  
    30  type ioDebugger struct {
    31  	client *ctrlclient.CtrlClient
    32  }
    33  
    34  func IODebug(client *ctrlclient.CtrlClient) Debugger {
    35  	return &ioDebugger{
    36  		client: client,
    37  	}
    38  }
    39  
    40  func (d *ioDebugger) Collect(ctx context.Context, namespace, chaosName string) ([]*common.ChaosResult, error) {
    41  	var results []*common.ChaosResult
    42  
    43  	var name *graphql.String
    44  	if chaosName != "" {
    45  		n := graphql.String(chaosName)
    46  		name = &n
    47  	}
    48  
    49  	var query struct {
    50  		Namespace []struct {
    51  			IOChaos []struct {
    52  				Name   string
    53  				Podios []struct {
    54  					Namespace string
    55  					Name      string
    56  					// TODO: fit types with v1alpha1.PodIOChaosSpec
    57  					Spec struct {
    58  						VolumeMountPath string
    59  						Container       *string
    60  						Actions         []struct {
    61  							Type            v1alpha1.IOChaosType
    62  							v1alpha1.Filter `json:",inline"`
    63  							Faults          []v1alpha1.IoFault
    64  							Latency         string
    65  							Ino             *uint64               `json:"ino,omitempty"`
    66  							Size            *uint64               `json:"size,omitempty"`
    67  							Blocks          *uint64               `json:"blocks,omitempty"`
    68  							Atime           *v1alpha1.Timespec    `json:"atime,omitempty"`
    69  							Mtime           *v1alpha1.Timespec    `json:"mtime,omitempty"`
    70  							Ctime           *v1alpha1.Timespec    `json:"ctime,omitempty"`
    71  							Kind            *v1alpha1.FileType    `json:"kind,omitempty"`
    72  							Perm            *uint                 `json:"perm,omitempty"`
    73  							Nlink           *uint                 `json:"nlink,omitempty"`
    74  							UID             *uint                 `json:"uid,omitempty"`
    75  							GID             *uint                 `json:"gid,omitempty"`
    76  							Rdev            *uint                 `json:"rdev,omitempty"`
    77  							Filling         *v1alpha1.FillingType `json:"filling,omitempty"`
    78  							MaxOccurrences  *int64                `json:"maxOccurrences,omitempty"`
    79  							MaxLength       *int64                `json:"maxLength,omitempty"`
    80  						}
    81  					}
    82  					Pod struct {
    83  						Mounts    []string
    84  						Processes []struct {
    85  							Pid     string
    86  							Command string
    87  							Fds     []struct {
    88  								Fd, Target string
    89  							}
    90  						}
    91  					}
    92  				}
    93  			} `graphql:"iochaos(name: $name)"`
    94  		} `graphql:"namespace(ns: $namespace)"`
    95  	}
    96  
    97  	variables := map[string]interface{}{
    98  		"namespace": graphql.String(namespace),
    99  		"name":      name,
   100  	}
   101  
   102  	err := d.client.QueryClient.Query(ctx, &query, variables)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	if len(query.Namespace) == 0 {
   108  		return results, nil
   109  	}
   110  
   111  	for _, ioChaos := range query.Namespace[0].IOChaos {
   112  		result := &common.ChaosResult{
   113  			Name: ioChaos.Name,
   114  		}
   115  
   116  		for _, podiochaos := range ioChaos.Podios {
   117  			podResult := common.PodResult{
   118  				Name: podiochaos.Name,
   119  			}
   120  
   121  			podResult.Items = append(podResult.Items, common.ItemResult{Name: "Mount Information", Value: strings.Join(podiochaos.Pod.Mounts, "\n")})
   122  			for _, process := range podiochaos.Pod.Processes {
   123  				var fds []string
   124  				for _, fd := range process.Fds {
   125  					fds = append(fds, fmt.Sprintf("%s -> %s", fd.Fd, fd.Target))
   126  				}
   127  				podResult.Items = append(podResult.Items, common.ItemResult{
   128  					Name:  fmt.Sprintf("file descriptors of PID: %s, COMMAND: %s", process.Pid, process.Command),
   129  					Value: strings.Join(fds, "\n"),
   130  				})
   131  			}
   132  			output, err := common.MarshalChaos(podiochaos.Spec)
   133  			if err != nil {
   134  				return nil, err
   135  			}
   136  			podResult.Items = append(podResult.Items, common.ItemResult{Name: "podiochaos", Value: output})
   137  			result.Pods = append(result.Pods, podResult)
   138  		}
   139  
   140  		results = append(results, result)
   141  	}
   142  	return results, nil
   143  }
   144  
   145  func (d *ioDebugger) List(ctx context.Context, namespace string) ([]string, error) {
   146  	var query struct {
   147  		Namespace []struct {
   148  			IOChaos []struct {
   149  				Name string
   150  			} `graphql:"iochaos"`
   151  		} `graphql:"namespace(ns: $namespace)"`
   152  	}
   153  
   154  	variables := map[string]interface{}{
   155  		"namespace": graphql.String(namespace),
   156  	}
   157  
   158  	err := d.client.QueryClient.Query(ctx, &query, variables)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	if len(query.Namespace) == 0 {
   164  		return nil, nil
   165  	}
   166  
   167  	var names []string
   168  	for _, ioChaos := range query.Namespace[0].IOChaos {
   169  		names = append(names, string(ioChaos.Name))
   170  	}
   171  	return names, nil
   172  }
   173