proxy.go 12 KB

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