1
0

proxy.go 13 KB

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