示例#1
0
func keypairsCreateCmd(c *CLI, ctx *cli.Context) {
	usage := func(msg string) {
		fmt.Printf("Usage: %s keypairs create --name=<keypair-name> <private-key-path> <certificate-path>\n", c.Name)
		fatal(msg)
	}
	if len(ctx.Args()) < 2 {
		usage("too few arguments")
	}
	if !ctx.IsSet("name") || ctx.String("name") == "" {
		usage("--name is required")
	}
	api := c.GetAPIClient(ctx)
	resourceGroup := c.GetResourceGroup(ctx)
	name := ctx.String("name")
	privateKeyPath := ctx.Args()[0]
	certPath := ctx.Args()[1]
	privateKey, err := ioutil.ReadFile(privateKeyPath)
	if err != nil {
		fatal(err.Error())
	}
	cert, err := ioutil.ReadFile(certPath)
	if err != nil {
		fatal(err.Error())
	}
	keypair := gondor.KeyPair{
		ResourceGroup: resourceGroup.URL,
		Name:          &name,
		Key:           privateKey,
		Certificate:   cert,
	}
	if err := api.KeyPairs.Create(&keypair); err != nil {
		fatal(err.Error())
	}
	success("keypair created.")
}
示例#2
0
文件: commands.go 项目: zbroju/biclog
func cmdTripDelete(c *cli.Context) error {
	// Get loggers
	printUserMsg, printError := getLoggers()

	// Check obligatory flags
	if c.String("file") == NotSetStringValue {
		printError.Fatalln(errMissingFileFlag)
	}
	id := c.Int("id")
	if id == NotSetIntValue {
		printError.Fatalln(errMissingIdFlag)
	}

	// Open data file
	f := gsqlitehandler.New(c.String("file"), dataFileProperties)
	if err := f.Open(); err != nil {
		printError.Fatalln(err)
	}
	defer f.Close()

	// Delete bicycle type
	sqlDeleteTrip := fmt.Sprintf("DELETE FROM trips WHERE id=%d;", id)
	r, err := f.Handler.Exec(sqlDeleteTrip)
	if err != nil {
		printError.Fatalln(errWritingToFile)
	}
	if i, _ := r.RowsAffected(); i == 0 {
		printError.Fatalln(errNoTripWithID)
	}

	// Show summary
	printUserMsg.Printf("deleted tirp with id = %d\n", id)

	return nil
}
示例#3
0
//
// deleteFile removes a file from the bucket
//
func deleteFile(o *formatter, cx *cli.Context, cmd *cliCommand) error {
	if len(cx.Args()) <= 0 {
		return fmt.Errorf("you have not specified any files to delete")
	}

	bucket := cx.String("bucket")
	// step: ensure the bucket exists
	if found, err := cmd.hasBucket(bucket); err != nil {
		return err
	} else if !found {
		return fmt.Errorf("the bucket: %s does not exist", bucket)
	}

	for _, path := range getPaths(cx) {
		if err := cmd.removeFile(bucket, path); err != nil {
			o.fields(map[string]interface{}{
				"action": "delete",
				"bucket": bucket,
				"path":   path,
				"error":  err.Error(),
			}).log("failed to remove s3://%s/%s, error: %s", bucket, path, err)
			continue
		}
		o.fields(map[string]interface{}{
			"action": "delete",
			"bucket": bucket,
			"path":   path,
		}).log("successfully deleted the file s3://%s/%s\n", bucket, path)
	}

	return nil
}
示例#4
0
// initRobotAccount creates a GCP robot account for this connector.
func initRobotAccount(context *cli.Context, userClient *http.Client) (string, string) {
	params := url.Values{}
	params.Set("oauth_client_id", context.String("gcp-oauth-client-id"))

	url := fmt.Sprintf("%s%s?%s", lib.DefaultConfig.GCPBaseURL, "createrobot", params.Encode())
	response, err := userClient.Get(url)
	if err != nil {
		log.Fatalln(err)
	}
	if response.StatusCode != http.StatusOK {
		log.Fatalf("Failed to initialize robot account: %s\n", response.Status)
	}

	var robotInit struct {
		Success  bool   `json:"success"`
		Message  string `json:"message"`
		XMPPJID  string `json:"xmpp_jid"`
		AuthCode string `json:"authorization_code"`
	}

	if err = json.NewDecoder(response.Body).Decode(&robotInit); err != nil {
		log.Fatalln(err)
	}
	if !robotInit.Success {
		log.Fatalf("Failed to initialize robot account: %s\n", robotInit.Message)
	}

	return robotInit.XMPPJID, robotInit.AuthCode
}
示例#5
0
文件: lastseen.go 项目: dnaeon/gru
// Executes the "lastseen" command
func execLastseenCommand(c *cli.Context) error {
	client := newEtcdMinionClientFromFlags(c)

	cFlag := c.String("with-classifier")
	minions, err := parseClassifierPattern(client, cFlag)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	table := uitable.New()
	table.MaxColWidth = 80
	table.AddRow("MINION", "LASTSEEN")
	for _, minion := range minions {
		lastseen, err := client.MinionLastseen(minion)
		if err != nil {
			return cli.NewExitError(err.Error(), 1)
		}

		table.AddRow(minion, time.Unix(lastseen, 0))
	}

	fmt.Println(table)

	return nil
}
示例#6
0
// ProjectKill forces stop service containers.
func ProjectKill(p project.APIProject, c *cli.Context) error {
	err := p.Kill(context.Background(), c.String("signal"), c.Args()...)
	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}
	return nil
}
示例#7
0
func stepList(c *cli.Context) error {
	// Input validation
	stepLibURIs := []string{}
	stepLibURI := c.String(CollectionKey)
	if stepLibURI == "" {
		stepLibURIs = stepman.GetAllStepCollectionPath()
	} else {
		stepLibURIs = []string{stepLibURI}
	}

	format := c.String(FormatKey)
	if format == "" {
		format = OutputFormatRaw
	} else if !(format == OutputFormatRaw || format == OutputFormatJSON) {
		log.Fatalf("Invalid format: %s", format)
	}

	for _, URI := range stepLibURIs {
		if err := listSteps(URI, format); err != nil {
			log.Errorf("Failed to list steps in StepLib (%s), err: %s", URI, err)
		}
	}

	return nil
}
示例#8
0
文件: apply.go 项目: ycaille/gru
// Executes the "apply" command
func execApplyCommand(c *cli.Context) error {
	if len(c.Args()) < 1 {
		return cli.NewExitError(errNoModuleName.Error(), 64)
	}

	L := lua.NewState()
	defer L.Close()
	config := &catalog.Config{
		Module:   c.Args()[0],
		DryRun:   c.Bool("dry-run"),
		Logger:   resource.DefaultLogger,
		SiteRepo: c.String("siterepo"),
		L:        L,
	}

	katalog := catalog.New(config)
	if err := katalog.Load(); err != nil {
		if err != nil {
			return cli.NewExitError(err.Error(), 1)
		}
	}

	if err := katalog.Run(); err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	return nil
}
示例#9
0
文件: update.go 项目: godrei/stepman
func update(c *cli.Context) error {
	collectionURIs := []string{}

	// StepSpec collection path
	collectionURI := c.String(CollectionKey)
	if collectionURI == "" {
		log.Info("No StepLib specified, update all...")
		collectionURIs = stepman.GetAllStepCollectionPath()
	} else {
		collectionURIs = []string{collectionURI}
	}

	if len(collectionURIs) == 0 {
		log.Info("No local StepLib found, nothing to update...")
	}

	for _, URI := range collectionURIs {
		log.Infof("Update StepLib (%s)...", URI)
		if _, err := updateCollection(URI); err != nil {
			return fmt.Errorf("Failed to update StepLib (%s), error: %s", URI, err)
		}
	}

	return nil
}
示例#10
0
func commandEncodeAction(c *cli.Context) error {
	flagInput := c.String("input")
	flagOutput := c.String("output")
	fmt.Println("in", flagInput, "out", flagOutput)

	if flagInput == "" {
		fmt.Println("missing -input flag")
		os.Exit(1)
	}
	if flagOutput == "" {
		fmt.Println("missing -output flag")
		os.Exit(1)
	}

	encodeDirHandler := func() {
		if err := encodeDir(flagInput, flagOutput); err != nil {
			fmt.Println("Error", err)
			os.Exit(127)
		}
	}

	encodeFileHandler := func() {
		if err := encodeFile(flagInput, flagOutput); err != nil {
			fmt.Println("Error", err)
			os.Exit(127)
		}
	}

	dataHandler(flagInput, encodeDirHandler, encodeFileHandler)
	return nil
}
示例#11
0
文件: rhobot.go 项目: cfpb/rhobot
func updateGOCDHost(c *cli.Context, config *config.Config) (gocdServer *gocd.Server) {
	if c.String("host") != "" {
		config.SetGoCDHost(c.String("host"))
	}
	gocdServer = gocd.NewServerConfig(config.GOCDHost, config.GOCDPort, config.GOCDUser, config.GOCDPassword, config.GOCDTimeout)
	return
}
示例#12
0
// REQUEST: curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE
func (a *AwsInternalProvider) Apply(c *cli.Context) error {

	role := c.String("aws-role")
	if len(role) == 0 {
		return errors.New("flag aws-role not set")
	}

	resp, err := http.Get(fmt.Sprintf("%s%s", a.ServerAddress, role))
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	var responseJson map[string]interface{}
	fmt.Println(body)
	responseBytes := []byte(body)

	if err := json.Unmarshal(responseBytes, &responseJson); err != nil {
		return err
	}

	SetEnvironmentVariable("AWS_ACCESS_KEY_ID", responseJson["AccessKeyId"])
	SetEnvironmentVariable("AWS_SECRET_ACCESS_KEY", responseJson["SecretAccessKey"])
	SetEnvironmentVariable("AWS_SESSION_TOKEN", responseJson["Token"])

	return nil
}
示例#13
0
func getChangeAddress(wltFile string, a string, c *gcli.Context) (string, error) {
	chgAddr := c.String("c")
	for {
		if chgAddr == "" {
			// get the default wallet's coin base address
			if a != "" {
				// use the from address as change address
				chgAddr = a
				break
			}

			if wltFile != "" {
				wlt, err := wallet.Load(wltFile)
				if err != nil {
					return "", err
				}
				if len(wlt.Entries) > 0 {
					chgAddr = wlt.Entries[0].Address.String()
					break
				}
				return "", errors.New("no change address was found")
			}
			return "", errors.New("both wallet file, from address and change address are empty")
		}
		break
	}

	// validate the address
	_, err := cipher.DecodeBase58Address(chgAddr)
	if err != nil {
		return "", fmt.Errorf("invalid change address: %s", chgAddr)
	}

	return chgAddr, nil
}
示例#14
0
文件: generate.go 项目: hqhq/ocitools
func seccompSet(context *cli.Context, seccompFlag string, g *generate.Generator) error {
	flagInput := context.String("seccomp-" + seccompFlag)
	flagArgs := strings.Split(flagInput, ",")
	setSyscallArgsSlice := []seccomp.SyscallOpts{}
	for _, flagArg := range flagArgs {
		comparisonArgs := strings.Split(flagArg, ":")
		if len(comparisonArgs) == 5 {
			setSyscallArgs := seccomp.SyscallOpts{
				Action:   seccompFlag,
				Syscall:  comparisonArgs[0],
				Index:    comparisonArgs[1],
				Value:    comparisonArgs[2],
				ValueTwo: comparisonArgs[3],
				Operator: comparisonArgs[4],
			}
			setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
		} else if len(comparisonArgs) == 1 {
			setSyscallArgs := seccomp.SyscallOpts{
				Action:  seccompFlag,
				Syscall: comparisonArgs[0],
			}
			setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
		} else {
			return fmt.Errorf("invalid syscall argument formatting %v", comparisonArgs)
		}

		for _, r := range setSyscallArgsSlice {
			err := g.SetSyscallAction(r)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
示例#15
0
文件: commands.go 项目: zbroju/biclog
func cmdTypeAdd(c *cli.Context) error {
	// Get loggers
	printUserMsg, printError := getLoggers()

	// Check obligatory flags (file, name)
	if c.String("file") == NotSetStringValue {
		printError.Fatalln(errMissingFileFlag)

	}
	if c.String("type") == NotSetStringValue {
		printError.Fatalln(errMissingTypeFlag)
	}

	// Open data file
	f := gsqlitehandler.New(c.String("file"), dataFileProperties)
	if err := f.Open(); err != nil {
		printError.Fatalln(err)
	}
	defer f.Close()

	// Add new type
	sqlAddType := fmt.Sprintf("INSERT INTO bicycle_types VALUES (NULL, '%s');", c.String("type"))
	if _, err := f.Handler.Exec(sqlAddType); err != nil {
		printError.Fatalln(errWritingToFile)
	}

	// Show summary
	printUserMsg.Printf("added new bicycle type: %s\n", c.String("type"))

	return nil
}
示例#16
0
func getCheckpointImagePath(context *cli.Context) string {
	imagePath := context.String("image-path")
	if imagePath == "" {
		imagePath = getDefaultImagePath(context)
	}
	return imagePath
}
示例#17
0
文件: list.go 项目: yehohanan7/swarm
func list(c *cli.Context) {
	dflag := getDiscovery(c)
	if dflag == "" {
		log.Fatalf("discovery required to list a cluster. See '%s list --help'.", c.App.Name)
	}
	timeout, err := time.ParseDuration(c.String("timeout"))
	if err != nil {
		log.Fatalf("invalid --timeout: %v", err)
	}
	if timeout <= time.Duration(0)*time.Second {
		log.Fatalf("--timeout should be a positive number")
	}

	d, err := discovery.New(dflag, timeout, 0, getDiscoveryOpt(c))
	if err != nil {
		log.Fatal(err)
	}

	ch, errCh := d.Watch(nil)
	select {
	case entries := <-ch:
		for _, entry := range entries {
			fmt.Println(entry)
		}
	case err := <-errCh:
		log.Fatal(err)
	case <-time.After(timeout):
		log.Fatal("Timed out")
	}
}
示例#18
0
func deleteStepLib(c *cli.Context) error {
	// Input validation
	collectionURI := c.String(CollectionKey)
	if collectionURI == "" {
		return fmt.Errorf("Missing required input: collection")
	}

	log.Infof("Delete StepLib: %s", collectionURI)

	route, found := stepman.ReadRoute(collectionURI)
	if !found {
		log.Warnf("No route found for collection: %s, cleaning up routing..", collectionURI)
		if err := stepman.CleanupDanglingLib(collectionURI); err != nil {
			log.Errorf("Error cleaning up lib: %s", collectionURI)
		}
		log.Infof("Call 'stepman setup -c %s' for a clean setup", collectionURI)
		return nil
	}

	if err := stepman.CleanupRoute(route); err != nil {
		return fmt.Errorf("Failed to cleanup route for StepLib: %s", collectionURI)
	}

	return nil
}
示例#19
0
func runUpdate(c *cli.Context) error {
	if c.IsSet("config") {
		setting.CustomConf = c.String("config")
	}

	setup("update.log")

	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
		log.GitLogger.Trace("SSH_ORIGINAL_COMMAND is empty")
		return nil
	}

	args := c.Args()
	if len(args) != 3 {
		log.GitLogger.Fatal(2, "Arguments received are not equal to three")
	} else if len(args[0]) == 0 {
		log.GitLogger.Fatal(2, "First argument 'refName' is empty, shouldn't use")
	}

	task := models.UpdateTask{
		UUID:        os.Getenv("uuid"),
		RefName:     args[0],
		OldCommitID: args[1],
		NewCommitID: args[2],
	}

	if err := models.AddUpdateTask(&task); err != nil {
		log.GitLogger.Fatal(2, "AddUpdateTask: %v", err)
	}

	return nil
}
示例#20
0
func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, error) {
	id := context.Args().First()
	if id == "" {
		return -1, errEmptyID
	}
	container, err := createContainer(context, id, spec)
	if err != nil {
		return -1, err
	}
	// Support on-demand socket activation by passing file descriptors into the container init process.
	listenFDs := []*os.File{}
	if os.Getenv("LISTEN_FDS") != "" {
		listenFDs = activation.Files(false)
	}
	r := &runner{
		enableSubreaper: !context.Bool("no-subreaper"),
		shouldDestroy:   true,
		container:       container,
		listenFDs:       listenFDs,
		console:         context.String("console"),
		detach:          context.Bool("detach"),
		pidFile:         context.String("pid-file"),
		create:          create,
	}
	return r.run(&spec.Process)
}
示例#21
0
func pluginInstall(c *cli.Context) error {
	// Input validation
	pluginSource := c.String("source")
	if pluginSource == "" {
		log.Fatal("Missing required input: source")
	}

	pluginVersionTag := c.String("version")

	// Install
	if pluginVersionTag == "" {
		log.Infof("=> Installing plugin from (%s) with latest version...", pluginSource)
	} else {
		log.Infof("=> Installing plugin (%s) with version (%s)...", pluginSource, pluginVersionTag)
	}

	plugin, version, err := plugins.InstallPlugin(pluginSource, pluginVersionTag)
	if err != nil {
		log.Fatalf("Failed to install plugin from (%s), error: %s", pluginSource, err)
	}

	fmt.Println()
	log.Infoln(colorstring.Greenf("Plugin (%s) with version (%s) installed ", plugin.Name, version))

	if len(plugin.Description) > 0 {
		fmt.Println()
		fmt.Println(plugin.Description)
		fmt.Println()
	}

	return nil
}
示例#22
0
文件: list.go 项目: dnaeon/gru
// Executes the "list" command
func execListCommand(c *cli.Context) error {
	klient := newEtcdMinionClientFromFlags(c)

	cFlag := c.String("with-classifier")
	minions, err := parseClassifierPattern(klient, cFlag)

	// Ignore errors about missing minion directory
	if err != nil {
		if eerr, ok := err.(client.Error); !ok || eerr.Code != client.ErrorCodeKeyNotFound {
			return cli.NewExitError(err.Error(), 1)
		}
	}

	if len(minions) == 0 {
		return nil
	}

	table := uitable.New()
	table.MaxColWidth = 80
	table.AddRow("MINION", "NAME")
	for _, minion := range minions {
		name, err := klient.MinionName(minion)
		if err != nil {
			return cli.NewExitError(err.Error(), 1)
		}

		table.AddRow(minion, name)
	}

	fmt.Println(table)

	return nil
}
示例#23
0
func doGroupMemberList(c *cli.Context) error {
	srv, err := NewService()
	if err != nil {
		return nil
	}

	groupKey := c.String("key")

	r, err := srv.directory.Members.List(groupKey).Do()
	if err != nil {
		log.Fatalf("Unable to retrieve group members in domain. %v", err)
		return nil
	}

	count := len(r.Members)
	if count == 0 {
		fmt.Print("No group members found.\n")
	} else {
		for _, m := range r.Members {
			fmt.Printf("%v, %v\n", m.Email, m.Role)
		}
	}

	return nil
}
示例#24
0
文件: status.go 项目: hhatto/jc
func statusCommand(c *cli.Context) {
	url := Config.Get(c.String("name"))
	fmt.Println(c.String("name"), "-", url)
	printJobQueue(url, c.Bool("dump"))
	fmt.Println("")
	printServerInfo(url)
}
示例#25
0
func initialize(c *cli.Context, terraformCommand string) TerraformOperation {
	if len(c.Args()) < 1 {
		fmt.Printf("Incorrect usage\n")
		fmt.Printf("%s <environment>\n", terraformCommand)
		os.Exit(1)
	}

	fmt.Println(c.Args())
	environment := c.Args()[0]

	security.Apply(c.String("security"), c)

	fmt.Println()
	fmt.Println("Execute Terraform command")
	fmt.Println("Command:    ", command.Bold(terraformCommand))
	fmt.Println("Environment:", command.Bold(environment))
	fmt.Println()

	configLocation := c.String("config-location")
	config := terraform_config.LoadConfig(configLocation, environment)

	getState(c.Bool("no-sync"), config, environment)

	return TerraformOperation{
		command:     terraformCommand,
		environment: environment,
		config:      config,
		args:        os.Args[2:],
	}
}
示例#26
0
func runCreateUser(c *cli.Context) error {
	if !c.IsSet("name") {
		return fmt.Errorf("Username is not specified")
	} else if !c.IsSet("password") {
		return fmt.Errorf("Password is not specified")
	} else if !c.IsSet("email") {
		return fmt.Errorf("Email is not specified")
	}

	if c.IsSet("config") {
		setting.CustomConf = c.String("config")
	}

	setting.NewContext()
	models.LoadConfigs()
	models.SetEngine()

	if err := models.CreateUser(&models.User{
		Name:     c.String("name"),
		Email:    c.String("email"),
		Passwd:   c.String("password"),
		IsActive: true,
		IsAdmin:  c.Bool("admin"),
	}); err != nil {
		return fmt.Errorf("CreateUser: %v", err)
	}

	fmt.Printf("New user '%s' has been successfully created!\n", c.String("name"))
	return nil
}
// deleteAllGCPPrinterJobs finds all GCP printer jobs associated with a
// a given printer id and deletes them.
func deleteAllGCPPrinterJobs(context *cli.Context) {
	config := getConfig(context)
	gcp := getGCP(config)

	jobs, err := gcp.Fetch(context.String("printer-id"))
	if err != nil {
		log.Fatalln(err)
	}

	if len(jobs) == 0 {
		fmt.Printf("No queued jobs\n")
	}

	ch := make(chan bool)
	for _, job := range jobs {
		go func(gcpJobID string) {
			err := gcp.DeleteJob(gcpJobID)
			if err != nil {
				fmt.Printf("Failed to delete GCP job %s: %s\n", gcpJobID, err)
			} else {
				fmt.Printf("Deleted GCP job %s\n", gcpJobID)
			}
			ch <- true
		}(job.GCPJobID)
	}

	for _ = range jobs {
		<-ch
	}
}
示例#28
0
func walletHistoryAction(c *gcli.Context) error {
	if c.NArg() > 0 {
		fmt.Printf("Error: invalid argument\n\n")
		gcli.ShowSubcommandHelp(c)
		return nil
	}
	f := c.String("f")
	if f == "" {
		f = filepath.Join(cfg.WalletDir, cfg.DefaultWalletName)
	}

	// check the file extension.
	if !strings.HasSuffix(f, walletExt) {
		return errWalletName
	}

	// check if file name contains path.
	if filepath.Base(f) != f {
		af, err := filepath.Abs(f)
		if err != nil {
			return fmt.Errorf("invalid wallet file:%v, err:%v", f, err)
		}
		f = af
	} else {
		f = filepath.Join(cfg.WalletDir, f)
	}

	// get all addresses in the wallet.
	addrs, err := getAddresses(f)
	if err != nil {
		return err
	}

	// get all the addresses affected uxouts
	uxouts, err := getAddrUxOuts(addrs)
	if err != nil {
		return err
	}

	// transmute the uxout to addrHistory, and sort the items by time in ascend order.
	totalAddrHis := []addrHistory{}
	for _, ux := range uxouts {
		addrHis, err := makeAddrHisArray(ux)
		if err != nil {
			return err
		}
		totalAddrHis = append(totalAddrHis, addrHis...)
	}

	sort.Sort(byTime(totalAddrHis))

	// print the addr history
	v, err := json.MarshalIndent(totalAddrHis, "", "    ")
	if err != nil {
		return errJSONMarshal
	}
	fmt.Println(string(v))
	return nil
}
示例#29
0
func heimdallBefore(c *cli.Context) error {
	if c.Bool("verbose") {
		log.SetLevel(log.DebugLevel)
	}

	redisPool = newPool(c.String("redis"), c.String("redis-password"))
	return nil
}
示例#30
0
func cmdWrapper(c *cli.Context) error {
	if len(c.Args()) < 1 {
		Logger.Fatalf("Missing <target> argument. See usage with 'assh wrapper %s -h'.", c.Command.Name)
	}

	// prepare variables
	target := c.Args()[0]
	command := c.Args()[1:]
	options := []string{}
	for _, flag := range config.SSHBoolFlags {
		if c.Bool(flag) {
			options = append(options, fmt.Sprintf("-%s", flag))
		}
	}
	for _, flag := range config.SSHStringFlags {
		if val := c.String(flag); val != "" {
			options = append(options, fmt.Sprintf("-%s", flag))
			options = append(options, val)
		}
	}
	args := []string{c.Command.Name}
	args = append(args, options...)
	args = append(args, target)
	args = append(args, command...)
	bin, err := exec.LookPath(c.Command.Name)
	if err != nil {
		Logger.Fatalf("Cannot find %q in $PATH", c.Command.Name)
	}

	Logger.Debugf("Wrapper called with bin=%v target=%v command=%v options=%v, args=%v", bin, target, command, options, args)

	// check if config is up-to-date
	conf, err := config.Open(c.GlobalString("config"))
	if err != nil {
		Logger.Fatalf("Cannot open configuration file: %v", err)
	}

	if err = conf.LoadKnownHosts(); err != nil {
		Logger.Debugf("Failed to load assh known_hosts: %v", err)
	}

	// check if .ssh/config is outdated
	isOutdated, err := conf.IsConfigOutdated(target)
	if err != nil {
		Logger.Error(err)
	}
	if isOutdated {
		Logger.Debugf("The configuration file is outdated, rebuilding it before calling %s", c.Command.Name)
		if err = conf.SaveSSHConfig(); err != nil {
			Logger.Error(err)
		}
	}

	// Execute Binary
	syscall.Exec(bin, args, os.Environ())

	return nil
}