proxy.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. Copyright 2020 Docker Compose CLI authors
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package api
  14. import (
  15. "context"
  16. "github.com/compose-spec/compose-go/types"
  17. )
  18. var _ Service = &ServiceProxy{}
  19. // ServiceProxy implements Service by delegating to implementation functions. This allows lazy init and per-method overrides
  20. type ServiceProxy struct {
  21. BuildFn func(ctx context.Context, project *types.Project, options BuildOptions) error
  22. PushFn func(ctx context.Context, project *types.Project, options PushOptions) error
  23. PullFn func(ctx context.Context, project *types.Project, opts PullOptions) error
  24. CreateFn func(ctx context.Context, project *types.Project, opts CreateOptions) error
  25. StartFn func(ctx context.Context, projectName string, options StartOptions) error
  26. RestartFn func(ctx context.Context, projectName string, options RestartOptions) error
  27. StopFn func(ctx context.Context, projectName string, options StopOptions) error
  28. UpFn func(ctx context.Context, project *types.Project, options UpOptions) error
  29. DownFn func(ctx context.Context, projectName string, options DownOptions) error
  30. LogsFn func(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error
  31. PsFn func(ctx context.Context, projectName string, options PsOptions) ([]ContainerSummary, error)
  32. ListFn func(ctx context.Context, options ListOptions) ([]Stack, error)
  33. ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
  34. KillFn func(ctx context.Context, project string, options KillOptions) error
  35. RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
  36. RemoveFn func(ctx context.Context, project string, options RemoveOptions) error
  37. ExecFn func(ctx context.Context, project string, opts RunOptions) (int, error)
  38. CopyFn func(ctx context.Context, project string, options CopyOptions) error
  39. PauseFn func(ctx context.Context, project string, options PauseOptions) error
  40. UnPauseFn func(ctx context.Context, project string, options PauseOptions) error
  41. TopFn func(ctx context.Context, projectName string, services []string) ([]ContainerProcSummary, error)
  42. EventsFn func(ctx context.Context, project string, options EventsOptions) error
  43. PortFn func(ctx context.Context, project string, service string, port uint16, options PortOptions) (string, int, error)
  44. ImagesFn func(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
  45. MaxConcurrencyFn func(parallel int)
  46. interceptors []Interceptor
  47. }
  48. // NewServiceProxy produces a ServiceProxy
  49. func NewServiceProxy() *ServiceProxy {
  50. return &ServiceProxy{}
  51. }
  52. // Interceptor allow to customize the compose types.Project before the actual Service method is executed
  53. type Interceptor func(ctx context.Context, project *types.Project)
  54. // WithService configure proxy to use specified Service as delegate
  55. func (s *ServiceProxy) WithService(service Service) *ServiceProxy {
  56. s.BuildFn = service.Build
  57. s.PushFn = service.Push
  58. s.PullFn = service.Pull
  59. s.CreateFn = service.Create
  60. s.StartFn = service.Start
  61. s.RestartFn = service.Restart
  62. s.StopFn = service.Stop
  63. s.UpFn = service.Up
  64. s.DownFn = service.Down
  65. s.LogsFn = service.Logs
  66. s.PsFn = service.Ps
  67. s.ListFn = service.List
  68. s.ConvertFn = service.Convert
  69. s.KillFn = service.Kill
  70. s.RunOneOffContainerFn = service.RunOneOffContainer
  71. s.RemoveFn = service.Remove
  72. s.ExecFn = service.Exec
  73. s.CopyFn = service.Copy
  74. s.PauseFn = service.Pause
  75. s.UnPauseFn = service.UnPause
  76. s.TopFn = service.Top
  77. s.EventsFn = service.Events
  78. s.PortFn = service.Port
  79. s.ImagesFn = service.Images
  80. s.MaxConcurrencyFn = service.MaxConcurrency
  81. return s
  82. }
  83. // WithInterceptor configures Interceptor to be applied to Service method execution
  84. func (s *ServiceProxy) WithInterceptor(interceptors ...Interceptor) *ServiceProxy {
  85. s.interceptors = append(s.interceptors, interceptors...)
  86. return s
  87. }
  88. // Build implements Service interface
  89. func (s *ServiceProxy) Build(ctx context.Context, project *types.Project, options BuildOptions) error {
  90. if s.BuildFn == nil {
  91. return ErrNotImplemented
  92. }
  93. for _, i := range s.interceptors {
  94. i(ctx, project)
  95. }
  96. return s.BuildFn(ctx, project, options)
  97. }
  98. // Push implements Service interface
  99. func (s *ServiceProxy) Push(ctx context.Context, project *types.Project, options PushOptions) error {
  100. if s.PushFn == nil {
  101. return ErrNotImplemented
  102. }
  103. for _, i := range s.interceptors {
  104. i(ctx, project)
  105. }
  106. return s.PushFn(ctx, project, options)
  107. }
  108. // Pull implements Service interface
  109. func (s *ServiceProxy) Pull(ctx context.Context, project *types.Project, options PullOptions) error {
  110. if s.PullFn == nil {
  111. return ErrNotImplemented
  112. }
  113. for _, i := range s.interceptors {
  114. i(ctx, project)
  115. }
  116. return s.PullFn(ctx, project, options)
  117. }
  118. // Create implements Service interface
  119. func (s *ServiceProxy) Create(ctx context.Context, project *types.Project, options CreateOptions) error {
  120. if s.CreateFn == nil {
  121. return ErrNotImplemented
  122. }
  123. for _, i := range s.interceptors {
  124. i(ctx, project)
  125. }
  126. return s.CreateFn(ctx, project, options)
  127. }
  128. // Start implements Service interface
  129. func (s *ServiceProxy) Start(ctx context.Context, projectName string, options StartOptions) error {
  130. if s.StartFn == nil {
  131. return ErrNotImplemented
  132. }
  133. return s.StartFn(ctx, projectName, options)
  134. }
  135. // Restart implements Service interface
  136. func (s *ServiceProxy) Restart(ctx context.Context, projectName string, options RestartOptions) error {
  137. if s.RestartFn == nil {
  138. return ErrNotImplemented
  139. }
  140. return s.RestartFn(ctx, projectName, options)
  141. }
  142. // Stop implements Service interface
  143. func (s *ServiceProxy) Stop(ctx context.Context, projectName string, options StopOptions) error {
  144. if s.StopFn == nil {
  145. return ErrNotImplemented
  146. }
  147. return s.StopFn(ctx, projectName, options)
  148. }
  149. // Up implements Service interface
  150. func (s *ServiceProxy) Up(ctx context.Context, project *types.Project, options UpOptions) error {
  151. if s.UpFn == nil {
  152. return ErrNotImplemented
  153. }
  154. for _, i := range s.interceptors {
  155. i(ctx, project)
  156. }
  157. return s.UpFn(ctx, project, options)
  158. }
  159. // Down implements Service interface
  160. func (s *ServiceProxy) Down(ctx context.Context, project string, options DownOptions) error {
  161. if s.DownFn == nil {
  162. return ErrNotImplemented
  163. }
  164. return s.DownFn(ctx, project, options)
  165. }
  166. // Logs implements Service interface
  167. func (s *ServiceProxy) Logs(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error {
  168. if s.LogsFn == nil {
  169. return ErrNotImplemented
  170. }
  171. return s.LogsFn(ctx, projectName, consumer, options)
  172. }
  173. // Ps implements Service interface
  174. func (s *ServiceProxy) Ps(ctx context.Context, project string, options PsOptions) ([]ContainerSummary, error) {
  175. if s.PsFn == nil {
  176. return nil, ErrNotImplemented
  177. }
  178. return s.PsFn(ctx, project, options)
  179. }
  180. // List implements Service interface
  181. func (s *ServiceProxy) List(ctx context.Context, options ListOptions) ([]Stack, error) {
  182. if s.ListFn == nil {
  183. return nil, ErrNotImplemented
  184. }
  185. return s.ListFn(ctx, options)
  186. }
  187. // Convert implements Service interface
  188. func (s *ServiceProxy) Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error) {
  189. if s.ConvertFn == nil {
  190. return nil, ErrNotImplemented
  191. }
  192. for _, i := range s.interceptors {
  193. i(ctx, project)
  194. }
  195. return s.ConvertFn(ctx, project, options)
  196. }
  197. // Kill implements Service interface
  198. func (s *ServiceProxy) Kill(ctx context.Context, projectName string, options KillOptions) error {
  199. if s.KillFn == nil {
  200. return ErrNotImplemented
  201. }
  202. return s.KillFn(ctx, projectName, options)
  203. }
  204. // RunOneOffContainer implements Service interface
  205. func (s *ServiceProxy) RunOneOffContainer(ctx context.Context, project *types.Project, options RunOptions) (int, error) {
  206. if s.RunOneOffContainerFn == nil {
  207. return 0, ErrNotImplemented
  208. }
  209. for _, i := range s.interceptors {
  210. i(ctx, project)
  211. }
  212. return s.RunOneOffContainerFn(ctx, project, options)
  213. }
  214. // Remove implements Service interface
  215. func (s *ServiceProxy) Remove(ctx context.Context, projectName string, options RemoveOptions) error {
  216. if s.RemoveFn == nil {
  217. return ErrNotImplemented
  218. }
  219. return s.RemoveFn(ctx, projectName, options)
  220. }
  221. // Exec implements Service interface
  222. func (s *ServiceProxy) Exec(ctx context.Context, projectName string, options RunOptions) (int, error) {
  223. if s.ExecFn == nil {
  224. return 0, ErrNotImplemented
  225. }
  226. return s.ExecFn(ctx, projectName, options)
  227. }
  228. // Copy implements Service interface
  229. func (s *ServiceProxy) Copy(ctx context.Context, projectName string, options CopyOptions) error {
  230. if s.CopyFn == nil {
  231. return ErrNotImplemented
  232. }
  233. return s.CopyFn(ctx, projectName, options)
  234. }
  235. // Pause implements Service interface
  236. func (s *ServiceProxy) Pause(ctx context.Context, projectName string, options PauseOptions) error {
  237. if s.PauseFn == nil {
  238. return ErrNotImplemented
  239. }
  240. return s.PauseFn(ctx, projectName, options)
  241. }
  242. // UnPause implements Service interface
  243. func (s *ServiceProxy) UnPause(ctx context.Context, projectName string, options PauseOptions) error {
  244. if s.UnPauseFn == nil {
  245. return ErrNotImplemented
  246. }
  247. return s.UnPauseFn(ctx, projectName, options)
  248. }
  249. // Top implements Service interface
  250. func (s *ServiceProxy) Top(ctx context.Context, project string, services []string) ([]ContainerProcSummary, error) {
  251. if s.TopFn == nil {
  252. return nil, ErrNotImplemented
  253. }
  254. return s.TopFn(ctx, project, services)
  255. }
  256. // Events implements Service interface
  257. func (s *ServiceProxy) Events(ctx context.Context, projectName string, options EventsOptions) error {
  258. if s.EventsFn == nil {
  259. return ErrNotImplemented
  260. }
  261. return s.EventsFn(ctx, projectName, options)
  262. }
  263. // Port implements Service interface
  264. func (s *ServiceProxy) Port(ctx context.Context, projectName string, service string, port uint16, options PortOptions) (string, int, error) {
  265. if s.PortFn == nil {
  266. return "", 0, ErrNotImplemented
  267. }
  268. return s.PortFn(ctx, projectName, service, port, options)
  269. }
  270. // Images implements Service interface
  271. func (s *ServiceProxy) Images(ctx context.Context, project string, options ImagesOptions) ([]ImageSummary, error) {
  272. if s.ImagesFn == nil {
  273. return nil, ErrNotImplemented
  274. }
  275. return s.ImagesFn(ctx, project, options)
  276. }
  277. func (s *ServiceProxy) MaxConcurrency(i int) {
  278. s.MaxConcurrencyFn(i)
  279. }