github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/subtool/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/Cloud-Foundations/Dominator/lib/constants"
    10  	"github.com/Cloud-Foundations/Dominator/lib/flags/commands"
    11  	"github.com/Cloud-Foundations/Dominator/lib/flags/loadflags"
    12  	"github.com/Cloud-Foundations/Dominator/lib/flagutil"
    13  	"github.com/Cloud-Foundations/Dominator/lib/log"
    14  	"github.com/Cloud-Foundations/Dominator/lib/log/cmdlogger"
    15  	"github.com/Cloud-Foundations/Dominator/lib/log/debuglogger"
    16  	"github.com/Cloud-Foundations/Dominator/lib/srpc"
    17  	"github.com/Cloud-Foundations/Dominator/lib/srpc/setupclient"
    18  )
    19  
    20  var (
    21  	computedFilesRoot = flag.String("computedFilesRoot", "",
    22  		"Name of directory tree containing computed files")
    23  	connectTimeout = flag.Duration("connectTimeout", 15*time.Second,
    24  		"connection timeout")
    25  	cpuPercent = flag.Uint("cpuPercent", 0,
    26  		"CPU speed as percentage of capacity (default 50)")
    27  	debug             = flag.Bool("debug", false, "Enable debug mode")
    28  	deleteBeforeFetch = flag.Bool("deleteBeforeFetch", false,
    29  		"If true, delete prior to Fetch rather than during Update")
    30  	file = flag.String("file", "",
    31  		"Name of file to write encoded data to")
    32  	filterFile = flag.String("filterFile", "",
    33  		"Replacement filter file to apply when pushing image")
    34  	imageServerHostname = flag.String("imageServerHostname", "localhost",
    35  		"Hostname of image server")
    36  	imageServerPortNum = flag.Uint("imageServerPortNum",
    37  		constants.ImageServerPortNumber,
    38  		"Port number of image server")
    39  	interval = flag.Uint("interval", 1,
    40  		"Seconds to sleep between Polls")
    41  	networkSpeedPercent = flag.Uint("networkSpeedPercent",
    42  		constants.DefaultNetworkSpeedPercent,
    43  		"Network speed as percentage of capacity")
    44  	newConnection = flag.Bool("newConnection", false,
    45  		"If true, (re)open a connection for each Poll")
    46  	numPolls = flag.Int("numPolls", 1,
    47  		"The number of polls to run (infinite: < 0)")
    48  	objectServerHostname = flag.String("objectServerHostname", "localhost",
    49  		"Hostname of image server")
    50  	objectServerPortNum = flag.Uint("objectServerPortNum",
    51  		constants.ImageServerPortNumber,
    52  		"Port number of image server")
    53  	scanExcludeList  flagutil.StringList = constants.ScanExcludeList
    54  	scanSpeedPercent                     = flag.Uint("scanSpeedPercent",
    55  		constants.DefaultScanSpeedPercent,
    56  		"Scan speed as percentage of capacity")
    57  	shortPoll = flag.Bool("shortPoll", false,
    58  		"If true, perform a short poll which does not request image or object data")
    59  	showTimes = flag.Bool("showTimes", false,
    60  		"If true, show time taken for some operations")
    61  	subHostname = flag.String("subHostname", "localhost", "Hostname of sub")
    62  	subPortNum  = flag.Uint("subPortNum", constants.SubPortNumber,
    63  		"Port number of sub")
    64  	timeout = flag.Duration("timeout", 15*time.Minute,
    65  		"timeout for long operations")
    66  	triggersFile = flag.String("triggersFile", "",
    67  		"Replacement triggers file to apply when pushing image")
    68  	triggersString = flag.String("triggersString", "",
    69  		"Replacement triggers string to apply when pushing image (ignored if triggersFile is set)")
    70  	wait = flag.Uint("wait", 0, "Seconds to sleep after last Poll")
    71  
    72  	logger      *debuglogger.Logger
    73  	timeoutTime time.Time
    74  )
    75  
    76  func init() {
    77  	flag.Var(&scanExcludeList, "scanExcludeList",
    78  		"Comma separated list of patterns to exclude from scanning")
    79  }
    80  
    81  func printUsage() {
    82  	w := flag.CommandLine.Output()
    83  	fmt.Fprintln(w,
    84  		"Usage: subtool [flags...] fetch|get-config|poll|set-config")
    85  	fmt.Fprintln(w, "Common flags:")
    86  	flag.PrintDefaults()
    87  	fmt.Fprintln(w, "Commands:")
    88  	commands.PrintCommands(w, subcommands)
    89  }
    90  
    91  func getSubClient(logger log.DebugLogger) *srpc.Client {
    92  	clientName := fmt.Sprintf("%s:%d", *subHostname, *subPortNum)
    93  	client, err := srpc.DialHTTP("tcp", clientName, *connectTimeout)
    94  	if err != nil {
    95  		logger.Fatalf("Error dialing %s: %s\n", clientName, err)
    96  	}
    97  	return client
    98  }
    99  
   100  func getSubClientRetry(logger log.DebugLogger) *srpc.Client {
   101  	clientName := fmt.Sprintf("%s:%d", *subHostname, *subPortNum)
   102  	var client *srpc.Client
   103  	var err error
   104  	for time.Now().Before(timeoutTime) {
   105  		client, err = srpc.DialHTTP("tcp", clientName, time.Second*5)
   106  		if err == nil {
   107  			return client
   108  		}
   109  		if err == srpc.ErrorMissingCertificate ||
   110  			err == srpc.ErrorBadCertificate ||
   111  			err == srpc.ErrorAccessToMethodDenied {
   112  			// Never going to happen. Bail out.
   113  			logger.Fatalf("Error dialing %s: %s\n", clientName, err)
   114  		}
   115  	}
   116  	logger.Fatalf("Error dialing %s: %s\n", clientName, err)
   117  	return nil
   118  }
   119  
   120  var subcommands = []commands.Command{
   121  	{"boost-cpu-limit", "", 0, 0, boostCpuLimitSubcommand},
   122  	{"cleanup", "", 0, 0, cleanupSubcommand},
   123  	{"delete", "pathname...", 1, 1, deleteSubcommand},
   124  	{"fetch", "hashesFile", 1, 1, fetchSubcommand},
   125  	{"get-config", "", 0, 0, getConfigSubcommand},
   126  	{"get-file", "remoteFile localFile", 2, 2, getFileSubcommand},
   127  	{"list-missing-objects", "image", 1, 1, listMissingObjectsSubcommand},
   128  	{"poll", "", 0, 0, pollSubcommand},
   129  	{"push-file", "source dest", 2, 2, pushFileSubcommand},
   130  	{"push-image", "image", 1, 1, pushImageSubcommand},
   131  	{"push-missing-objects", "image", 1, 1, pushMissingObjectsSubcommand},
   132  	{"restart-service", "name", 1, 1, restartServiceSubcommand},
   133  	{"set-config", "", 0, 0, setConfigSubcommand},
   134  	{"show-update-request", "image", 1, 1, showUpdateRequestSubcommand},
   135  	{"wait-for-image", "image", 1, 1, waitForImageSubcommand},
   136  }
   137  
   138  func doMain() int {
   139  	if err := loadflags.LoadForCli("subtool"); err != nil {
   140  		fmt.Fprintln(os.Stderr, err)
   141  		return 1
   142  	}
   143  	flag.Usage = printUsage
   144  	flag.Parse()
   145  	if flag.NArg() < 1 {
   146  		printUsage()
   147  		return 2
   148  	}
   149  	logger = cmdlogger.New()
   150  	if *triggersFile != "" && *triggersString != "" {
   151  		logger.Fatalln(os.Stderr,
   152  			"Cannot specify both -triggersFile and -triggersString")
   153  	}
   154  	if err := setupclient.SetupTls(true); err != nil {
   155  		logger.Fatalln(os.Stderr, err)
   156  	}
   157  	timeoutTime = time.Now().Add(*timeout)
   158  	return commands.RunCommands(subcommands, printUsage, logger)
   159  }
   160  
   161  func main() {
   162  	os.Exit(doMain())
   163  }