// iam injects info into the environment about a host's self. // // Sets the following environment variables. (Values represent the data format. // Instances will get its own values.) // // MY_NODEIP=10.245.1.3 // MY_SERVICE_IP=10.22.1.4 // MY_PORT_PEER=2380 // MY_PORT_CLIENT=2379 // MY_NAMESPACE=default // MY_SELFLINK=/api/v1/namespaces/default/pods/deis-etcd-1-336jp // MY_UID=62a3b54a-6956-11e5-b8ab-0800279dd272 // MY_APISERVER=https://10.247.0.1:443 // MY_NAME=deis-etcd-1-336jp // MY_IP=10.246.44.7 // MY_LABEL_NAME=deis-etcd-1 # One entry per label in the JSON // MY_ANNOTATION_NAME=deis-etcd-1 # One entry per annitation in the JSON // MY_PORT_CLIENT=4100 // MY_PORT_PEER=2380 func iam(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { me, err := aboutme.FromEnv() if err != nil { log.Errf(c, "Failed aboutme.FromEnv: %s", err) } else { if strings.TrimSpace(me.IP) == "" { log.Warn(c, "No IP found by API query.") ip, err := aboutme.MyIP() if err != nil || ip == "" { // Force pod death. log.Errf(c, "Failed to get an IP address: %s", err) os.Exit(5) } } me.ShuntEnv() os.Setenv("ETCD_NAME", me.Name) c.Put("ETCD_NAME", me.Name) } passEnv("MY_PORT_CLIENT", "$DEIS_ETCD_1_SERVICE_PORT_CLIENT") passEnv("MY_PORT_PEER", "$DEIS_ETCD_1_SERVICE_PORT_PEER") return nil, nil }
// iam injects info into the environment about a host's self. // // Sets the following environment variables. (Values represent the data format. // Instances will get its own values.) // // MY_NODEIP=10.245.1.3 // MY_SERVICE_IP=10.22.1.4 // MY_PORT_PEER=2380 // MY_PORT_CLIENT=2379 // MY_NAMESPACE=default // MY_SELFLINK=/api/v1/namespaces/default/pods/deis-etcd-1-336jp // MY_UID=62a3b54a-6956-11e5-b8ab-0800279dd272 // MY_APISERVER=https://10.247.0.1:443 // MY_NAME=deis-etcd-1-336jp // MY_IP=10.246.44.7 // MY_LABEL_NAME=deis-etcd-1 # One entry per label in the JSON // MY_ANNOTATION_NAME=deis-etcd-1 # One entry per annitation in the JSON // MY_PORT_CLIENT=4100 // MY_PORT_PEER=2380 func iam(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { me, err := aboutme.FromEnv() if err != nil { log.Errf(c, "Failed aboutme.FromEnv: %s", err) log.Warn(c, "Attempting to recover.") } // This will try to recover whenever IP is not set. Only some fields // can be recovered. But all we really need is IP and Name. if strings.TrimSpace(me.IP) == "" { log.Warn(c, "No IP found by API query.") ip, err := aboutme.MyIP() if err != nil || ip == "" { // Force pod death. log.Errf(c, "Failed to get an IP address: %s", err) os.Exit(5) } me.IP = ip } if strings.TrimSpace(me.Name) == "" { // Try to set name from DAPI. me.Name = os.Getenv("POD_NAME") log.Warnf(c, "Setting name to %q", me.Name) } if strings.TrimSpace(me.Namespace) == "" { // Try to set namespace from DAPI. me.Namespace = os.Getenv("POD_NAMESPACE") log.Warnf(c, "Setting name to %q", me.Namespace) } me.ShuntEnv() os.Setenv("ETCD_NAME", me.Name) c.Put("ETCD_NAME", me.Name) passEnv("MY_PORT_CLIENT", "$DEIS_ETCD_1_SERVICE_PORT_CLIENT") passEnv("MY_PORT_PEER", "$DEIS_ETCD_1_SERVICE_PORT_PEER") return nil, nil }
// answer handles answering requests and channel requests // // Currently, an exec must be either "ping", "git-receive-pack" or // "git-upload-pack". Anything else will result in a failure response. Right // now, we leave the channel open on failure because it is unclear what the // correct behavior for a failed exec is. // // Support for setting environment variables via `env` has been disabled. func (s *server) answer(channel ssh.Channel, requests <-chan *ssh.Request, sshConn string) error { defer channel.Close() // Answer all the requests on this connection. for req := range requests { ok := false // I think that ideally what we want to do here is pass this on to // the Cookoo router and let it handle each Type on its own. switch req.Type { case "env": o := &EnvVar{} ssh.Unmarshal(req.Payload, o) fmt.Printf("Key='%s', Value='%s'\n", o.Name, o.Value) req.Reply(true, nil) case "exec": clean := cleanExec(req.Payload) parts := strings.SplitN(clean, " ", 2) router := s.c.Get("cookoo.Router", nil).(*cookoo.Router) // TODO: Should we unset the context value 'cookoo.Router'? // We need a shallow copy of the context to avoid race conditions. cxt := s.c.Copy() cxt.Put("SSH_CONNECTION", sshConn) // Only allow commands that we know about. switch parts[0] { case "ping": cxt.Put("channel", channel) cxt.Put("request", req) sshPing := cxt.Get("route.sshd.sshPing", "sshPing").(string) err := router.HandleRequest(sshPing, cxt, true) if err != nil { log.Warnf(s.c, "Error pinging: %s", err) } return err case "git-receive-pack", "git-upload-pack": if len(parts) < 2 { log.Warn(s.c, "Expected two-part command.\n") req.Reply(ok, nil) break } req.Reply(true, nil) // We processed. Yay. cxt.Put("channel", channel) cxt.Put("request", req) cxt.Put("operation", parts[0]) cxt.Put("repository", parts[1]) sshGitReceive := cxt.Get("route.sshd.sshGitReceive", "sshGitReceive").(string) err := router.HandleRequest(sshGitReceive, cxt, true) var xs uint32 if err != nil { log.Errf(s.c, "Failed git receive: %v", err) xs = 1 } sendExitStatus(xs, channel) return nil default: log.Warnf(s.c, "Illegal command is '%s'\n", clean) req.Reply(false, nil) return nil } if err := sendExitStatus(0, channel); err != nil { log.Errf(s.c, "Failed to write exit status: %s", err) } return nil default: // We simply ignore all of the other cases and leave the // channel open to take additional requests. log.Infof(s.c, "Received request of type %s\n", req.Type) req.Reply(false, nil) } } return nil }