api.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. package api
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "strings"
  8. "github.com/docker/libnetwork"
  9. "github.com/docker/libnetwork/types"
  10. "github.com/gorilla/mux"
  11. )
  12. var (
  13. successResponse = responseStatus{Status: "Success", StatusCode: http.StatusOK}
  14. createdResponse = responseStatus{Status: "Created", StatusCode: http.StatusCreated}
  15. mismatchResponse = responseStatus{Status: "Body/URI parameter mismatch", StatusCode: http.StatusBadRequest}
  16. badQueryResponse = responseStatus{Status: "Unsupported query", StatusCode: http.StatusBadRequest}
  17. )
  18. const (
  19. // Resource name regex
  20. regex = "[a-zA-Z_0-9-]+"
  21. // Router URL variable definition
  22. nwName = "{" + urlNwName + ":" + regex + "}"
  23. nwID = "{" + urlNwID + ":" + regex + "}"
  24. nwPID = "{" + urlNwPID + ":" + regex + "}"
  25. epName = "{" + urlEpName + ":" + regex + "}"
  26. epID = "{" + urlEpID + ":" + regex + "}"
  27. epPID = "{" + urlEpPID + ":" + regex + "}"
  28. cnID = "{" + urlCnID + ":" + regex + "}"
  29. // Internal URL variable name, they can be anything
  30. urlNwName = "network-name"
  31. urlNwID = "network-id"
  32. urlNwPID = "network-partial-id"
  33. urlEpName = "endpoint-name"
  34. urlEpID = "endpoint-id"
  35. urlEpPID = "endpoint-partial-id"
  36. urlCnID = "container-id"
  37. )
  38. // NewHTTPHandler creates and initialize the HTTP handler to serve the requests for libnetwork
  39. func NewHTTPHandler(c libnetwork.NetworkController) func(w http.ResponseWriter, req *http.Request) {
  40. h := &httpHandler{c: c}
  41. h.initRouter()
  42. return h.handleRequest
  43. }
  44. type responseStatus struct {
  45. Status string
  46. StatusCode int
  47. }
  48. func (r *responseStatus) isOK() bool {
  49. return r.StatusCode == http.StatusOK || r.StatusCode == http.StatusCreated
  50. }
  51. type processor func(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus)
  52. type httpHandler struct {
  53. c libnetwork.NetworkController
  54. r *mux.Router
  55. }
  56. func (h *httpHandler) handleRequest(w http.ResponseWriter, req *http.Request) {
  57. // Make sure the service is there
  58. if h.c == nil {
  59. http.Error(w, "NetworkController is not available", http.StatusServiceUnavailable)
  60. return
  61. }
  62. // Get handler from router and execute it
  63. h.r.ServeHTTP(w, req)
  64. }
  65. func (h *httpHandler) initRouter() {
  66. m := map[string][]struct {
  67. url string
  68. qrs []string
  69. fct processor
  70. }{
  71. "GET": {
  72. // Order matters
  73. {"/networks", []string{"name", nwName}, procGetNetworks},
  74. {"/networks", []string{"partial-id", nwPID}, procGetNetworks},
  75. {"/networks", nil, procGetNetworks},
  76. {"/networks/" + nwID, nil, procGetNetwork},
  77. {"/networks/" + nwID + "/endpoints", []string{"name", epName}, procGetEndpoints},
  78. {"/networks/" + nwID + "/endpoints", []string{"partial-id", epPID}, procGetEndpoints},
  79. {"/networks/" + nwID + "/endpoints", nil, procGetEndpoints},
  80. {"/networks/" + nwID + "/endpoints/" + epID, nil, procGetEndpoint},
  81. {"/services", []string{"network", nwName}, procGetServices},
  82. {"/services", []string{"name", epName}, procGetServices},
  83. {"/services", []string{"partial-id", epPID}, procGetServices},
  84. {"/services", nil, procGetServices},
  85. {"/services/" + epID, nil, procGetService},
  86. },
  87. "POST": {
  88. {"/networks", nil, procCreateNetwork},
  89. {"/networks/" + nwID + "/endpoints", nil, procCreateEndpoint},
  90. {"/networks/" + nwID + "/endpoints/" + epID + "/containers", nil, procJoinEndpoint},
  91. {"/services", nil, procPublishService},
  92. {"/services/" + epID + "/backend", nil, procAttachBackend},
  93. },
  94. "DELETE": {
  95. {"/networks/" + nwID, nil, procDeleteNetwork},
  96. {"/networks/" + nwID + "/endpoints/" + epID, nil, procDeleteEndpoint},
  97. {"/networks/" + nwID + "/endpoints/" + epID + "/containers/" + cnID, nil, procLeaveEndpoint},
  98. {"/services/" + epID, nil, procUnpublishService},
  99. {"/services/" + epID + "/backend/" + cnID, nil, procDetachBackend},
  100. },
  101. }
  102. h.r = mux.NewRouter()
  103. for method, routes := range m {
  104. for _, route := range routes {
  105. r := h.r.Path("/{.*}" + route.url).Methods(method).HandlerFunc(makeHandler(h.c, route.fct))
  106. if route.qrs != nil {
  107. r.Queries(route.qrs...)
  108. }
  109. r = h.r.Path(route.url).Methods(method).HandlerFunc(makeHandler(h.c, route.fct))
  110. if route.qrs != nil {
  111. r.Queries(route.qrs...)
  112. }
  113. }
  114. }
  115. }
  116. func makeHandler(ctrl libnetwork.NetworkController, fct processor) http.HandlerFunc {
  117. return func(w http.ResponseWriter, req *http.Request) {
  118. var (
  119. body []byte
  120. err error
  121. )
  122. if req.Body != nil {
  123. body, err = ioutil.ReadAll(req.Body)
  124. if err != nil {
  125. http.Error(w, "Invalid body: "+err.Error(), http.StatusBadRequest)
  126. return
  127. }
  128. }
  129. res, rsp := fct(ctrl, mux.Vars(req), body)
  130. if !rsp.isOK() {
  131. http.Error(w, rsp.Status, rsp.StatusCode)
  132. return
  133. }
  134. if res != nil {
  135. writeJSON(w, rsp.StatusCode, res)
  136. }
  137. }
  138. }
  139. /*****************
  140. Resource Builders
  141. ******************/
  142. func buildNetworkResource(nw libnetwork.Network) *networkResource {
  143. r := &networkResource{}
  144. if nw != nil {
  145. r.Name = nw.Name()
  146. r.ID = nw.ID()
  147. r.Type = nw.Type()
  148. epl := nw.Endpoints()
  149. r.Endpoints = make([]*endpointResource, 0, len(epl))
  150. for _, e := range epl {
  151. epr := buildEndpointResource(e)
  152. r.Endpoints = append(r.Endpoints, epr)
  153. }
  154. }
  155. return r
  156. }
  157. func buildEndpointResource(ep libnetwork.Endpoint) *endpointResource {
  158. r := &endpointResource{}
  159. if ep != nil {
  160. r.Name = ep.Name()
  161. r.ID = ep.ID()
  162. r.Network = ep.Network()
  163. }
  164. return r
  165. }
  166. /****************
  167. Options Parsers
  168. *****************/
  169. func (nc *networkCreate) parseOptions() []libnetwork.NetworkOption {
  170. var setFctList []libnetwork.NetworkOption
  171. if nc.Options != nil {
  172. setFctList = append(setFctList, libnetwork.NetworkOptionGeneric(nc.Options))
  173. }
  174. return setFctList
  175. }
  176. func (ej *endpointJoin) parseOptions() []libnetwork.EndpointOption {
  177. var setFctList []libnetwork.EndpointOption
  178. if ej.HostName != "" {
  179. setFctList = append(setFctList, libnetwork.JoinOptionHostname(ej.HostName))
  180. }
  181. if ej.DomainName != "" {
  182. setFctList = append(setFctList, libnetwork.JoinOptionDomainname(ej.DomainName))
  183. }
  184. if ej.HostsPath != "" {
  185. setFctList = append(setFctList, libnetwork.JoinOptionHostsPath(ej.HostsPath))
  186. }
  187. if ej.ResolvConfPath != "" {
  188. setFctList = append(setFctList, libnetwork.JoinOptionResolvConfPath(ej.ResolvConfPath))
  189. }
  190. if ej.UseDefaultSandbox {
  191. setFctList = append(setFctList, libnetwork.JoinOptionUseDefaultSandbox())
  192. }
  193. if ej.DNS != nil {
  194. for _, d := range ej.DNS {
  195. setFctList = append(setFctList, libnetwork.JoinOptionDNS(d))
  196. }
  197. }
  198. if ej.ExtraHosts != nil {
  199. for _, e := range ej.ExtraHosts {
  200. setFctList = append(setFctList, libnetwork.JoinOptionExtraHost(e.Name, e.Address))
  201. }
  202. }
  203. if ej.ParentUpdates != nil {
  204. for _, p := range ej.ParentUpdates {
  205. setFctList = append(setFctList, libnetwork.JoinOptionParentUpdate(p.EndpointID, p.Name, p.Address))
  206. }
  207. }
  208. return setFctList
  209. }
  210. /******************
  211. Process functions
  212. *******************/
  213. /***************************
  214. NetworkController interface
  215. ****************************/
  216. func procCreateNetwork(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  217. var create networkCreate
  218. err := json.Unmarshal(body, &create)
  219. if err != nil {
  220. return "", &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
  221. }
  222. nw, err := c.NewNetwork(create.NetworkType, create.Name, create.parseOptions()...)
  223. if err != nil {
  224. return "", convertNetworkError(err)
  225. }
  226. return nw.ID(), &createdResponse
  227. }
  228. func procGetNetwork(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  229. t, by := detectNetworkTarget(vars)
  230. nw, errRsp := findNetwork(c, t, by)
  231. if !errRsp.isOK() {
  232. return nil, errRsp
  233. }
  234. return buildNetworkResource(nw), &successResponse
  235. }
  236. func procGetNetworks(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  237. var list []*networkResource
  238. // Look for query filters and validate
  239. name, queryByName := vars[urlNwName]
  240. shortID, queryByPid := vars[urlNwPID]
  241. if queryByName && queryByPid {
  242. return nil, &badQueryResponse
  243. }
  244. if queryByName {
  245. if nw, errRsp := findNetwork(c, name, byName); errRsp.isOK() {
  246. list = append(list, buildNetworkResource(nw))
  247. }
  248. } else if queryByPid {
  249. // Return all the prefix-matching networks
  250. l := func(nw libnetwork.Network) bool {
  251. if strings.HasPrefix(nw.ID(), shortID) {
  252. list = append(list, buildNetworkResource(nw))
  253. }
  254. return false
  255. }
  256. c.WalkNetworks(l)
  257. } else {
  258. for _, nw := range c.Networks() {
  259. list = append(list, buildNetworkResource(nw))
  260. }
  261. }
  262. return list, &successResponse
  263. }
  264. /******************
  265. Network interface
  266. *******************/
  267. func procCreateEndpoint(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  268. var ec endpointCreate
  269. err := json.Unmarshal(body, &ec)
  270. if err != nil {
  271. return "", &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
  272. }
  273. nwT, nwBy := detectNetworkTarget(vars)
  274. n, errRsp := findNetwork(c, nwT, nwBy)
  275. if !errRsp.isOK() {
  276. return "", errRsp
  277. }
  278. var setFctList []libnetwork.EndpointOption
  279. if ec.ExposedPorts != nil {
  280. setFctList = append(setFctList, libnetwork.CreateOptionExposedPorts(ec.ExposedPorts))
  281. }
  282. if ec.PortMapping != nil {
  283. setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(ec.PortMapping))
  284. }
  285. ep, err := n.CreateEndpoint(ec.Name, setFctList...)
  286. if err != nil {
  287. return "", convertNetworkError(err)
  288. }
  289. return ep.ID(), &createdResponse
  290. }
  291. func procGetEndpoint(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  292. nwT, nwBy := detectNetworkTarget(vars)
  293. epT, epBy := detectEndpointTarget(vars)
  294. ep, errRsp := findEndpoint(c, nwT, epT, nwBy, epBy)
  295. if !errRsp.isOK() {
  296. return nil, errRsp
  297. }
  298. return buildEndpointResource(ep), &successResponse
  299. }
  300. func procGetEndpoints(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  301. // Look for query filters and validate
  302. name, queryByName := vars[urlEpName]
  303. shortID, queryByPid := vars[urlEpPID]
  304. if queryByName && queryByPid {
  305. return nil, &badQueryResponse
  306. }
  307. nwT, nwBy := detectNetworkTarget(vars)
  308. nw, errRsp := findNetwork(c, nwT, nwBy)
  309. if !errRsp.isOK() {
  310. return nil, errRsp
  311. }
  312. var list []*endpointResource
  313. // If query parameter is specified, return a filtered collection
  314. if queryByName {
  315. if ep, errRsp := findEndpoint(c, nwT, name, nwBy, byName); errRsp.isOK() {
  316. list = append(list, buildEndpointResource(ep))
  317. }
  318. } else if queryByPid {
  319. // Return all the prefix-matching endpoints
  320. l := func(ep libnetwork.Endpoint) bool {
  321. if strings.HasPrefix(ep.ID(), shortID) {
  322. list = append(list, buildEndpointResource(ep))
  323. }
  324. return false
  325. }
  326. nw.WalkEndpoints(l)
  327. } else {
  328. for _, ep := range nw.Endpoints() {
  329. epr := buildEndpointResource(ep)
  330. list = append(list, epr)
  331. }
  332. }
  333. return list, &successResponse
  334. }
  335. func procDeleteNetwork(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  336. target, by := detectNetworkTarget(vars)
  337. nw, errRsp := findNetwork(c, target, by)
  338. if !errRsp.isOK() {
  339. return nil, errRsp
  340. }
  341. err := nw.Delete()
  342. if err != nil {
  343. return nil, convertNetworkError(err)
  344. }
  345. return nil, &successResponse
  346. }
  347. /******************
  348. Endpoint interface
  349. *******************/
  350. func procJoinEndpoint(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  351. var ej endpointJoin
  352. err := json.Unmarshal(body, &ej)
  353. if err != nil {
  354. return nil, &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
  355. }
  356. nwT, nwBy := detectNetworkTarget(vars)
  357. epT, epBy := detectEndpointTarget(vars)
  358. ep, errRsp := findEndpoint(c, nwT, epT, nwBy, epBy)
  359. if !errRsp.isOK() {
  360. return nil, errRsp
  361. }
  362. err = ep.Join(ej.ContainerID, ej.parseOptions()...)
  363. if err != nil {
  364. return nil, convertNetworkError(err)
  365. }
  366. return ep.Info().SandboxKey(), &successResponse
  367. }
  368. func procLeaveEndpoint(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  369. nwT, nwBy := detectNetworkTarget(vars)
  370. epT, epBy := detectEndpointTarget(vars)
  371. ep, errRsp := findEndpoint(c, nwT, epT, nwBy, epBy)
  372. if !errRsp.isOK() {
  373. return nil, errRsp
  374. }
  375. err := ep.Leave(vars[urlCnID])
  376. if err != nil {
  377. return nil, convertNetworkError(err)
  378. }
  379. return nil, &successResponse
  380. }
  381. func procDeleteEndpoint(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  382. nwT, nwBy := detectNetworkTarget(vars)
  383. epT, epBy := detectEndpointTarget(vars)
  384. ep, errRsp := findEndpoint(c, nwT, epT, nwBy, epBy)
  385. if !errRsp.isOK() {
  386. return nil, errRsp
  387. }
  388. err := ep.Delete()
  389. if err != nil {
  390. return nil, convertNetworkError(err)
  391. }
  392. return nil, &successResponse
  393. }
  394. /******************
  395. Service interface
  396. *******************/
  397. func procGetServices(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  398. // Look for query filters and validate
  399. nwName, filterByNwName := vars[urlNwName]
  400. svName, queryBySvName := vars[urlEpName]
  401. shortID, queryBySvPID := vars[urlEpPID]
  402. if filterByNwName && queryBySvName || filterByNwName && queryBySvPID || queryBySvName && queryBySvPID {
  403. return nil, &badQueryResponse
  404. }
  405. var list []*endpointResource
  406. switch {
  407. case filterByNwName:
  408. // return all service present on the specified network
  409. nw, errRsp := findNetwork(c, nwName, byName)
  410. if !errRsp.isOK() {
  411. return list, &successResponse
  412. }
  413. for _, ep := range nw.Endpoints() {
  414. epr := buildEndpointResource(ep)
  415. list = append(list, epr)
  416. }
  417. case queryBySvName:
  418. // Look in each network for the service with the specified name
  419. l := func(ep libnetwork.Endpoint) bool {
  420. if ep.Name() == svName {
  421. list = append(list, buildEndpointResource(ep))
  422. return true
  423. }
  424. return false
  425. }
  426. for _, nw := range c.Networks() {
  427. nw.WalkEndpoints(l)
  428. }
  429. case queryBySvPID:
  430. // Return all the prefix-matching services
  431. l := func(ep libnetwork.Endpoint) bool {
  432. if strings.HasPrefix(ep.ID(), shortID) {
  433. list = append(list, buildEndpointResource(ep))
  434. }
  435. return false
  436. }
  437. for _, nw := range c.Networks() {
  438. nw.WalkEndpoints(l)
  439. }
  440. default:
  441. for _, nw := range c.Networks() {
  442. for _, ep := range nw.Endpoints() {
  443. epr := buildEndpointResource(ep)
  444. list = append(list, epr)
  445. }
  446. }
  447. }
  448. return list, &successResponse
  449. }
  450. func procGetService(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  451. epT, epBy := detectEndpointTarget(vars)
  452. sv, errRsp := findService(c, epT, epBy)
  453. if !errRsp.isOK() {
  454. return nil, endpointToService(errRsp)
  455. }
  456. return buildEndpointResource(sv), &successResponse
  457. }
  458. func procPublishService(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  459. var sp servicePublish
  460. err := json.Unmarshal(body, &sp)
  461. if err != nil {
  462. return "", &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
  463. }
  464. n, errRsp := findNetwork(c, sp.Network, byName)
  465. if !errRsp.isOK() {
  466. return "", errRsp
  467. }
  468. var setFctList []libnetwork.EndpointOption
  469. if sp.ExposedPorts != nil {
  470. setFctList = append(setFctList, libnetwork.CreateOptionExposedPorts(sp.ExposedPorts))
  471. }
  472. if sp.PortMapping != nil {
  473. setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(sp.PortMapping))
  474. }
  475. ep, err := n.CreateEndpoint(sp.Name, setFctList...)
  476. if err != nil {
  477. return "", endpointToService(convertNetworkError(err))
  478. }
  479. return ep.ID(), &createdResponse
  480. }
  481. func procUnpublishService(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  482. epT, epBy := detectEndpointTarget(vars)
  483. sv, errRsp := findService(c, epT, epBy)
  484. if !errRsp.isOK() {
  485. return nil, errRsp
  486. }
  487. err := sv.Delete()
  488. if err != nil {
  489. return nil, endpointToService(convertNetworkError(err))
  490. }
  491. return nil, &successResponse
  492. }
  493. func procAttachBackend(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  494. var bk endpointJoin
  495. err := json.Unmarshal(body, &bk)
  496. if err != nil {
  497. return nil, &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
  498. }
  499. epT, epBy := detectEndpointTarget(vars)
  500. sv, errRsp := findService(c, epT, epBy)
  501. if !errRsp.isOK() {
  502. return nil, errRsp
  503. }
  504. err = sv.Join(bk.ContainerID, bk.parseOptions()...)
  505. if err != nil {
  506. return nil, convertNetworkError(err)
  507. }
  508. return sv.Info().SandboxKey(), &successResponse
  509. }
  510. func procDetachBackend(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
  511. epT, epBy := detectEndpointTarget(vars)
  512. sv, errRsp := findService(c, epT, epBy)
  513. if !errRsp.isOK() {
  514. return nil, errRsp
  515. }
  516. err := sv.Leave(vars[urlCnID])
  517. if err != nil {
  518. return nil, convertNetworkError(err)
  519. }
  520. return nil, &successResponse
  521. }
  522. /***********
  523. Utilities
  524. ************/
  525. const (
  526. byID = iota
  527. byName
  528. )
  529. func detectNetworkTarget(vars map[string]string) (string, int) {
  530. if target, ok := vars[urlNwName]; ok {
  531. return target, byName
  532. }
  533. if target, ok := vars[urlNwID]; ok {
  534. return target, byID
  535. }
  536. // vars are populated from the URL, following cannot happen
  537. panic("Missing URL variable parameter for network")
  538. }
  539. func detectEndpointTarget(vars map[string]string) (string, int) {
  540. if target, ok := vars[urlEpName]; ok {
  541. return target, byName
  542. }
  543. if target, ok := vars[urlEpID]; ok {
  544. return target, byID
  545. }
  546. // vars are populated from the URL, following cannot happen
  547. panic("Missing URL variable parameter for endpoint")
  548. }
  549. func findNetwork(c libnetwork.NetworkController, s string, by int) (libnetwork.Network, *responseStatus) {
  550. var (
  551. nw libnetwork.Network
  552. err error
  553. )
  554. switch by {
  555. case byID:
  556. nw, err = c.NetworkByID(s)
  557. case byName:
  558. nw, err = c.NetworkByName(s)
  559. default:
  560. panic(fmt.Sprintf("unexpected selector for network search: %d", by))
  561. }
  562. if err != nil {
  563. if _, ok := err.(types.NotFoundError); ok {
  564. return nil, &responseStatus{Status: "Resource not found: Network", StatusCode: http.StatusNotFound}
  565. }
  566. return nil, &responseStatus{Status: err.Error(), StatusCode: http.StatusBadRequest}
  567. }
  568. return nw, &successResponse
  569. }
  570. func findEndpoint(c libnetwork.NetworkController, ns, es string, nwBy, epBy int) (libnetwork.Endpoint, *responseStatus) {
  571. nw, errRsp := findNetwork(c, ns, nwBy)
  572. if !errRsp.isOK() {
  573. return nil, errRsp
  574. }
  575. var (
  576. err error
  577. ep libnetwork.Endpoint
  578. )
  579. switch epBy {
  580. case byID:
  581. ep, err = nw.EndpointByID(es)
  582. case byName:
  583. ep, err = nw.EndpointByName(es)
  584. default:
  585. panic(fmt.Sprintf("unexpected selector for endpoint search: %d", epBy))
  586. }
  587. if err != nil {
  588. if _, ok := err.(types.NotFoundError); ok {
  589. return nil, &responseStatus{Status: "Resource not found: Endpoint", StatusCode: http.StatusNotFound}
  590. }
  591. return nil, &responseStatus{Status: err.Error(), StatusCode: http.StatusBadRequest}
  592. }
  593. return ep, &successResponse
  594. }
  595. func findService(c libnetwork.NetworkController, svs string, svBy int) (libnetwork.Endpoint, *responseStatus) {
  596. for _, nw := range c.Networks() {
  597. var (
  598. ep libnetwork.Endpoint
  599. err error
  600. )
  601. switch svBy {
  602. case byID:
  603. ep, err = nw.EndpointByID(svs)
  604. case byName:
  605. ep, err = nw.EndpointByName(svs)
  606. default:
  607. panic(fmt.Sprintf("unexpected selector for service search: %d", svBy))
  608. }
  609. if err == nil {
  610. return ep, &successResponse
  611. } else if _, ok := err.(types.NotFoundError); !ok {
  612. return nil, convertNetworkError(err)
  613. }
  614. }
  615. return nil, &responseStatus{Status: "Service not found", StatusCode: http.StatusNotFound}
  616. }
  617. func endpointToService(rsp *responseStatus) *responseStatus {
  618. rsp.Status = strings.Replace(rsp.Status, "endpoint", "service", -1)
  619. return rsp
  620. }
  621. func convertNetworkError(err error) *responseStatus {
  622. var code int
  623. switch err.(type) {
  624. case types.BadRequestError:
  625. code = http.StatusBadRequest
  626. case types.ForbiddenError:
  627. code = http.StatusForbidden
  628. case types.NotFoundError:
  629. code = http.StatusNotFound
  630. case types.TimeoutError:
  631. code = http.StatusRequestTimeout
  632. case types.NotImplementedError:
  633. code = http.StatusNotImplemented
  634. case types.NoServiceError:
  635. code = http.StatusServiceUnavailable
  636. case types.InternalError:
  637. code = http.StatusInternalServerError
  638. default:
  639. code = http.StatusInternalServerError
  640. }
  641. return &responseStatus{Status: err.Error(), StatusCode: code}
  642. }
  643. func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
  644. w.Header().Set("Content-Type", "application/json")
  645. w.WriteHeader(code)
  646. return json.NewEncoder(w).Encode(v)
  647. }