github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/repository/charms/fill-logs/actions/actions.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  func main() {
    14  	if err := run(os.Args); err != nil {
    15  		fmt.Fprintln(os.Stderr, err)
    16  		os.Exit(1)
    17  	}
    18  }
    19  
    20  func run(args []string) error {
    21  	if len(args) != 2 {
    22  		return fmt.Errorf("expected exactly one argument, the action name")
    23  	}
    24  	switch args[1] {
    25  	case "fill-unit":
    26  		return fillUnit()
    27  	case "fill-machine":
    28  		return fillMachine()
    29  	case "unit-size":
    30  		return unitLogSizes()
    31  	case "machine-size":
    32  		return machineLogSizes()
    33  	default:
    34  		return fmt.Errorf("unknown action: %q", args[1])
    35  	}
    36  }
    37  
    38  func fillUnit() error {
    39  	return fillLog(os.Stdout)
    40  }
    41  
    42  func unitLogSizes() error {
    43  	return writeSizes("/var/log/juju/unit-fill-logs*.log*")
    44  }
    45  
    46  func machineLogSizes() error {
    47  	return writeSizes("/var/log/juju/machine-*.log*")
    48  }
    49  
    50  func fillMachine() (err error) {
    51  	machine, err := getMachine()
    52  	if err != nil {
    53  		return err
    54  	}
    55  	svcname := fmt.Sprintf("jujud-machine-%d", machine)
    56  	out, err := exec.Command("service", svcname, "stop").CombinedOutput()
    57  	if err != nil {
    58  		return fmt.Errorf("error stopping machine agent %q: %s", svcname, out)
    59  	}
    60  	defer func() {
    61  		out, err2 := exec.Command("service", svcname, "start").CombinedOutput()
    62  		if err2 == nil {
    63  			return
    64  		}
    65  		if err == nil {
    66  			// function error is currently nil, so overwrite with this one.
    67  			err = fmt.Errorf("error starting machine agent %q: %s", svcname, out)
    68  			return
    69  		}
    70  		// function error is non-nil, so can't overwrite, just print.
    71  		fmt.Printf("error starting machine agent %q: %s", svcname, out)
    72  	}()
    73  	logname := fmt.Sprintf("/var/log/juju/machine-%d.log", machine)
    74  	f, err := os.OpenFile(logname, os.O_APPEND|os.O_WRONLY, 0644)
    75  	if err != nil {
    76  		return fmt.Errorf("failed to open machine log file: %v", err)
    77  	}
    78  	defer f.Close()
    79  	return fillLog(f)
    80  }
    81  
    82  func fillLog(w io.Writer) error {
    83  	megs, err := getMegs()
    84  	if err != nil {
    85  		return err
    86  	}
    87  	bytes := megs * 1024 * 1024
    88  	total := 0
    89  
    90  	for total < bytes {
    91  		// technically, the log file will be bigger than asked for, since it
    92  		// prepends a bunch of stuff to each log call, but this guarantees we've
    93  		// put *at least* this much data in the log, which should guarantee a
    94  		// rotation.
    95  		n, err := fmt.Fprintln(w, lorem)
    96  		if err != nil {
    97  			return fmt.Errorf("error writing to log: %s", err)
    98  		}
    99  		total += n
   100  	}
   101  	return nil
   102  }
   103  
   104  func writeSizes(glob string) error {
   105  	paths, err := filepath.Glob(glob)
   106  	if err != nil {
   107  		return fmt.Errorf("error getting logs for %q: %s", glob, err)
   108  	}
   109  
   110  	// go through the list in reverse, since the primary log file is always last,
   111  	// but it's a lot more convenient for parsing if it's first in the output.
   112  	for i, j := len(paths)-1, 0; i >= 0; i-- {
   113  		path := paths[i]
   114  		// Skip any log files that start with machine-lock as these aren't interesting
   115  		// for fill logs.
   116  		if strings.HasPrefix(filepath.Base(path), "machine-lock") {
   117  			continue
   118  		}
   119  		info, err := os.Stat(path)
   120  		if err != nil {
   121  			return fmt.Errorf("error stating log %q: %s", path, err)
   122  		}
   123  		name := fmt.Sprintf("result-map.log%d.name=%s", j, path)
   124  		size := fmt.Sprintf("result-map.log%d.size=%d", j, info.Size()/1024/1024)
   125  		out, err := exec.Command("action-set", name, size).CombinedOutput()
   126  		if err != nil {
   127  			return fmt.Errorf("error calling action-set: %s", out)
   128  		}
   129  		j++
   130  	}
   131  
   132  	return nil
   133  }
   134  
   135  func getMegs() (int, error) {
   136  	return getInt("megs")
   137  }
   138  
   139  func getMachine() (int, error) {
   140  	return getInt("machine")
   141  }
   142  
   143  func getInt(name string) (int, error) {
   144  	out, err := exec.Command("action-get", name).CombinedOutput()
   145  	if err != nil {
   146  		fmt.Fprintln(os.Stderr, out)
   147  		return 0, fmt.Errorf("error calling action-get: %s", err)
   148  	}
   149  	// for some reason the output always comes with a /n at the end, so just
   150  	// trim it.
   151  	return strconv.Atoi(strings.TrimSpace(string(out)))
   152  }
   153  
   154  const lorem = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`