proxy.go 11 KB

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