...

Source file src/github.com/chaos-mesh/chaos-mesh/tools/schedule-migration/main.go

Documentation: github.com/chaos-mesh/chaos-mesh/tools/schedule-migration

     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  // 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  	"io/ioutil"
    19  	"os"
    20  	"strings"
    21  
    22  	"gopkg.in/yaml.v2"
    23  )
    24  
    25  type Item struct {
    26  	ApiVersion string        `yaml:"apiVersion"`
    27  	Kind       string        `yaml:"kind"`
    28  	Metadata   yaml.MapSlice `yaml:"metadata"`
    29  	Spec       yaml.MapSlice `yaml:"spec"`
    30  }
    31  
    32  func main() {
    33  	if len(os.Args) != 3 {
    34  		fmt.Println("migrator <old-yaml> <new-yaml>")
    35  		os.Exit(1)
    36  	}
    37  	data, err := ioutil.ReadFile(os.Args[1])
    38  	if err != nil {
    39  		fmt.Println(err)
    40  		os.Exit(1)
    41  	}
    42  	var (
    43  		old Item
    44  		new Item
    45  	)
    46  	err = yaml.Unmarshal(data, &old)
    47  	if err != nil {
    48  		fmt.Println(err)
    49  		os.Exit(1)
    50  	}
    51  	{
    52  		var (
    53  			schedule     yaml.MapSlice
    54  			findSchedule bool
    55  		)
    56  
    57  		if isIncompatibleChaos(old) {
    58  			fmt.Printf("the define of %s is changed in v2.0, please modify it according to the document, refer to https://chaos-mesh.org/docs/\n", old.Kind)
    59  			os.Exit(1)
    60  		}
    61  
    62  		for _, item := range old.Spec {
    63  			if item.Key == "scheduler" {
    64  				schedule = item.Value.(yaml.MapSlice)
    65  				findSchedule = true
    66  			}
    67  		}
    68  
    69  		if findSchedule {
    70  			new = toScheduleObject(old, schedule)
    71  		} else {
    72  			new = old
    73  			new.Spec = transformChaosSpec(old)
    74  		}
    75  	}
    76  	data, err = yaml.Marshal(new)
    77  	if err != nil {
    78  		fmt.Println(err)
    79  		os.Exit(1)
    80  	}
    81  	err = ioutil.WriteFile(os.Args[2], data, 0644)
    82  	if err != nil {
    83  		fmt.Println(err)
    84  		os.Exit(1)
    85  	}
    86  }
    87  
    88  func getKeyName(name string) string {
    89  	s := strings.ToLower(name)
    90  	return strings.ReplaceAll(s, "chaos", "Chaos")
    91  }
    92  
    93  func toNewKind(kind string) string {
    94  	if kind == "IoChaos" {
    95  		return "IOChaos"
    96  	}
    97  	return kind
    98  }
    99  
   100  func toScheduleObject(old Item, schedule yaml.MapSlice) Item {
   101  	var new Item
   102  	var cron string
   103  	for _, item := range schedule {
   104  		if item.Key == "cron" {
   105  			cron = item.Value.(string)
   106  		}
   107  	}
   108  	new.ApiVersion = old.ApiVersion
   109  	new.Metadata = old.Metadata
   110  	new.Kind = "Schedule"
   111  	new.Spec = append(new.Spec, yaml.MapItem{Key: "schedule", Value: cron})
   112  	new.Spec = append(new.Spec, yaml.MapItem{Key: "type", Value: toNewKind(old.Kind)})
   113  	new.Spec = append(new.Spec, yaml.MapItem{Key: "historyLimit", Value: 5})
   114  	new.Spec = append(new.Spec, yaml.MapItem{Key: "concurrencyPolicy", Value: "Forbid"})
   115  
   116  	newSpec := transformChaosSpec(old)
   117  	new.Spec = append(new.Spec, yaml.MapItem{Key: getKeyName(old.Kind), Value: newSpec})
   118  	return new
   119  }
   120  
   121  func transformChaosSpec(item Item) yaml.MapSlice {
   122  	var (
   123  		newSpec        yaml.MapSlice
   124  		containerNames []string
   125  	)
   126  	for _, kv := range item.Spec {
   127  		if kv.Key == "scheduler" {
   128  			continue
   129  		}
   130  
   131  		if kv.Key == "containerName" {
   132  			containerNames = append(containerNames, kv.Value.(string))
   133  			continue
   134  		}
   135  
   136  		if item.Kind == "DNSChaos" {
   137  			// 'scope' is obsolete in v2.0, and instead with 'patterns'
   138  			// if 'scope' is 'all', means chaos applies to all the host
   139  			// so it equal to pattern "*". otherwise, can't transform.
   140  			if kv.Key == "scope" && kv.Value == "all" {
   141  				patterns := []string{"*"}
   142  				kv = yaml.MapItem{Key: "patterns", Value: patterns}
   143  			}
   144  		}
   145  
   146  		newSpec = append(newSpec, kv)
   147  	}
   148  
   149  	if len(containerNames) != 0 {
   150  		newSpec = append(newSpec, yaml.MapItem{Key: "containerNames", Value: containerNames})
   151  	}
   152  
   153  	return newSpec
   154  }
   155  
   156  func isIncompatibleChaos(item Item) bool {
   157  	incompatible := false
   158  	switch item.Kind {
   159  	case "DNSChaos":
   160  		for _, kv := range item.Spec {
   161  			// 'scope' is obsolete in v2.0, and instead with 'patterns'
   162  			// if 'scope' is 'all', means chaos applies to all the host
   163  			// so it equal to pattern "*". otherwise, can't transform.
   164  			if kv.Key == "scope" && kv.Value != "all" {
   165  				incompatible = true
   166  			}
   167  		}
   168  	default:
   169  	}
   170  
   171  	return incompatible
   172  }
   173