func subcommandHelp(reg *cookoo.Registry) string { names := reg.RouteNames() helptext := make([]string, 0, len(names)) for _, name := range names { if strings.HasPrefix(name, "@") { continue } rs, _ := reg.RouteSpec(name) help := fmt.Sprintf("\t%s: %s", name, cookoo.RouteDetails(rs).Description()) helptext = append(helptext, help) } return strings.Join(helptext, "\n") }
func routes(reg *cookoo.Registry, cxt cookoo.Context) { reg.Route("@startup", "Parse args and send to the right subcommand."). // TODO: Add setup for debug in addition to quiet. Does(cmd.BeQuiet, "quiet"). Using("quiet").From("cxt:q"). Does(cmd.VersionGuard, "v") reg.Route("@ready", "Prepare for glide commands."). Does(cmd.ReadyToGlide, "ready").Using("filename").From("cxt:yaml"). Does(cmd.ParseYaml, "cfg").Using("filename").From("cxt:yaml") reg.Route("get", "Install a pkg in vendor, and store the results in the glide.yaml"). Includes("@startup"). Includes("@ready"). Does(cmd.GetAll, "goget"). Using("filename").From("cxt:yaml"). Using("packages").From("cxt:packages"). Using("conf").From("cxt:cfg"). Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg"). Does(cmd.Recurse, "recurse").Using("conf").From("cxt:cfg"). Using("enable").From("cxt:recursiveDependencies"). Using("importGodeps").From("cxt:importGodeps"). Using("importGPM").From("cxt:importGPM"). Using("importGb").From("cxt:importGb"). Using("force").From("cxt:forceUpdate").WithDefault(false). Using("packages").From("cxt:packages"). Does(cmd.WriteYaml, "out"). Using("yaml.Node").From("cxt:merged"). Using("filename").WithDefault("glide.yaml").From("cxt:yaml") reg.Route("exec", "Execute command with GOPATH set."). Includes("@startup"). Includes("@ready"). Does(cmd.ExecCmd, "cmd"). Using("args").From("cxt:cliArgs"). Using("filename").From("cxt:yaml") reg.Route("update", "Update dependencies."). Includes("@startup"). Includes("@ready"). Does(cmd.CowardMode, "_"). Does(cmd.Mkdir, "dir").Using("dir").WithDefault(VendorDir). Does(cmd.DeleteUnusedPackages, "deleted"). Using("conf").From("cxt:cfg"). Using("optIn").From("cxt:deleteOptIn"). Does(cmd.VendoredSetup, "cfg"). Using("conf").From("cxt:cfg"). Using("update").From("cxt:updateVendoredDeps"). Does(cmd.UpdateImports, "dependencies"). Using("conf").From("cxt:cfg"). Using("force").From("cxt:forceUpdate"). Using("packages").From("cxt:packages"). Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg"). Does(cmd.Recurse, "recurse").Using("conf").From("cxt:cfg"). Using("deleteFlatten").From("cxt:deleteFlatten"). Using("importGodeps").From("cxt:importGodeps"). Using("importGPM").From("cxt:importGPM"). Using("importGb").From("cxt:importGb"). Using("enable").From("cxt:recursiveDependencies"). Using("force").From("cxt:forceUpdate"). Using("packages").From("cxt:packages"). Does(cmd.VendoredCleanUp, "_"). Using("conf").From("cxt:cfg"). Using("update").From("cxt:updateVendoredDeps") //Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg") reg.Route("rebuild", "Rebuild dependencies"). Includes("@startup"). Includes("@ready"). Does(cmd.CowardMode, "_"). Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg") reg.Route("pin", "Print a YAML file with all of the packages pinned to the current version."). Includes("@startup"). Includes("@ready"). Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg"). Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out"). Using("yaml.Node").From("cxt:merged"). Using("filename").From("cxt:toPath") reg.Route("import gpm", "Read a Godeps file"). Includes("@startup"). Includes("@ready"). Does(cmd.GPMGodeps, "godeps"). Does(cmd.AddDependencies, "addGodeps"). Using("dependencies").From("cxt:godeps"). Using("conf").From("cxt:cfg"). Does(cmd.GPMGodepsGit, "godepsGit"). Does(cmd.AddDependencies, "addGodepsGit"). Using("dependencies").From("cxt:godepsGit"). Using("conf").From("cxt:cfg"). // Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg"). Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged") reg.Route("import godep", "Read a Godeps.json file"). Includes("@startup"). Includes("@ready"). Does(cmd.ParseGodepGodeps, "godeps"). Does(cmd.AddDependencies, "addGodeps"). Using("dependencies").From("cxt:godeps"). Using("conf").From("cxt:cfg"). // Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg"). Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged") reg.Route("import gb", "Read a vendor/manifest file"). Includes("@startup"). Includes("@ready"). Does(cmd.GbManifest, "manifest"). Does(cmd.AddDependencies, "addGodeps"). Using("dependencies").From("cxt:manifest"). Using("conf").From("cxt:cfg"). Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out").Using("yaml.Node").From("cxt:merged") reg.Route("guess", "Guess dependencies"). Includes("@ready"). Does(cmd.GuessDeps, "cfg"). Does(cmd.MergeToYaml, "merged").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out"). Using("yaml.Node").From("cxt:merged"). Using("filename").From("cxt:toPath") reg.Route("create", "Initialize Glide"). Includes("@startup"). Does(cmd.InitGlide, "init"). Using("filename").From("cxt:yaml"). Using("project").From("cxt:project").WithDefault("main") reg.Route("name", "Print environment"). Includes("@startup"). Includes("@ready"). Does(cmd.PrintName, "status"). Using("conf").From("cxt:cfg") reg.Route("tree", "Print a dependency graph."). Includes("@startup"). Does(cmd.Tree, "tree") reg.Route("list", "Print a dependency graph."). Includes("@startup"). Does(cmd.ListDeps, "list") reg.Route("nv", "No Vendor"). Includes("@startup"). Does(cmd.NoVendor, "paths"). Does(cmd.PathString, "out").Using("paths").From("cxt:paths") reg.Route("about", "Status"). Includes("@startup"). Does(cmd.About, "about") reg.Route("@plugin", "Try to send to a plugin."). Includes("@ready"). Does(cmd.DropToShell, "plugin"). Using("command").From("cxt:command") }
// 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"}, }, }, }, }) }
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"}, }, }, }, }) }
// 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"}, }, }, }, }) }
func routes(reg *cookoo.Registry, cxt cookoo.Context) { reg.Route("@startup", "Parse args and send to the right subcommand."). // TODO: Add setup for debug in addition to quiet. Does(cmd.BeQuiet, "quiet"). Using("quiet").From("cxt:q"). Using("debug").From("cxt:debug"). Does(cmd.CheckColor, "no-color"). Using("no-color").From("cxt:no-color"). Does(cmd.VersionGuard, "v") reg.Route("@ready", "Prepare for glide commands."). Does(cmd.ReadyToGlide, "ready").Using("filename").From("cxt:yaml"). Does(cmd.ParseYaml, "cfg").Using("filename").From("cxt:yaml"). Does(cmd.EnsureCacheDir, "_").Using("home").From("cxt:home") reg.Route("get", "Install a pkg in vendor, and store the results in the glide.yaml"). Includes("@startup"). Includes("@ready"). Does(cmd.CowardMode, "_"). Does(cmd.GetAll, "goget"). Using("packages").From("cxt:packages"). Using("conf").From("cxt:cfg"). Using("insecure").From("cxt:insecure"). Does(cmd.VendoredSetup, "cfg"). Using("conf").From("cxt:cfg"). Using("update").From("cxt:updateVendoredDeps"). Does(cmd.UpdateImports, "dependencies"). Using("conf").From("cxt:cfg"). Using("force").From("cxt:forceUpdate"). //Using("packages").From("cxt:packages"). Using("home").From("cxt:home"). Using("cache").From("cxt:useCache"). Using("cacheGopath").From("cxt:cacheGopath"). Using("useGopath").From("cxt:useGopath"). Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg"). Does(cmd.Flatten, "flattened").Using("conf").From("cxt:cfg"). //Using("packages").From("cxt:packages"). Using("force").From("cxt:forceUpdate"). Using("home").From("cxt:home"). Using("cache").From("cxt:useCache"). Using("cacheGopath").From("cxt:cacheGopath"). Using("useGopath").From("cxt:useGopath"). Does(cmd.VendoredCleanUp, "_"). Using("conf").From("cxt:flattened"). Using("update").From("cxt:updateVendoredDeps"). Does(cmd.WriteYaml, "out"). Using("conf").From("cxt:cfg"). Using("filename").WithDefault("glide.yaml").From("cxt:yaml"). Does(cmd.WriteLock, "lock"). Using("lockfile").From("cxt:Lockfile") reg.Route("install", "Install dependencies."). Includes("@startup"). Includes("@ready"). Does(cmd.CowardMode, "_"). Does(cmd.LockFileExists, "_"). Does(cmd.LoadLockFile, "lock"). Using("conf").From("cxt:cfg"). Does(cmd.Mkdir, "dir").Using("dir").WithDefault(VendorDir). Does(cmd.DeleteUnusedPackages, "deleted"). Using("conf").From("cxt:cfg"). Using("optIn").From("cxt:deleteOptIn"). Does(cmd.VendoredSetup, "cfg"). Using("conf").From("cxt:cfg"). Using("update").From("cxt:updateVendoredDeps"). Does(cmd.Install, "icfg"). Using("conf").From("cxt:cfg"). Using("lock").From("cxt:lock"). Using("home").From("cxt:home"). Does(cmd.SetReference, "version").Using("conf").From("cxt:icfg"). Does(cmd.VendoredCleanUp, "_"). Using("conf").From("cxt:icfg"). Using("update").From("cxt:updateVendoredDeps") reg.Route("update", "Update dependencies."). Includes("@startup"). Includes("@ready"). Does(cmd.CowardMode, "_"). Does(cmd.Mkdir, "dir").Using("dir").WithDefault(VendorDir). Does(cmd.DeleteUnusedPackages, "deleted"). Using("conf").From("cxt:cfg"). Using("optIn").From("cxt:deleteOptIn"). Does(cmd.VendoredSetup, "cfg"). Using("conf").From("cxt:cfg"). Using("update").From("cxt:updateVendoredDeps"). Does(cmd.UpdateImports, "dependencies"). Using("conf").From("cxt:cfg"). Using("force").From("cxt:forceUpdate"). Using("packages").From("cxt:packages"). Using("home").From("cxt:home"). Using("cache").From("cxt:useCache"). Using("cacheGopath").From("cxt:cacheGopath"). Using("useGopath").From("cxt:useGopath"). Does(cmd.SetReference, "version").Using("conf").From("cxt:cfg"). Does(cmd.Flatten, "flattened").Using("conf").From("cxt:cfg"). //Using("packages").From("cxt:packages"). Using("force").From("cxt:forceUpdate"). Using("skip").From("cxt:skipFlatten"). Using("home").From("cxt:home"). Using("cache").From("cxt:useCache"). Using("cacheGopath").From("cxt:cacheGopath"). Using("useGopath").From("cxt:useGopath"). Does(cmd.VendoredCleanUp, "_"). Using("conf").From("cxt:flattened"). Using("update").From("cxt:updateVendoredDeps"). Does(cmd.WriteYaml, "out"). Using("conf").From("cxt:cfg"). Using("filename").From("cxt:toPath"). Using("toStdout").From("cxt:toStdout"). Does(cmd.WriteLock, "lock"). Using("lockfile").From("cxt:Lockfile"). Using("skip").From("cxt:skipFlatten") //Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg") reg.Route("rebuild", "Rebuild dependencies"). Includes("@startup"). Includes("@ready"). Does(cmd.CowardMode, "_"). Does(cmd.Rebuild, "rebuild").Using("conf").From("cxt:cfg") reg.Route("pin", "Print a YAML file with all of the packages pinned to the current version."). Includes("@startup"). Includes("@ready"). Does(cmd.Flatten, "flattened").Using("conf").From("cxt:cfg"). Using("packages").From("cxt:packages"). Using("force").From("cxt:forceUpdate"). Using("skip").From("cxt:skipFlatten"). Using("home").From("cxt:home"). Using("cache").From("cxt:useCache"). Using("cacheGopath").From("cxt:cacheGopath"). Using("useGopath").From("cxt:useGopath"). //Does(cmd.VendoredCleanUp, "_"). //Using("conf").From("cxt:flattened"). //Using("update").From("cxt:updateVendoredDeps"). // Write the Lockfile Does(cmd.WriteYaml, "out"). Using("conf").From("cxt:Lockfile"). Using("filename").From("cxt:toPath"). Using("toStdout").From("cxt:toStdout") reg.Route("import gpm", "Read a Godeps file"). Includes("@startup"). Includes("@ready"). Does(cmd.GPMGodeps, "godeps"). Does(cmd.AddDependencies, "addGodeps"). Using("dependencies").From("cxt:godeps"). Using("conf").From("cxt:cfg"). Does(cmd.GPMGodepsGit, "godepsGit"). Does(cmd.AddDependencies, "addGodepsGit"). Using("dependencies").From("cxt:godepsGit"). Using("conf").From("cxt:cfg"). // Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out").Using("conf").From("cxt:cfg"). Using("filename").From("cxt:toPath") reg.Route("import godep", "Read a Godeps.json file"). Includes("@startup"). Includes("@ready"). Does(cmd.ParseGodepGodeps, "godeps"). Does(cmd.AddDependencies, "addGodeps"). Using("dependencies").From("cxt:godeps"). Using("conf").From("cxt:cfg"). // Does(cmd.UpdateReferences, "refs").Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out").Using("conf").From("cxt:cfg"). Using("filename").From("cxt:toPath") reg.Route("import gb", "Read a vendor/manifest file"). Includes("@startup"). Includes("@ready"). Does(cmd.GbManifest, "manifest"). Does(cmd.AddDependencies, "addGodeps"). Using("dependencies").From("cxt:manifest"). Using("conf").From("cxt:cfg"). Does(cmd.WriteYaml, "out").Using("conf").From("cxt:cfg"). Using("filename").From("cxt:toPath") reg.Route("create", "Guess dependencies"). Includes("@startup"). Does(cmd.GuardYaml, "_"). Using("filename").From("cxt:yaml"). Does(cmd.GuessDeps, "cfg"). Using("skipImport").From("cxt:skipImport"). Does(cmd.WriteYaml, "out"). Using("conf").From("cxt:cfg"). Using("filename").From("cxt:yaml") reg.Route("name", "Print environment"). Includes("@startup"). Includes("@ready"). Does(cmd.PrintName, "status"). Using("conf").From("cxt:cfg") reg.Route("tree", "Print a dependency graph."). Includes("@startup"). Does(cmd.Tree, "tree") reg.Route("list", "Print a dependency graph."). Includes("@startup"). Does(cmd.ListDeps, "list") reg.Route("nv", "No Vendor"). Includes("@startup"). Does(cmd.NoVendor, "paths"). Does(cmd.PathString, "out").Using("paths").From("cxt:paths") reg.Route("about", "Status"). Includes("@startup"). Does(cmd.About, "about") reg.Route("@plugin", "Try to send to a plugin."). Includes("@ready"). Does(cmd.DropToShell, "plugin"). Using("command").From("cxt:command") }
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"}, }, }) }
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"}, }, }, }, }) }
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"}, }, }, }, }) }