proxy.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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. WatchFn func(ctx context.Context, project *types.Project, services []string, options WatchOptions) error
  46. MaxConcurrencyFn func(parallel int)
  47. interceptors []Interceptor
  48. }
  49. // NewServiceProxy produces a ServiceProxy
  50. func NewServiceProxy() *ServiceProxy {
  51. return &ServiceProxy{}
  52. }
  53. // Interceptor allow to customize the compose types.Project before the actual Service method is executed
  54. type Interceptor func(ctx context.Context, project *types.Project)
  55. // WithService configure proxy to use specified Service as delegate
  56. func (s *ServiceProxy) WithService(service Service) *ServiceProxy {
  57. s.BuildFn = service.Build
  58. s.PushFn = service.Push
  59. s.PullFn = service.Pull
  60. s.CreateFn = service.Create
  61. s.StartFn = service.Start
  62. s.RestartFn = service.Restart
  63. s.StopFn = service.Stop
  64. s.UpFn = service.Up
  65. s.DownFn = service.Down
  66. s.LogsFn = service.Logs
  67. s.PsFn = service.Ps
  68. s.ListFn = service.List
  69. s.ConvertFn = service.Convert
  70. s.KillFn = service.Kill
  71. s.RunOneOffContainerFn = service.RunOneOffContainer
  72. s.RemoveFn = service.Remove
  73. s.ExecFn = service.Exec
  74. s.CopyFn = service.Copy
  75. s.PauseFn = service.Pause
  76. s.UnPauseFn = service.UnPause
  77. s.TopFn = service.Top
  78. s.EventsFn = service.Events
  79. s.PortFn = service.Port
  80. s.ImagesFn = service.Images
  81. s.WatchFn = service.Watch
  82. s.MaxConcurrencyFn = service.MaxConcurrency
  83. return s
  84. }
  85. // WithInterceptor configures Interceptor to be applied to Service method execution
  86. func (s *ServiceProxy) WithInterceptor(interceptors ...Interceptor) *ServiceProxy {
  87. s.interceptors = append(s.interceptors, interceptors...)
  88. return s
  89. }
  90. // Build implements Service interface
  91. func (s *ServiceProxy) Build(ctx context.Context, project *types.Project, options BuildOptions) error {
  92. if s.BuildFn == nil {
  93. return ErrNotImplemented
  94. }
  95. for _, i := range s.interceptors {
  96. i(ctx, project)
  97. }
  98. return s.BuildFn(ctx, project, options)
  99. }
  100. // Push implements Service interface
  101. func (s *ServiceProxy) Push(ctx context.Context, project *types.Project, options PushOptions) error {
  102. if s.PushFn == nil {
  103. return ErrNotImplemented
  104. }
  105. for _, i := range s.interceptors {
  106. i(ctx, project)
  107. }
  108. return s.PushFn(ctx, project, options)
  109. }
  110. // Pull implements Service interface
  111. func (s *ServiceProxy) Pull(ctx context.Context, project *types.Project, options PullOptions) error {
  112. if s.PullFn == nil {
  113. return ErrNotImplemented
  114. }
  115. for _, i := range s.interceptors {
  116. i(ctx, project)
  117. }
  118. return s.PullFn(ctx, project, options)
  119. }
  120. // Create implements Service interface
  121. func (s *ServiceProxy) Create(ctx context.Context, project *types.Project, options CreateOptions) error {
  122. if s.CreateFn == nil {
  123. return ErrNotImplemented
  124. }
  125. for _, i := range s.interceptors {
  126. i(ctx, project)
  127. }
  128. return s.CreateFn(ctx, project, options)
  129. }
  130. // Start implements Service interface
  131. func (s *ServiceProxy) Start(ctx context.Context, projectName string, options StartOptions) error {
  132. if s.StartFn == nil {
  133. return ErrNotImplemented
  134. }
  135. return s.StartFn(ctx, projectName, options)
  136. }
  137. // Restart implements Service interface
  138. func (s *ServiceProxy) Restart(ctx context.Context, projectName string, options RestartOptions) error {
  139. if s.RestartFn == nil {
  140. return ErrNotImplemented
  141. }
  142. return s.RestartFn(ctx, projectName, options)
  143. }
  144. // Stop implements Service interface
  145. func (s *ServiceProxy) Stop(ctx context.Context, projectName string, options StopOptions) error {
  146. if s.StopFn == nil {
  147. return ErrNotImplemented
  148. }
  149. return s.StopFn(ctx, projectName, options)
  150. }
  151. // Up implements Service interface
  152. func (s *ServiceProxy) Up(ctx context.Context, project *types.Project, options UpOptions) error {
  153. if s.UpFn == nil {
  154. return ErrNotImplemented
  155. }
  156. for _, i := range s.interceptors {
  157. i(ctx, project)
  158. }
  159. return s.UpFn(ctx, project, options)
  160. }
  161. // Down implements Service interface
  162. func (s *ServiceProxy) Down(ctx context.Context, project string, options DownOptions) error {
  163. if s.DownFn == nil {
  164. return ErrNotImplemented
  165. }
  166. return s.DownFn(ctx, project, options)
  167. }
  168. // Logs implements Service interface
  169. func (s *ServiceProxy) Logs(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error {
  170. if s.LogsFn == nil {
  171. return ErrNotImplemented
  172. }
  173. return s.LogsFn(ctx, projectName, consumer, options)
  174. }
  175. // Ps implements Service interface
  176. func (s *ServiceProxy) Ps(ctx context.Context, project string, options PsOptions) ([]ContainerSummary, error) {
  177. if s.PsFn == nil {
  178. return nil, ErrNotImplemented
  179. }
  180. return s.PsFn(ctx, project, options)
  181. }
  182. // List implements Service interface
  183. func (s *ServiceProxy) List(ctx context.Context, options ListOptions) ([]Stack, error) {
  184. if s.ListFn == nil {
  185. return nil, ErrNotImplemented
  186. }
  187. return s.ListFn(ctx, options)
  188. }
  189. // Convert implements Service interface
  190. func (s *ServiceProxy) Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error) {
  191. if s.ConvertFn == nil {
  192. return nil, ErrNotImplemented
  193. }
  194. for _, i := range s.interceptors {
  195. i(ctx, project)
  196. }
  197. return s.ConvertFn(ctx, project, options)
  198. }
  199. // Kill implements Service interface
  200. func (s *ServiceProxy) Kill(ctx context.Context, projectName string, options KillOptions) error {
  201. if s.KillFn == nil {
  202. return ErrNotImplemented
  203. }
  204. return s.KillFn(ctx, projectName, options)
  205. }
  206. // RunOneOffContainer implements Service interface
  207. func (s *ServiceProxy) RunOneOffContainer(ctx context.Context, project *types.Project, options RunOptions) (int, error) {
  208. if s.RunOneOffContainerFn == nil {
  209. return 0, ErrNotImplemented
  210. }
  211. for _, i := range s.interceptors {
  212. i(ctx, project)
  213. }
  214. return s.RunOneOffContainerFn(ctx, project, options)
  215. }
  216. // Remove implements Service interface
  217. func (s *ServiceProxy) Remove(ctx context.Context, projectName string, options RemoveOptions) error {
  218. if s.RemoveFn == nil {
  219. return ErrNotImplemented
  220. }
  221. return s.RemoveFn(ctx, projectName, options)
  222. }
  223. // Exec implements Service interface
  224. func (s *ServiceProxy) Exec(ctx context.Context, projectName string, options RunOptions) (int, error) {
  225. if s.ExecFn == nil {
  226. return 0, ErrNotImplemented
  227. }
  228. return s.ExecFn(ctx, projectName, options)
  229. }
  230. // Copy implements Service interface
  231. func (s *ServiceProxy) Copy(ctx context.Context, projectName string, options CopyOptions) error {
  232. if s.CopyFn == nil {
  233. return ErrNotImplemented
  234. }
  235. return s.CopyFn(ctx, projectName, options)
  236. }
  237. // Pause implements Service interface
  238. func (s *ServiceProxy) Pause(ctx context.Context, projectName string, options PauseOptions) error {
  239. if s.PauseFn == nil {
  240. return ErrNotImplemented
  241. }
  242. return s.PauseFn(ctx, projectName, options)
  243. }
  244. // UnPause implements Service interface
  245. func (s *ServiceProxy) UnPause(ctx context.Context, projectName string, options PauseOptions) error {
  246. if s.UnPauseFn == nil {
  247. return ErrNotImplemented
  248. }
  249. return s.UnPauseFn(ctx, projectName, options)
  250. }
  251. // Top implements Service interface
  252. func (s *ServiceProxy) Top(ctx context.Context, project string, services []string) ([]ContainerProcSummary, error) {
  253. if s.TopFn == nil {
  254. return nil, ErrNotImplemented
  255. }
  256. return s.TopFn(ctx, project, services)
  257. }
  258. // Events implements Service interface
  259. func (s *ServiceProxy) Events(ctx context.Context, projectName string, options EventsOptions) error {
  260. if s.EventsFn == nil {
  261. return ErrNotImplemented
  262. }
  263. return s.EventsFn(ctx, projectName, options)
  264. }
  265. // Port implements Service interface
  266. func (s *ServiceProxy) Port(ctx context.Context, projectName string, service string, port uint16, options PortOptions) (string, int, error) {
  267. if s.PortFn == nil {
  268. return "", 0, ErrNotImplemented
  269. }
  270. return s.PortFn(ctx, projectName, service, port, options)
  271. }
  272. // Images implements Service interface
  273. func (s *ServiceProxy) Images(ctx context.Context, project string, options ImagesOptions) ([]ImageSummary, error) {
  274. if s.ImagesFn == nil {
  275. return nil, ErrNotImplemented
  276. }
  277. return s.ImagesFn(ctx, project, options)
  278. }
  279. // Watch implements Service interface
  280. func (s *ServiceProxy) Watch(ctx context.Context, project *types.Project, services []string, options WatchOptions) error {
  281. if s.WatchFn == nil {
  282. return ErrNotImplemented
  283. }
  284. return s.WatchFn(ctx, project, services, options)
  285. }
  286. func (s *ServiceProxy) MaxConcurrency(i int) {
  287. s.MaxConcurrencyFn(i)
  288. }