services.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package docker
  2. import (
  3. "fmt"
  4. "strings"
  5. log "github.com/Sirupsen/logrus"
  6. "github.com/rancherio/os/config"
  7. "github.com/rancherio/os/util"
  8. "github.com/rancherio/rancher-compose/librcompose/project"
  9. )
  10. type configEnvironment struct {
  11. cfg *config.Config
  12. }
  13. func appendEnv(array []string, key, value string) []string {
  14. parts := strings.SplitN(key, "/", 2)
  15. if len(parts) == 2 {
  16. key = parts[1]
  17. }
  18. return append(array, fmt.Sprintf("%s=%s", key, value))
  19. }
  20. func lookupKeys(cfg *config.Config, keys ...string) []string {
  21. for _, key := range keys {
  22. if strings.HasSuffix(key, "*") {
  23. result := []string{}
  24. for envKey, envValue := range cfg.Environment {
  25. keyPrefix := key[:len(key)-1]
  26. if strings.HasPrefix(envKey, keyPrefix) {
  27. result = appendEnv(result, envKey, envValue)
  28. }
  29. }
  30. if len(result) > 0 {
  31. return result
  32. }
  33. } else if value, ok := cfg.Environment[key]; ok {
  34. return appendEnv([]string{}, key, value)
  35. }
  36. }
  37. return []string{}
  38. }
  39. func (c *configEnvironment) Lookup(key, serviceName string, serviceConfig *project.ServiceConfig) []string {
  40. fullKey := fmt.Sprintf("%s/%s", serviceName, key)
  41. return lookupKeys(c.cfg, fullKey, key)
  42. }
  43. func RunServices(name string, cfg *config.Config, configs map[string]*project.ServiceConfig) error {
  44. network := false
  45. projectEvents := make(chan project.ProjectEvent)
  46. p := project.NewProject(name, NewContainerFactory(cfg))
  47. p.EnvironmentLookup = &configEnvironment{cfg: cfg}
  48. p.AddListener(projectEvents)
  49. enabled := make(map[string]bool)
  50. for name, serviceConfig := range configs {
  51. if err := p.AddConfig(name, serviceConfig); err != nil {
  52. log.Infof("Failed loading service %s", name)
  53. }
  54. }
  55. p.ReloadCallback = func() error {
  56. err := cfg.Reload()
  57. if err != nil {
  58. return err
  59. }
  60. for service, serviceEnabled := range cfg.ServicesInclude {
  61. if !serviceEnabled {
  62. continue
  63. }
  64. if _, ok := enabled[service]; ok {
  65. continue
  66. }
  67. bytes, err := LoadServiceResource(service, network, cfg)
  68. if err != nil {
  69. if err == util.ErrNoNetwork {
  70. log.Debugf("Can not load %s, networking not enabled", service)
  71. } else {
  72. log.Errorf("Failed to load %s : %v", service, err)
  73. }
  74. continue
  75. }
  76. err = p.Load(bytes)
  77. if err != nil {
  78. log.Errorf("Failed to load %s : %v", service, err)
  79. continue
  80. }
  81. enabled[service] = true
  82. }
  83. for service, config := range cfg.Services {
  84. if _, ok := enabled[service]; ok {
  85. continue
  86. }
  87. err = p.AddConfig(service, config)
  88. if err != nil {
  89. log.Errorf("Failed to load %s : %v", service, err)
  90. continue
  91. }
  92. enabled[service] = true
  93. }
  94. return nil
  95. }
  96. go func() {
  97. for event := range projectEvents {
  98. if event.Event == project.CONTAINER_STARTED && event.ServiceName == "network" {
  99. network = true
  100. }
  101. }
  102. }()
  103. err := p.ReloadCallback()
  104. if err != nil {
  105. log.Errorf("Failed to reload %s : %v", name, err)
  106. return err
  107. }
  108. return p.Up()
  109. }
  110. func LoadServiceResource(name string, network bool, cfg *config.Config) ([]byte, error) {
  111. return util.LoadResource(name, network, cfg.Repositories.ToArray())
  112. }