...

Source file src/github.com/chaos-mesh/chaos-mesh/cmd/chaos-builder/main.go

Documentation: github.com/chaos-mesh/chaos-mesh/cmd/chaos-builder

     1  // Copyright 2020 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package main
    15  
    16  import (
    17  	"fmt"
    18  	"go/ast"
    19  	"go/parser"
    20  	"go/token"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/pingcap/errors"
    26  	"sigs.k8s.io/controller-runtime/pkg/log/zap"
    27  )
    28  
    29  var (
    30  	log = zap.New(zap.UseDevMode(true))
    31  )
    32  
    33  type metadata struct {
    34  	Type       string
    35  	OneShotExp string
    36  }
    37  
    38  func main() {
    39  	implCode := boilerplate + implImport
    40  
    41  	testCode := boilerplate + testImport
    42  	initImpl := ""
    43  	scheduleImpl := ""
    44  	allTypes := make([]string, 0, 10)
    45  
    46  	workflowGenerator := newWorkflowCodeGenerator(nil)
    47  	workflowTestGenerator := newWorkflowTestCodeGenerator(nil)
    48  	workflowFrontendGenerator := newWorkflowFrontendCodeGenerator(nil)
    49  
    50  	scheduleGenerator := newScheduleCodeGenerator(nil)
    51  
    52  	filepath.Walk("./api/v1alpha1", func(path string, info os.FileInfo, err error) error {
    53  		log := log.WithValues("file", path)
    54  
    55  		if err != nil {
    56  			log.Error(err, "fail to walk in directory")
    57  			return err
    58  		}
    59  		if info.IsDir() {
    60  			return nil
    61  		}
    62  		if !strings.HasSuffix(info.Name(), ".go") {
    63  			return nil
    64  		}
    65  
    66  		fset := token.NewFileSet()
    67  		file, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
    68  		if err != nil {
    69  			log.Error(err, "fail to parse file")
    70  			return err
    71  		}
    72  
    73  		cmap := ast.NewCommentMap(fset, file, file.Comments)
    74  
    75  	out:
    76  		for node, commentGroups := range cmap {
    77  			for _, commentGroup := range commentGroups {
    78  				var err error
    79  				var oneShotExp string
    80  				for _, comment := range commentGroup.List {
    81  					if strings.Contains(comment.Text, "+chaos-mesh:oneshot") {
    82  						oneShotExp = strings.TrimPrefix(comment.Text, "// +chaos-mesh:oneshot=")
    83  						log.Info("decode oneshot expression", "expression", oneShotExp)
    84  					}
    85  				}
    86  				for _, comment := range commentGroup.List {
    87  					if strings.Contains(comment.Text, "+chaos-mesh:base") {
    88  						log.Info("build", "pos", fset.Position(comment.Pos()))
    89  						baseDecl, ok := node.(*ast.GenDecl)
    90  						if !ok {
    91  							err = errors.Errorf("node is not a *ast.GenDecl")
    92  							log.Error(err, "fail to get type")
    93  							return err
    94  						}
    95  
    96  						if baseDecl.Tok != token.TYPE {
    97  							err = errors.Errorf("node.Tok is not token.TYPE")
    98  							log.Error(err, "fail to get type")
    99  							return err
   100  						}
   101  
   102  						baseType, ok := baseDecl.Specs[0].(*ast.TypeSpec)
   103  						if !ok {
   104  							err = errors.Errorf("node is not a *ast.TypeSpec")
   105  							log.Error(err, "fail to get type")
   106  							return err
   107  						}
   108  						if baseType.Name.Name != "Workflow" {
   109  							implCode += generateImpl(baseType.Name.Name, oneShotExp)
   110  							testCode += generateTest(baseType.Name.Name)
   111  							initImpl += generateInit(baseType.Name.Name)
   112  							workflowGenerator.AppendTypes(baseType.Name.Name)
   113  							workflowTestGenerator.AppendTypes(baseType.Name.Name)
   114  							workflowFrontendGenerator.AppendTypes(baseType.Name.Name)
   115  						}
   116  						scheduleImpl += generateScheduleRegister(baseType.Name.Name)
   117  						scheduleGenerator.AppendTypes(baseType.Name.Name)
   118  						allTypes = append(allTypes, baseType.Name.Name)
   119  						continue out
   120  					}
   121  				}
   122  			}
   123  		}
   124  
   125  		return nil
   126  	})
   127  
   128  	implCode += fmt.Sprintf(`
   129  func init() {
   130  %s
   131  %s
   132  }
   133  `, initImpl, scheduleImpl)
   134  	file, err := os.Create("./api/v1alpha1/zz_generated.chaosmesh.go")
   135  	if err != nil {
   136  		log.Error(err, "fail to create file")
   137  		os.Exit(1)
   138  	}
   139  	fmt.Fprint(file, implCode)
   140  
   141  	testCode += testInit
   142  	file, err = os.Create("./api/v1alpha1/zz_generated.chaosmesh_test.go")
   143  	if err != nil {
   144  		log.Error(err, "fail to create file")
   145  		os.Exit(1)
   146  	}
   147  	fmt.Fprint(file, testCode)
   148  
   149  	file, err = os.Create("./api/v1alpha1/zz_generated.workflow.chaosmesh.go")
   150  	if err != nil {
   151  		log.Error(err, "fail to create file")
   152  		os.Exit(1)
   153  	}
   154  	fmt.Fprint(file, workflowGenerator.Render())
   155  
   156  	file, err = os.Create("./api/v1alpha1/zz_generated.workflow.chaosmesh_test.go")
   157  	if err != nil {
   158  		log.Error(err, "fail to create file")
   159  		os.Exit(1)
   160  	}
   161  	fmt.Fprint(file, workflowTestGenerator.Render())
   162  
   163  	file, err = os.Create("./ui/src/api/zz_generated.workflow.chaos-mesh.ts")
   164  	if err != nil {
   165  		log.Error(err, "fail to create file")
   166  		os.Exit(1)
   167  	}
   168  	fmt.Fprint(file, workflowFrontendGenerator.Render())
   169  
   170  	file, err = os.Create("./api/v1alpha1/zz_generated.schedule.chaosmesh.go")
   171  	if err != nil {
   172  		log.Error(err, "fail to create file")
   173  		os.Exit(1)
   174  	}
   175  	fmt.Fprint(file, scheduleGenerator.Render())
   176  
   177  }
   178