//Request is the base level method upon which all protocolink requests are handled //for the sake of being a valid protcollink it implements the method signature // (string,io.Reader) but for flexibilty string func (h *SSHProtocolLink) Request(path string, body io.Reader) flux.ActionStackInterface { req := flux.NewAction() err := flux.NewAction() act := req.Chain(2) st := flux.NewActionStackBy(act, err) if h.conn == nil { st.Complete(ErrorNoConnection) return st } act.OverrideBefore(1, func(b interface{}, next flux.ActionInterface) { se, ok := b.(*SSHClientSession) if !ok { return } se.Close() next.Fullfill(b) }) session, erro := h.conn.NewSession() if erro != nil { st.Complete(erro) } else { st.Complete(NewSSHClientSession(session, body)) } return st }
//FS creates a ftp client on the remote connection and allows file base op func (h *SSHProtocolLink) FS() flux.ActionStackInterface { req := flux.NewAction() eo := flux.NewAction() st := flux.NewActionStackBy(req, eo) ch := req.Chain(2) ch.OverrideBefore(1, func(b interface{}, next flux.ActionInterface) { ce, ok := b.(*sftp.Client) if !ok { return } ce.Close() }) cl, err := sftp.NewClient(h.conn) if err != nil { st.Complete(err) } else { st.Complete(cl) } return st }
//NewPayloadRack returns a new instance of the payloadrack func NewPayloadRack(timeout int, fx Failure) *PayloadRack { p := &PayloadRack{ make(chan interface{}), time.Duration(timeout) * time.Millisecond, flux.NewAction(), flux.NewAction(), new(sync.Once), } if fx != nil { fx(p.Failed()) } return p }
//RSASSHProtocolLink returns a new sshProtocollink to communicate with ssh servers //you pass func RSASSHProtocolLink(service, addr string, port int, user string, pkeyFile string) *SSHProtocolLink { pbytes, err := ioutil.ReadFile(pkeyFile) if err != nil { panic(fmt.Sprintf("ReadError %v \nFailed to load private key file: %s", err, pkeyFile)) } private, err := ssh.ParsePrivateKey(pbytes) if err != nil { log.Println(fmt.Sprintf("ParseError:(%s):", pkeyFile), err) panic("Failed to parse private key") } auth := []ssh.AuthMethod{ ssh.PublicKeys(private), } config := &ssh.ClientConfig{ User: user, Auth: auth, } desc := NewDescriptor("ssh", service, addr, port, "0", "ssh") nsh := &SSHProtocolLink{ NewProtocolLink(desc), config, nil, flux.NewAction(), } return nsh }
//PasswordSSHProtocolLink returns a new sshProtocollink to communicate with ssh servers //you pass func PasswordSSHProtocolLink(service, addr string, port int, user string, password string) *SSHProtocolLink { auth := []ssh.AuthMethod{ ssh.Password(password), } config := &ssh.ClientConfig{ User: user, Auth: auth, } desc := NewDescriptor("ssh", service, addr, port, "0", "ssh") //should we store the password? // desc.Misc["password"]=password nsh := &SSHProtocolLink{ NewProtocolLink(desc), config, nil, flux.NewAction(), } return nsh }
//Request is the base level method upon which all protocolink requests are handled func (h *HTTPProtocolLink) Request(path string, body io.Reader) flux.ActionStackInterface { log.Printf("Initiating HTTPLink: New HTTP Request for %s", path) addr := fmt.Sprintf("%s:%d/%s", h.Descriptor().Address, h.Descriptor().Port, h.Descriptor().Service) addr = ExcessSlash.ReplaceAllString(addr, "/") addr = EndSlash.ReplaceAllString(addr, "") path = ExcessSlash.ReplaceAllString(path, "/") path = EndSlash.ReplaceAllString(path, "") resuri := fmt.Sprintf("%s/%s", addr, path) resuri = ExcessSlash.ReplaceAllString(resuri, "/") url := fmt.Sprintf("%s://%s", h.Descriptor().Scheme, resuri) log.Printf("HTTPLink: New HTTP Request for %s", url) red := flux.NewAction() erd := flux.NewAction() act := red.Chain(3) //we do these so we can override what happens after the user adds all they //want on the request act.OverrideBefore(1, func(b interface{}, next flux.ActionInterface) { rq, ok := b.(*http.Request) if !ok { // next.Fullfill(b interface) return } rq.Header.Set("X-Service-Request", h.Descriptor().Service) log.Printf("HTTPLink: Request Header Set,Initiaing RequestClient Sending...") res, err := h.client.Do(rq) if err == nil { log.Printf("HTTPLink: Recieved Request (%s) Response Status: %d", rq.URL, res.StatusCode) } else { log.Printf("HTTPLink: Recieved Request (%s) Response Error: %v", rq.URL, err) } pck := NewHTTPPacket(res, rq, err) next.Fullfill(pck) }) cl := flux.NewActionStackBy(act, erd) var req *http.Request var err error if body == nil { req, err = http.NewRequest("GET", url, body) if err != nil { cl.Complete(err) return cl } } else { req, err = http.NewRequest("POST", url, body) if err != nil { cl.Complete(err) return cl } } log.Printf("HTTPLink: Initiating Http Request Method: (%+s), URI: (%+s)", req.Method, req.URL) cl.Complete(req) return cl }