Skip to content

Commit

Permalink
Merge pull request #131 from sergenyalcin/apply-in-interval
Browse files Browse the repository at this point in the history
Support for applying manifests in a specified time interval
  • Loading branch information
sergenyalcin authored Sep 11, 2023
2 parents 6e567eb + 0390516 commit e7a4ea0
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 33 deletions.
105 changes: 73 additions & 32 deletions cmd/perf/internal/managed/managed.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ import (
// RunExperiment runs the experiment according to command-line inputs.
// Firstly the input manifests are deployed. After the all MRs are ready, time to readiness metrics are calculated.
// Then, by default, all deployed MRs are deleted.
func RunExperiment(mrTemplatePaths map[string]int, clean bool) ([]common.Result, error) {
func RunExperiment(mrTemplatePaths map[string]int, clean bool, applyInterval time.Duration) ([]common.Result, error) {
var timeToReadinessResults []common.Result

client := createDynamicClient()

tmpFileName, err := applyResources(mrTemplatePaths)
tmpFiles, err := applyResources(mrTemplatePaths, applyInterval)
if err != nil {
return nil, errors.Wrap(err, "cannot apply resources")
}
Expand All @@ -70,51 +70,92 @@ func RunExperiment(mrTemplatePaths map[string]int, clean bool) ([]common.Result,

if clean {
log.Info("Deleting resources...")
if err := deleteResources(tmpFileName); err != nil {
return nil, errors.Wrap(err, "cannot delete resources")
for _, tmpFile := range tmpFiles {
if err := deleteResources(tmpFile); err != nil {
return nil, errors.Wrap(err, "cannot delete resources")
}
}
}
return timeToReadinessResults, nil
}

func applyResources(mrTemplatePaths map[string]int) (string, error) {
f, err := os.CreateTemp("/tmp", "")
if err != nil {
return "", errors.Wrap(err, "cannot create input file")
}

for mrPath, count := range mrTemplatePaths {
m, err := readYamlFile(mrPath)
func applyResources(mrTemplatePaths map[string]int, applyInterval time.Duration) ([]string, error) { //nolint:gocyclo // easy to follow all cases here
switch applyInterval { //nolint:exhaustive // not necessary to handle all duration cases
case 0 * time.Second:
f, err := os.CreateTemp("/tmp", "")
if err != nil {
return "", errors.Wrap(err, "cannot read template file")
return nil, errors.Wrap(err, "cannot create input file")
}

for i := 1; i <= count; i++ {
m["metadata"].(map[interface{}]interface{})["name"] = fmt.Sprintf("testperfrun%d", i)

b, err := yaml.Marshal(m)
for mrPath, count := range mrTemplatePaths {
m, err := readYamlFile(mrPath)
if err != nil {
return "", errors.Wrap(err, "cannot marshal object")
return nil, errors.Wrap(err, "cannot read template file")
}

if _, err := f.Write(b); err != nil {
return "", errors.Wrap(err, "cannot write manifest")
for i := 1; i <= count; i++ {
if err := createManifest(f, m, i); err != nil {
return nil, err
}
}

if _, err := f.WriteString("\n---\n\n"); err != nil {
return "", errors.Wrap(err, "cannot write yaml separator")
if err := runApplyCommand(f); err != nil {
return nil, err
}
}

if err := f.Close(); err != nil {
return "", errors.Wrap(err, "cannot close input file")
return []string{f.Name()}, nil
default:
var tmpFiles []string
for mrPath, count := range mrTemplatePaths {
m, err := readYamlFile(mrPath)
if err != nil {
return nil, errors.Wrap(err, "cannot read template file")
}
for i := 1; i <= count; i++ {
f, err := os.CreateTemp("/tmp", "")
if err != nil {
return nil, errors.Wrap(err, "cannot create input file")
}
if err := createManifest(f, m, i); err != nil {
return nil, err
}
if err := runApplyCommand(f); err != nil {
return nil, err
}
if i != count {
time.Sleep(applyInterval)
}
tmpFiles = append(tmpFiles, f.Name())
}
}
return tmpFiles, nil
}
}

if err := runCommand(fmt.Sprintf(`"kubectl" apply -f %s`, f.Name())); err != nil {
return "", errors.Wrap(err, "cannot execute kubectl apply command")
}
func createManifest(f *os.File, m map[interface{}]interface{}, index int) error {
m["metadata"].(map[interface{}]interface{})["name"] = fmt.Sprintf("testperfrun%d", index)

b, err := yaml.Marshal(m)
if err != nil {
return errors.Wrap(err, "cannot marshal object")
}

if _, err := f.Write(b); err != nil {
return errors.Wrap(err, "cannot write manifest")
}
return f.Name(), nil

if _, err := f.WriteString("\n---\n\n"); err != nil {
return errors.Wrap(err, "cannot write yaml separator")
}
return nil
}

func runApplyCommand(f *os.File) error {
if err := f.Close(); err != nil {
return errors.Wrap(err, "cannot close input file")
}
if err := runCommand(fmt.Sprintf(`"kubectl" apply -f %s`, f.Name())); err != nil {
return errors.Wrap(err, "cannot execute kubectl apply command")
}
return nil
}

func deleteResources(tmpFileName string) error {
Expand Down Expand Up @@ -280,7 +321,7 @@ func runCommand(command string) error {
sc := bufio.NewScanner(stdout)
sc.Split(bufio.ScanLines)
for sc.Scan() {
fmt.Println(sc.Text())
log.Info(sc.Text())
}
if err := cmd.Wait(); err != nil {
return errors.Wrap(err, "cannot wait for the command exit")
Expand Down
4 changes: 3 additions & 1 deletion cmd/perf/internal/quantify.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type QuantifyOptions struct {
stepDuration time.Duration
clean bool
nodeIP string
applyInterval time.Duration
timeout time.Duration
}

Expand All @@ -70,6 +71,7 @@ func NewCmdQuantify() *cobra.Command {
o.cmd.Flags().DurationVar(&o.stepDuration, "step-duration", 1*time.Second, "Step duration between two data points")
o.cmd.Flags().BoolVar(&o.clean, "clean", true, "Delete deployed MRs")
o.cmd.Flags().StringVar(&o.nodeIP, "node", "", "Node IP")
o.cmd.Flags().DurationVar(&o.applyInterval, "apply-interval", 0*time.Second, "Elapsed time between applying two manifests to the cluster. Example = 10s. This means that examples will be applied every 10 seconds.")
o.cmd.Flags().DurationVar(&o.timeout, "timeout", 120*time.Minute, "Timeout for the experiment")

if err := o.cmd.MarkFlagRequired("provider-pods"); err != nil {
Expand All @@ -90,7 +92,7 @@ func (o *QuantifyOptions) Run(_ *cobra.Command, _ []string) error {
results := make(chan []common.Result, 5)
errChan := make(chan error, 1)
go func() {
timeToReadinessResults, err := managed.RunExperiment(o.mrPaths, o.clean)
timeToReadinessResults, err := managed.RunExperiment(o.mrPaths, o.clean, o.applyInterval)
if err != nil {
errChan <- errors.Wrap(err, "cannot run experiment")
return
Expand Down

0 comments on commit e7a4ea0

Please sign in to comment.