func removeHostEntry(hostEntries []*HostEntry, name string) []*HostEntry { for i, entry := range hostEntries { if entry.Name == name { if i < len(hostEntries)-1 { return append(hostEntries[:i], hostEntries[i+1:]...) } return hostEntries[:i] } } log.Warn("Did not find a host entry with name %s", name) return hostEntries }
// RemoteSSHCommand invokes the given command on a host and port func RemoteSSHCommand(user string, privateKey string, host string, port string, cmd string, envVars map[string]string) error { if len(privateKey) == 0 { return fmt.Errorf("Could not find PrivateKey for entry %s", host) } log.Info("Connecting to host over SSH on host %s and port %s with user %s with command `%s`", host, port, user, cmd) hostPort := net.JoinHostPort(host, port) sshConfig := &ssh.ClientConfig{ User: user, Auth: []ssh.AuthMethod{ PublicKeyFile(privateKey), }, } if sshConfig == nil { log.Warn("No sshConfig could be created!") } connection, err := ssh.Dial("tcp", hostPort, sshConfig) if err != nil { return fmt.Errorf("Failed to dial: %s", err) } session, err := connection.NewSession() if err != nil { return fmt.Errorf("Failed to create session: %s", err) } defer session.Close() modes := ssh.TerminalModes{ // ssh.ECHO: 0, // disable echoing ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } if err := session.RequestPty("xterm", 80, 40, modes); err != nil { return fmt.Errorf("Request for pseudo terminal failed: %s", err) } stdin, err := session.StdinPipe() if err != nil { return fmt.Errorf("Unable to setup stdin for session: %v", err) } go io.Copy(stdin, os.Stdin) stdout, err := session.StdoutPipe() if err != nil { return fmt.Errorf("Unable to setup stdout for session: %v", err) } go io.Copy(os.Stdout, stdout) stderr, err := session.StderrPipe() if err != nil { return fmt.Errorf("Unable to setup stderr for session: %v", err) } go io.Copy(os.Stderr, stderr) for envName, envValue := range envVars { log.Info("Setting environment value %s = %s", envName, envValue) if err := session.Setenv(envName, envValue); err != nil { return fmt.Errorf("Could not set environment variable %s = %s over SSH. This could be disabled by the sshd configuration. See the `AcceptEnv` setting in your /etc/ssh/sshd_config more info: http://linux.die.net/man/5/sshd_config . Error: %s", envName, envValue, err) } } signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) signaled := false go func() { <-signals log.Info("Shutting down SSH session.") signaled = true session.Close() }() log.Info("Running command %s", cmd) err = session.Run(cmd) if !signaled && err != nil { return fmt.Errorf("Failed to run command: "+cmd+": %v", err) } return nil }
// RemoteWinRmCommand runs the remote command on a windows machine func RemoteWinRmCommand(user string, password string, host string, port string, commandText string, c *client.Client, rc *api.ReplicationController, hostName string) error { portNumber, err := parsePortNumber(port) if err != nil { return err } log.Info("Connecting to windows host over WinRM on host %s and port %d with user %s with command `%s`", host, portNumber, user, commandText) client, err := winrm.NewClient(&winrm.Endpoint{Host: host, Port: portNumber, HTTPS: false, Insecure: false}, user, password) if err != nil { return fmt.Errorf("Could not create WinRM client: %s", err) } isBash := false isBashShellText := os.Getenv(ansible.EnvIsBashShell) if len(isBashShellText) > 0 && strings.ToLower(isBashShellText) == "true" { isBash = true } if rc.ObjectMeta.Annotations != nil && !isBash { oldShellID := rc.ObjectMeta.Annotations[ansible.WinRMShellAnnotationPrefix+hostName] if len(oldShellID) > 0 { // lets close the previously running shell on this machine log.Info("Closing the old WinRM Shell %s", oldShellID) shell := client.NewShell(oldShellID) err = shell.Close() if err != nil { log.Warn("Failed to close shell %s. Error: %s", oldShellID, err) } } } shell, err := client.CreateShell() if err != nil { return fmt.Errorf("Impossible to create WinRM shell: %s", err) } defer shell.Close() shellID := shell.ShellId log.Info("Created WinRM Shell %s", shellID) if rc != nil && c != nil && !isBash { rc.ObjectMeta.Annotations[ansible.WinRMShellAnnotationPrefix+hostName] = shellID _, err = c.ReplicationControllers(rc.ObjectMeta.Namespace).UpdateStatus(rc) if err != nil { return err } } var cmd *winrm.Command cmd, err = shell.Execute(commandText) if err != nil { return fmt.Errorf("Impossible to create Command %s\n", err) } go io.Copy(cmd.Stdin, os.Stdin) go io.Copy(os.Stdout, cmd.Stdout) go io.Copy(os.Stderr, cmd.Stderr) cmd.Wait() exitCode := cmd.ExitCode() if exitCode > 0 { return fmt.Errorf("Failed to run command '%s' got exit code %d", commandText, exitCode) } // TODO // return cmd.Error() return nil }