service.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package service
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/rancher/os/cmd/control/service/command"
  6. "github.com/rancher/os/config"
  7. "github.com/rancher/os/pkg/compose"
  8. "github.com/rancher/os/pkg/log"
  9. "github.com/rancher/os/pkg/util"
  10. "github.com/rancher/os/pkg/util/network"
  11. "github.com/codegangsta/cli"
  12. dockerApp "github.com/docker/libcompose/cli/docker/app"
  13. "github.com/docker/libcompose/project"
  14. )
  15. type projectFactory struct {
  16. }
  17. func (p *projectFactory) Create(c *cli.Context) (project.APIProject, error) {
  18. cfg := config.LoadConfig()
  19. return compose.GetProject(cfg, true, false)
  20. }
  21. func beforeApp(c *cli.Context) error {
  22. if c.GlobalBool("verbose") {
  23. log.SetLevel(log.DebugLevel)
  24. }
  25. return nil
  26. }
  27. func Commands() cli.Command {
  28. factory := &projectFactory{}
  29. app := cli.Command{}
  30. app.Name = "service"
  31. app.ShortName = "s"
  32. app.Before = beforeApp
  33. app.Flags = append(dockerApp.DockerClientFlags(), cli.BoolFlag{
  34. Name: "verbose,debug",
  35. })
  36. app.Subcommands = append(serviceSubCommands(),
  37. command.BuildCommand(factory),
  38. command.CreateCommand(factory),
  39. command.UpCommand(factory),
  40. command.StartCommand(factory),
  41. command.LogsCommand(factory),
  42. command.RestartCommand(factory),
  43. command.StopCommand(factory),
  44. command.RmCommand(factory),
  45. command.PullCommand(factory),
  46. command.KillCommand(factory),
  47. command.PsCommand(factory),
  48. )
  49. return app
  50. }
  51. func serviceSubCommands() []cli.Command {
  52. return []cli.Command{
  53. {
  54. Name: "enable",
  55. Usage: "turn on an service",
  56. Action: enable,
  57. },
  58. {
  59. Name: "disable",
  60. Usage: "turn off an service",
  61. Action: disable,
  62. },
  63. {
  64. Name: "list",
  65. Usage: "list services and state",
  66. Flags: []cli.Flag{
  67. cli.BoolFlag{
  68. Name: "all, a",
  69. Usage: "list all services and state",
  70. },
  71. cli.BoolFlag{
  72. Name: "update, u",
  73. Usage: "update service cache",
  74. },
  75. },
  76. Action: list,
  77. },
  78. {
  79. Name: "delete",
  80. Usage: "delete a service",
  81. Action: del,
  82. },
  83. }
  84. }
  85. func updateIncludedServices(cfg *config.CloudConfig) error {
  86. return config.Set("rancher.services_include", cfg.Rancher.ServicesInclude)
  87. }
  88. func disable(c *cli.Context) error {
  89. changed := false
  90. cfg := config.LoadConfig()
  91. for _, service := range c.Args() {
  92. validateService(service, cfg)
  93. if _, ok := cfg.Rancher.ServicesInclude[service]; !ok {
  94. continue
  95. }
  96. cfg.Rancher.ServicesInclude[service] = false
  97. changed = true
  98. }
  99. if changed {
  100. if err := updateIncludedServices(cfg); err != nil {
  101. log.Fatal(err)
  102. }
  103. }
  104. return nil
  105. }
  106. func del(c *cli.Context) error {
  107. changed := false
  108. cfg := config.LoadConfig()
  109. for _, service := range c.Args() {
  110. validateService(service, cfg)
  111. if _, ok := cfg.Rancher.ServicesInclude[service]; !ok {
  112. continue
  113. }
  114. delete(cfg.Rancher.ServicesInclude, service)
  115. changed = true
  116. }
  117. if changed {
  118. if err := updateIncludedServices(cfg); err != nil {
  119. log.Fatal(err)
  120. }
  121. }
  122. return nil
  123. }
  124. func enable(c *cli.Context) error {
  125. cfg := config.LoadConfig()
  126. var enabledServices []string
  127. for _, service := range c.Args() {
  128. validateService(service, cfg)
  129. if val, ok := cfg.Rancher.ServicesInclude[service]; !ok || !val {
  130. if isLocal(service) && !strings.HasPrefix(service, "/var/lib/rancher/conf") {
  131. log.Fatalf("ERROR: Service should be in path /var/lib/rancher/conf")
  132. }
  133. cfg.Rancher.ServicesInclude[service] = true
  134. enabledServices = append(enabledServices, service)
  135. }
  136. }
  137. if len(enabledServices) > 0 {
  138. if err := compose.StageServices(cfg, enabledServices...); err != nil {
  139. log.Fatal(err)
  140. }
  141. if err := updateIncludedServices(cfg); err != nil {
  142. log.Fatal(err)
  143. }
  144. }
  145. return nil
  146. }
  147. func list(c *cli.Context) error {
  148. cfg := config.LoadConfig()
  149. clone := make(map[string]bool)
  150. for service, enabled := range cfg.Rancher.ServicesInclude {
  151. clone[service] = enabled
  152. }
  153. services := availableService(cfg, c.Bool("update"))
  154. if c.Bool("all") {
  155. for service := range cfg.Rancher.Services {
  156. fmt.Printf("enabled %s\n", service)
  157. }
  158. }
  159. for _, service := range services {
  160. if enabled, ok := clone[service]; ok {
  161. delete(clone, service)
  162. if enabled {
  163. fmt.Printf("enabled %s\n", service)
  164. } else {
  165. fmt.Printf("disabled %s\n", service)
  166. }
  167. } else {
  168. fmt.Printf("disabled %s\n", service)
  169. }
  170. }
  171. for service, enabled := range clone {
  172. if enabled {
  173. fmt.Printf("enabled %s\n", service)
  174. } else {
  175. fmt.Printf("disabled %s\n", service)
  176. }
  177. }
  178. return nil
  179. }
  180. func isLocal(service string) bool {
  181. return strings.HasPrefix(service, "/")
  182. }
  183. func IsLocalOrURL(service string) bool {
  184. return isLocal(service) || strings.HasPrefix(service, "http:/") || strings.HasPrefix(service, "https:/")
  185. }
  186. // ValidService checks to see if the service definition exists
  187. func ValidService(service string, cfg *config.CloudConfig) bool {
  188. services := availableService(cfg, false)
  189. if !IsLocalOrURL(service) && !util.Contains(services, service) {
  190. return false
  191. }
  192. return true
  193. }
  194. func validateService(service string, cfg *config.CloudConfig) {
  195. if !ValidService(service, cfg) {
  196. log.Fatalf("%s is not a valid service", service)
  197. }
  198. }
  199. func availableService(cfg *config.CloudConfig, update bool) []string {
  200. if update {
  201. err := network.UpdateCaches(cfg.Rancher.Repositories.ToArray(), "services")
  202. if err != nil {
  203. log.Debugf("Failed to update service caches: %v", err)
  204. }
  205. }
  206. services, err := network.GetServices(cfg.Rancher.Repositories.ToArray())
  207. if err != nil {
  208. log.Fatalf("Failed to get services: %v", err)
  209. }
  210. return services
  211. }