compose.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package convert
  2. import (
  3. "io/ioutil"
  4. "github.com/docker/docker/api/types"
  5. networktypes "github.com/docker/docker/api/types/network"
  6. "github.com/docker/docker/api/types/swarm"
  7. composetypes "github.com/docker/docker/cli/compose/types"
  8. )
  9. const (
  10. // LabelNamespace is the label used to track stack resources
  11. LabelNamespace = "com.docker.stack.namespace"
  12. )
  13. // Namespace mangles names by prepending the name
  14. type Namespace struct {
  15. name string
  16. }
  17. // Scope prepends the namespace to a name
  18. func (n Namespace) Scope(name string) string {
  19. return n.name + "_" + name
  20. }
  21. // Name returns the name of the namespace
  22. func (n Namespace) Name() string {
  23. return n.name
  24. }
  25. // NewNamespace returns a new Namespace for scoping of names
  26. func NewNamespace(name string) Namespace {
  27. return Namespace{name: name}
  28. }
  29. // AddStackLabel returns labels with the namespace label added
  30. func AddStackLabel(namespace Namespace, labels map[string]string) map[string]string {
  31. if labels == nil {
  32. labels = make(map[string]string)
  33. }
  34. labels[LabelNamespace] = namespace.name
  35. return labels
  36. }
  37. type networkMap map[string]composetypes.NetworkConfig
  38. // Networks from the compose-file type to the engine API type
  39. func Networks(namespace Namespace, networks networkMap, servicesNetworks map[string]struct{}) (map[string]types.NetworkCreate, []string) {
  40. if networks == nil {
  41. networks = make(map[string]composetypes.NetworkConfig)
  42. }
  43. externalNetworks := []string{}
  44. result := make(map[string]types.NetworkCreate)
  45. for internalName := range servicesNetworks {
  46. network := networks[internalName]
  47. if network.External.External {
  48. externalNetworks = append(externalNetworks, network.External.Name)
  49. continue
  50. }
  51. createOpts := types.NetworkCreate{
  52. Labels: AddStackLabel(namespace, network.Labels),
  53. Driver: network.Driver,
  54. Options: network.DriverOpts,
  55. Internal: network.Internal,
  56. Attachable: network.Attachable,
  57. }
  58. if network.Ipam.Driver != "" || len(network.Ipam.Config) > 0 {
  59. createOpts.IPAM = &networktypes.IPAM{}
  60. }
  61. if network.Ipam.Driver != "" {
  62. createOpts.IPAM.Driver = network.Ipam.Driver
  63. }
  64. for _, ipamConfig := range network.Ipam.Config {
  65. config := networktypes.IPAMConfig{
  66. Subnet: ipamConfig.Subnet,
  67. }
  68. createOpts.IPAM.Config = append(createOpts.IPAM.Config, config)
  69. }
  70. result[internalName] = createOpts
  71. }
  72. return result, externalNetworks
  73. }
  74. // Secrets converts secrets from the Compose type to the engine API type
  75. func Secrets(namespace Namespace, secrets map[string]composetypes.SecretConfig) ([]swarm.SecretSpec, error) {
  76. result := []swarm.SecretSpec{}
  77. for name, secret := range secrets {
  78. if secret.External.External {
  79. continue
  80. }
  81. data, err := ioutil.ReadFile(secret.File)
  82. if err != nil {
  83. return nil, err
  84. }
  85. result = append(result, swarm.SecretSpec{
  86. Annotations: swarm.Annotations{
  87. Name: namespace.Scope(name),
  88. Labels: AddStackLabel(namespace, secret.Labels),
  89. },
  90. Data: data,
  91. })
  92. }
  93. return result, nil
  94. }