proxy.go 12 KB

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