Beispiel #1
0
func localhost() *henchman.Machine {
	tc := make(henchman.TransportConfig)
	local, _ := henchman.NewLocal(&tc)
	localhost := henchman.Machine{}
	localhost.Hostname = "127.0.0.1"
	localhost.Transport = local
	return &localhost
}
Beispiel #2
0
func main() {
	username := flag.String("user", currentUsername().Username, "User to run as")
	usePassword := flag.Bool("password", false, "Use password authentication")
	keyfile := flag.String("private-keyfile", defaultKeyFile(), "Path to the keyfile")
	extraArgs := flag.String("args", "", "Extra arguments for the plan")

	modulesDir, err := validateModulesPath()
	if err != nil {
		log.Fatalf("Couldn't stat modules path '%s'\n", modulesDir)
	}
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [args] <plan>\n\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	planFile := flag.Arg(0)
	if planFile == "" {
		flag.Usage()
		os.Exit(1)
	}
	if *username == "" {
		fmt.Fprintf(os.Stderr, "Missing username")
		os.Exit(1)
	}
	// We support two SSH authentications methods for now
	// password and client key bases. Both are mutually exclusive and password takes
	// higher precedence
	tc := make(henchman.TransportConfig)
	tc["username"] = *username
	if *usePassword {
		var password string
		if password, err = gopass.GetPass("Password:"******"Couldn't get password: "******"password"] = password
	} else {
		tc["keyfile"] = *keyfile
	}

	planBuf, err := ioutil.ReadFile(planFile)
	if err != nil {
		log.Fatalf("Error reading plan - %s\n", planFile)
	}

	var plan *henchman.Plan
	parsedArgs := parseExtraArgs(*extraArgs)
	plan, err = henchman.NewPlanFromYAML(planBuf, &parsedArgs)
	if err != nil {
		log.Fatalf("Couldn't read the plan: %s", err)
		os.Exit(1)
	}

	local := localhost()
	// Execute the same plan concurrently across all the machines.
	// Note the tasks themselves in plan are executed sequentially.
	wg := new(sync.WaitGroup)
	for _, hostname := range plan.Hosts {
		machine := henchman.Machine{}
		machine.Hostname = hostname
		machine.Transport = sshTransport(&tc, hostname)
		wg.Add(1)
		go func(machine *henchman.Machine) {
			defer wg.Done()
			for _, task := range plan.Tasks {
				var status *henchman.TaskStatus
				var err error
				if task.LocalAction {
					log.Printf("Local action detected\n")
					status, err = task.Run(local, plan.Vars)
				} else {
					status, err = task.Run(machine, plan.Vars)
				}
				plan.SaveStatus(&task, status.Status)
				if err != nil {
					log.Printf("Error when executing task: %s\n", err.Error())
				}
				if status.Status == "failure" {
					log.Printf("Task was unsuccessful: %s\n", task.Id)
					break
				}
			}
		}(&machine)
	}
	wg.Wait()
	plan.PrintReport()
}