Пример #1
0
func routes(reg *cookoo.Registry) {
	reg.AddRoute(cookoo.Route{
		Name: "boot",
		Help: "Boot Etcd",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "setenv",
				Fn:   iam,
			},
			cookoo.Cmd{
				Name: "discoveryToken",
				Fn:   discovery.GetToken,
			},
			// This synchronizes the local copy of env vars with the actual
			// environment. So all of these vars are available in cxt: or in
			// os.Getenv(). They will also be available to the etcd process
			// we spawn.
			cookoo.Cmd{
				Name: "vars",
				Fn:   env.Get,
				Using: []cookoo.Param{
					{Name: "DEIS_ETCD_DISCOVERY_SERVICE_HOST"},
					{Name: "DEIS_ETCD_DISCOVERY_SERVICE_PORT"},
					{Name: "DEIS_ETCD_1_SERVICE_HOST"},
					{Name: "DEIS_ETCD_1_SERVICE_PORT_CLIENT"},
					{Name: "DEIS_ETCD_CLUSTER_SIZE", DefaultValue: "3"},
					{Name: "DEIS_ETCD_DISCOVERY_TOKEN", From: "cxt:discoveryToken"},
					{Name: "HOSTNAME"},

					// Peer URLs are for traffic between etcd nodes.
					// These point to internal IP addresses, not service addresses.
					{Name: "ETCD_LISTEN_PEER_URLS", DefaultValue: "http://$MY_IP:$MY_PORT_PEER"},
					{Name: "ETCD_INITIAL_ADVERTISE_PEER_URLS", DefaultValue: "http://$MY_IP:$MY_PORT_PEER"},

					{
						Name:         "ETCD_LISTEN_CLIENT_URLS",
						DefaultValue: "http://$MY_IP:$MY_PORT_CLIENT,http://127.0.0.1:$MY_PORT_CLIENT",
					},
					{Name: "ETCD_ADVERTISE_CLIENT_URLS", DefaultValue: "http://$MY_IP:$MY_PORT_CLIENT"},

					// {Name: "ETCD_WAL_DIR", DefaultValue: "/var/"},
					// {Name: "ETCD_MAX_WALS", DefaultValue: "5"},
				},
			},

			// We need to connect to the discovery service to find out whether
			// we're part of a new cluster, or part of an existing cluster.
			cookoo.Cmd{
				Name: "discoveryClient",
				Fn:   etcd.CreateClient,
				Using: []cookoo.Param{
					{
						Name:         "url",
						DefaultValue: "http://$DEIS_ETCD_DISCOVERY_SERVICE_HOST:$DEIS_ETCD_DISCOVERY_SERVICE_PORT",
					},
				},
			},
			cookoo.Cmd{
				Name: "clusterClient",
				Fn:   etcd.CreateClient,
				Using: []cookoo.Param{
					{
						Name:         "url",
						DefaultValue: "http://$DEIS_ETCD_1_SERVICE_HOST:$DEIS_ETCD_1_SERVICE_PORT_CLIENT",
					},
				},
			},

			// If there is an existing cluster, set join mode to "existing",
			// Otherwise this gets set to "new". Note that we check the
			// 'status' directory on the discovery service. If the discovery
			// service is down, we will bail out, which will force a pod
			// restart.
			cookoo.Cmd{
				Name: "joinMode",
				Fn:   setJoinMode,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:discoveryClient"},
					{Name: "path", DefaultValue: "/deis/status/$DEIS_ETCD_DISCOVERY_TOKEN"},
					{Name: "desiredLen", From: "cxt:DEIS_ETCD_CLUSTER_SIZE"},
				},
			},
			// If joinMode is "new", we reroute to the route that creates new
			// clusters. Otherwise, we keep going on this chain, assuming
			// we're working with an existing cluster.
			cookoo.Cmd{
				Name: "rerouteIfNew",
				Fn: func(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
					if m := p.Get("joinMode", "").(string); m == "new" {
						return nil, cookoo.NewReroute("@newCluster")
					} else {
						log.Infof(c, "Join mode is %s", m)
					}
					return nil, nil
				},
				Using: []cookoo.Param{
					{Name: "joinMode", From: "cxt:joinMode"},
				},
			},

			// If we didn't get rerouted by the last command, we're in an
			// existing cluster, and we need to do some cleanup. First thing is
			// to remove any previous copies of this pod.
			cookoo.Cmd{
				Name: "removeMember",
				Fn:   etcd.RemoveMemberByName,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:clusterClient"},
					{Name: "name", From: "cxt:HOSTNAME"},
				},
			},

			// If any other etcd cluster members are gone (pod does not exist)
			// then we need to remove them from the cluster or else they will
			// remain voting members in the master election, and can eventually
			// deadlock the cluster.
			cookoo.Cmd{
				Name: "removeStale",
				Fn:   etcd.RemoveStaleMembers,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:clusterClient"},
					{Name: "namespace", From: "cxt:MY_NAMESPACE", DefaultValue: "default"},
					{Name: "label", DefaultValue: "name=deis-etcd-1"},
				},
			},

			// Now add self to cluster.
			cookoo.Cmd{
				Name: "addMember",
				Fn:   etcd.AddMember,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:clusterClient"},
					{Name: "name", From: "cxt:HOSTNAME"},
					{Name: "url", From: "cxt:ETCD_INITIAL_ADVERTISE_PEER_URLS"},
				},
			},

			// Find out who is in the cluster.
			cookoo.Cmd{
				Name: "initialCluster",
				Fn:   etcd.GetInitialCluster,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:clusterClient"},
				},
			},

			// Start etcd. Note that we use environment variables to pass
			// info into etcd, which is why there is so much env munging
			// in this startup script.
			cookoo.Cmd{
				Name: "startEtcd",
				Fn:   startEtcd,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:discoveryClient"},
					{Name: "discover", From: "cxt:discoveryUrl"},
				},
			},
		},
	})

	// This route gets called if boot gets part way through and discovers
	// that this is a new cluster. This short-circuits around the logic
	// that tries to detect a cluster and manage membership, and skips straight
	// to discovery via etcd-discovery.
	reg.AddRoute(cookoo.Route{
		Name: "@newCluster",
		Help: "Start as part of a new cluster",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "vars2",
				Fn:   env.Get,
				Using: []cookoo.Param{
					{
						Name:         "ETCD_DISCOVERY",
						DefaultValue: "http://$DEIS_ETCD_DISCOVERY_SERVICE_HOST:$DEIS_ETCD_DISCOVERY_SERVICE_PORT/v2/keys/deis/discovery/$DEIS_ETCD_DISCOVERY_TOKEN",
					},
				},
			},
			cookoo.Cmd{
				Name: "startEtcd",
				Fn:   startEtcd,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:discoveryClient"},
					{Name: "discover", From: "cxt:discoveryUrl"},
				},
			},
		},
	})
}
Пример #2
0
// routes builds the Cookoo registry.
//
// Esssentially this is a list of all of the things that Builder can do, broken
// down into a step-by-step list.
func routes(reg *cookoo.Registry) {

	// The "boot" route starts up the builder as a daemon process. Along the
	// way, it starts and configures multiple services, including sshd.
	reg.AddRoute(cookoo.Route{
		Name: "boot",
		Help: "Boot the builder",
		Does: []cookoo.Task{

			// SSHD: Create and configure host keys.
			cookoo.Cmd{
				Name: "installSshHostKeys",
				Fn:   sshd.GenSSHKeys,
			},
			cookoo.Cmd{
				Name: sshd.HostKeys,
				Fn:   sshd.ParseHostKeys,
			},
			cookoo.Cmd{
				Name: sshd.ServerConfig,
				Fn:   sshd.Configure,
			},

			// If there's an EXTERNAL_PORT, we publish info to etcd.
			cookoo.Cmd{
				Name: "externalport",
				Fn:   env.Get,
				Using: []cookoo.Param{
					{Name: "EXTERNAL_PORT", DefaultValue: ""},
				},
			},

			// DAEMON: Finally, we wait around for a signal, and then cleanup.
			cookoo.Cmd{
				Name: "listen",
				Fn:   KillOnExit,
				Using: []cookoo.Param{
					{Name: "sshd", From: "cxt:sshdstart"},
				},
			},
		},
	})

	// This provides a very basic SSH ping.
	// Called by the sshd.Server
	reg.AddRoute(cookoo.Route{
		Name: "sshPing",
		Help: "Handles an ssh exec ping.",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "ping",
				Fn:   sshd.Ping,
				Using: []cookoo.Param{
					{Name: "request", From: "cxt:request"},
					{Name: "channel", From: "cxt:channel"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "pubkeyAuth",
		Does: []cookoo.Task{
			// Auth against the keys
			cookoo.Cmd{
				Name: "authN",
				Fn:   sshd.AuthKey,
				Using: []cookoo.Param{
					{Name: "metadata", From: "cxt:metadata"},
					{Name: "key", From: "cxt:key"},
					{Name: "repoName", From: "cxt:repository"},
				},
			},
		},
	})

	// This proxies a client session into a git receive.
	//
	// Called by the sshd.Server
	reg.AddRoute(cookoo.Route{
		Name: "sshGitReceive",
		Help: "Handle a git receive over an SSH connection.",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "receive",
				Fn:   git.Receive,
				Using: []cookoo.Param{
					{Name: "request", From: "cxt:request"},
					{Name: "channel", From: "cxt:channel"},
					{Name: "operation", From: "cxt:operation"},
					{Name: "repoName", From: "cxt:repository"},
					{Name: "permissions", From: "cxt:authN"},
					{Name: "userinfo", From: "cxt:userinfo"},
				},
			},
		},
	})
}
Пример #3
0
// routes builds the Cookoo registry.
//
// Esssentially this is a list of all of the things that Builder can do, broken
// down into a step-by-step list.
func routes(reg *cookoo.Registry) {

	// The "boot" route starts up the builder as a daemon process. Along the
	// way, it starts and configures multiple services, including etcd, confd,
	// and sshd.
	reg.AddRoute(cookoo.Route{
		Name: "boot",
		Help: "Boot the builder",
		Does: []cookoo.Task{

			// ENV: Make sure the environment is correct.
			cookoo.Cmd{
				Name: "vars",
				Fn:   env.Get,
				Using: []cookoo.Param{
					{Name: "HOST", DefaultValue: "127.0.0.1"},
					{Name: "ETCD_PORT", DefaultValue: "4001"},
					{Name: "ETCD_PATH", DefaultValue: "/deis/builder"},
					{Name: "ETCD_TTL", DefaultValue: "20"},
				},
			},
			cookoo.Cmd{ // This depends on others being processed first.
				Name: "vars2",
				Fn:   env.Get,
				Using: []cookoo.Param{
					{Name: "ETCD", DefaultValue: "$HOST:$ETCD_PORT"},
				},
			},

			// DOCKER: start up Docker and make sure it's running.
			// Then let it download the images while we keep going.
			cookoo.Cmd{
				Name: "docker",
				Fn:   docker.CreateClient,
				Using: []cookoo.Param{
					{Name: "url", DefaultValue: "unix:///var/run/docker.sock"},
				},
			},
			cookoo.Cmd{
				Name: "dockerclean",
				Fn:   docker.Cleanup,
			},
			cookoo.Cmd{
				Name: "dockerstart",
				Fn:   docker.Start,
			},
			cookoo.Cmd{
				Name: "waitfordocker",
				Fn:   docker.WaitForStart,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:docker"},
				},
			},

			cookoo.Cmd{
				Name: "buildImages",
				Fn:   docker.ParallelBuild,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:docker"},
					{
						Name: "images",
						DefaultValue: []docker.BuildImg{
							{Path: "/usr/local/src/slugbuilder/", Tag: "deis/slugbuilder"},
							{Path: "/usr/local/src/slugrunner/", Tag: "deis/slugrunner"},
						},
					},
				},
			},

			// ETCD: Make sure Etcd is running, and do the initial population.
			cookoo.Cmd{
				Name:  "client",
				Fn:    etcd.CreateClient,
				Using: []cookoo.Param{{Name: "url", DefaultValue: "http://127.0.0.1:4001", From: "cxt:ETCD"}},
			},
			cookoo.Cmd{
				Name: "etcdup",
				Fn:   etcd.IsRunning,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:client"},
					{Name: "count", DefaultValue: 20},
				},
			},
			cookoo.Cmd{
				Name: "-",
				Fn:   Sleep,
				Using: []cookoo.Param{
					{Name: "duration", DefaultValue: 21 * time.Second},
					{Name: "message", DefaultValue: "Sleeping while etcd expires keys."},
				},
			},
			cookoo.Cmd{
				Name: "newdir",
				Fn:   fmt.Sprintf,
				Using: []cookoo.Param{
					{Name: "format", DefaultValue: "%s/users"},
					{Name: "0", From: "cxt:ETCD_PATH"},
				},
			},
			cookoo.Cmd{
				Name: "mkdir",
				Fn:   etcd.MakeDir,
				Using: []cookoo.Param{
					{Name: "path", From: "cxt:newdir"},
					{Name: "client", From: "cxt:client"},
				},
			},

			// SSHD: Create and configure host keys.
			cookoo.Cmd{
				Name: "installSshHostKeys",
				Fn:   etcd.StoreHostKeys,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:client"},
					{Name: "basepath", From: "cxt:ETCD_PATH"},
				},
			},
			cookoo.Cmd{
				Name: sshd.HostKeys,
				Fn:   sshd.ParseHostKeys,
			},
			cookoo.Cmd{
				Name: sshd.ServerConfig,
				Fn:   sshd.Configure,
			},

			// CONFD: Build out the templates, then start the Confd server.
			cookoo.Cmd{
				Name:  "once",
				Fn:    confd.RunOnce,
				Using: []cookoo.Param{{Name: "node", From: "cxt:ETCD"}},
			},
			cookoo.Cmd{
				Name:  "confd",
				Fn:    confd.Run,
				Using: []cookoo.Param{{Name: "node", From: "cxt:ETCD"}},
			},

			// Now we wait for Docker to finish downloading.
			cookoo.Cmd{
				Name: "dowloadImages",
				Fn:   docker.Wait,
				Using: []cookoo.Param{
					{Name: "wg", From: "cxt:buildImages"},
					{Name: "msg", DefaultValue: "Images downloaded"},
					{Name: "waiting", DefaultValue: "Downloading Docker images. This may take a long time. https://xkcd.com/303/"},
					{Name: "failures", From: "cxt:ParallelBuild.failN"},
				},
			},
			cookoo.Cmd{
				Name: "pushImages",
				Fn:   docker.Push,
				Using: []cookoo.Param{
					{Name: "tag", DefaultValue: "deis/slugrunner:latest"},
					{Name: "client", From: "cxt:client"},
				},
			},

			// ETDCD: Now watch for events on etcd, and trigger a git check-repos for
			// each. For the most part, this runs in the background.
			cookoo.Cmd{
				Name: "Cleanup",
				Fn:   etcd.Watch,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:client"},
				},
			},
			// If there's an EXTERNAL_PORT, we publish info to etcd.
			cookoo.Cmd{
				Name: "externalport",
				Fn:   env.Get,
				Using: []cookoo.Param{
					{Name: "EXTERNAL_PORT", DefaultValue: ""},
				},
			},
			cookoo.Cmd{
				Name: "etcdupdate",
				Fn:   etcd.UpdateHostPort,
				Using: []cookoo.Param{
					{Name: "base", From: "cxt:ETCD_PATH"},
					{Name: "host", From: "cxt:HOST"},
					{Name: "port", From: "cxt:EXTERNAL_PORT"},
					{Name: "client", From: "cxt:client"},
					{Name: "sshdPid", From: "cxt:sshd"},
				},
			},

			// DAEMON: Finally, we wait around for a signal, and then cleanup.
			cookoo.Cmd{
				Name: "listen",
				Fn:   KillOnExit,
				Using: []cookoo.Param{
					{Name: "docker", From: "cxt:dockerstart"},
					{Name: "sshd", From: "cxt:sshdstart"},
				},
			},
		},
	})

	// This route is called during a user authentication for SSH.
	// The rough pattern is that we parse the local authorized keys file, and
	// then validate that the supplied user key matches an authorized key.
	//
	// This grants access to running git-receive, but does not grant access
	// to writing to the repo. That's handled by the sshReceive.
	reg.AddRoute(cookoo.Route{
		Name: "pubkeyAuth",
		Does: []cookoo.Task{
			// Parse the authorized keys file.
			// We do this every time because confd is constantly regenerating
			// the auth keys file.
			cookoo.Cmd{
				Name: "authorizedKeys",
				Fn:   sshd.ParseAuthorizedKeys,
				Using: []cookoo.Param{
					{Name: "path", DefaultValue: "/home/git/.ssh/authorized_keys"},
				},
			},

			// Auth against the keys
			cookoo.Cmd{
				Name: "authN",
				Fn:   sshd.AuthKey,
				Using: []cookoo.Param{
					{Name: "metadata", From: "cxt:metadata"},
					{Name: "key", From: "cxt:key"},
					{Name: "authorizedKeys", From: "cxt:authorizedKeys"},
				},
			},
		},
	})

	// This provides a very basic SSH ping.
	// Called by the sshd.Server
	reg.AddRoute(cookoo.Route{
		Name: "sshPing",
		Help: "Handles an ssh exec ping.",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "ping",
				Fn:   sshd.Ping,
				Using: []cookoo.Param{
					{Name: "request", From: "cxt:request"},
					{Name: "channel", From: "cxt:channel"},
				},
			},
		},
	})

	// This proxies a client session into a git receive.
	//
	// Called by the sshd.Server
	reg.AddRoute(cookoo.Route{
		Name: "sshGitReceive",
		Help: "Handle a git receive over an SSH connection.",
		Does: []cookoo.Task{
			// The Git receive handler needs the username. So we provide
			// it by looking up the name based on the key. When the
			// controller no longer requires username for SSH auth, we can
			// ditch this.
			cookoo.Cmd{
				Name: "fingerprint",
				Fn:   sshd.FingerprintKey,
				Using: []cookoo.Param{
					{Name: "key", From: "cxt:key"},
				},
			},
			cookoo.Cmd{
				Name: "username",
				Fn:   etcd.FindSSHUser,
				Using: []cookoo.Param{
					{Name: "client", From: "cxt:client"},
					{Name: "fingerprint", From: "cxt:fingerprint"},
				},
			},
			cookoo.Cmd{
				Name: "receive",
				Fn:   git.Receive,
				Using: []cookoo.Param{
					{Name: "request", From: "cxt:request"},
					{Name: "channel", From: "cxt:channel"},
					{Name: "operation", From: "cxt:operation"},
					{Name: "repoName", From: "cxt:repository"},
					{Name: "fingerprint", From: "cxt:fingerprint"},
					{Name: "permissions", From: "cxt:authN"},
					{Name: "user", From: "cxt:username"},
				},
			},
		},
	})
}
Пример #4
0
func routes(reg *cookoo.Registry) {
	reg.AddRoute(cookoo.Route{
		Name: "@json",
		Help: "Parse incoming JSON out of HTTP body",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "data",
				Fn:   readBody,
			},
			cookoo.Cmd{
				Name: "json",
				Fn:   fromJSON,
				Using: []cookoo.Param{
					{Name: "data", From: "cxt:data"},
					{Name: "dest", From: "cxt:prototype"},
				},
			},
		},
	})
	reg.AddRoute(cookoo.Route{
		Name: "@out",
		Help: "Serialize JSON and write it to http.Response",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "content",
				Fn:   toJSON,
				Using: []cookoo.Param{
					{Name: "o", From: "cxt:res"},
				},
			},
			cookoo.Cmd{
				Name: "flush",
				Fn:   web.Flush,
				Using: []cookoo.Param{
					{Name: "contentType", DefaultValue: "application/json"},
					{Name: "content", From: "cxt:content"},
				},
			},
		},
	})
	reg.AddRoute(cookoo.Route{
		Name: "GET /package",
		Help: "List packages",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "res",
				Fn:   backend.Packages,
			},
			cookoo.Include{"@out"},
		},
	})
	reg.AddRoute(cookoo.Route{
		Name: "GET /package/*",
		Help: "Get an individual package",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "res",
				Fn:   backend.Package,
				Using: []cookoo.Param{
					{Name: "name", From: "path:1"},
				},
			},
			cookoo.Include{"@out"},
		},
	})
	reg.AddRoute(cookoo.Route{
		Name: "POST /package",
		Help: "Create a package",
		Does: []cookoo.Task{
			cookoo.Cmd{
				Name: "-",
				Fn:   cookoo.AddToContext,
				Using: []cookoo.Param{
					{Name: "prototype", DefaultValue: &model.Package{}},
				},
			},
			cookoo.Include{"@json"},
			cookoo.Cmd{
				Name: "res",
				Fn:   backend.AddPackage,
				Using: []cookoo.Param{
					{Name: "pkg", From: "cxt:json"},
				},
			},
			cookoo.Include{"@out"},
		},
	})
	reg.AddRoute(cookoo.Route{
		Name: "POST /package/*",
		Help: "Create a package release",
		Does: []cookoo.Task{
			//cookoo.Cmd{
			//Name: "pkg",
			//Fn:   backend.Package,
			//Using: []cookoo.Param{
			//{Name: "name", From: "path:1"},
			//},
			//},
			cookoo.Cmd{
				Name: "-",
				Fn:   cookoo.AddToContext,
				Using: []cookoo.Param{
					{Name: "prototype", DefaultValue: &model.Package{}},
				},
			},
			cookoo.Include{"@json"},
			cookoo.Cmd{
				Name: "res",
				Fn:   backend.AddRelease,
				Using: []cookoo.Param{
					{Name: "pkg", From: "cxt:json"},
				},
			},
			cookoo.Include{"@out"},
		},
	})
}
Пример #5
0
func buildRegistry(reg *cookoo.Registry, router *cookoo.Router, cxt cookoo.Context) {

	reg.AddRoute(cookoo.Route{
		Name: "PUT /v1/t/*",
		Help: "Create a new topic.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "topic",
				Fn:   pubsub.CreateTopic,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "POST /v1/t/*",
		Help: "Publish a message to a channel.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "postBody",
				Fn:   httputil.BufferPost,
			},
			cookoo.Cmd{
				Name: "publish",
				Fn:   pubsub.Publish,
				Using: []cookoo.Param{
					{Name: "message", From: "cxt:postBody"},
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "GET /v1/t/*",
		Help: "Subscribe to a topic.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "history",
				Fn:   pubsub.ReplayHistory,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
			cookoo.Cmd{
				Name: "subscribe",
				Fn:   pubsub.Subscribe,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "HEAD /v1/t/*",
		Help: "Check whether a topic exists.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "has",
				Fn:   pubsub.TopicExists,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "DELETE /v1/t/*",
		Help: "Delete a topic and close all subscriptions to the topic.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "delete",
				Fn:   pubsub.DeleteTopic,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})
}
Пример #6
0
func buildRegistry(reg *cookoo.Registry, router *cookoo.Router, cxt cookoo.Context) {
	reg.AddRoute(cookoo.Route{
		Name: "GET /ping",
		Help: "Ping the server, get a pong reponse.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Fn: func(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
					w := c.Get("http.ResponseWriter", nil).(http.ResponseWriter)
					w.Write([]byte("pong"))
					return nil, nil
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "GET /v1/time",
		Help: "Print the current server time as a UNIX seconds-since-epoch",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "timestamp",
				Fn:   httputil.Timestamp,
			},
			cookoo.Cmd{
				Name: "_",
				Fn:   web.Flush,
				Using: []cookoo.Param{
					{Name: "content", From: "cxt:timestamp"},
					{Name: "contentType", DefaultValue: "text/plain"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "GET /",
		Help: "API Reference",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "help",
				Fn:   cfmt.Template,
				Using: []cookoo.Param{
					{Name: "template", DefaultValue: helpTemplate},
					{Name: "Routes", From: "cxt:routes"},
				},
			},
			cookoo.Cmd{
				Name: "_",
				Fn:   web.Flush,
				Using: []cookoo.Param{
					{Name: "content", From: "cxt:help"},
					{Name: "contentType", DefaultValue: "text/html"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "PUT /v1/t/*",
		Help: "Create a new topic.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "topic",
				Fn:   pubsub.CreateTopic,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "POST /v1/t/*",
		Help: "Publish a message to a channel.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "postBody",
				Fn:   httputil.BufferPost,
			},
			cookoo.Cmd{
				Name: "publish",
				Fn:   pubsub.Publish,
				Using: []cookoo.Param{
					{Name: "message", From: "cxt:postBody"},
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "GET /v1/t/*",
		Help: "Subscribe to a channel.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "history",
				Fn:   pubsub.ReplayHistory,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
			cookoo.Cmd{
				Name: "subscribe",
				Fn:   pubsub.Subscribe,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "HEAD /v1/t/*",
		Help: "Check whether a topic exists.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "has",
				Fn:   pubsub.TopicExists,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})

	reg.AddRoute(cookoo.Route{
		Name: "DELETE /v1/t/*",
		Help: "Delete a topic and close all subscriptions to the topic.",
		Does: cookoo.Tasks{
			cookoo.Cmd{
				Name: "delete",
				Fn:   pubsub.DeleteTopic,
				Using: []cookoo.Param{
					{Name: "topic", From: "path:2"},
				},
			},
		},
	})
}