cluster.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. package router
  2. import (
  3. "fmt"
  4. "github.com/go-chi/chi"
  5. "github.com/porter-dev/porter/api/server/handlers/cluster"
  6. "github.com/porter-dev/porter/api/server/shared"
  7. "github.com/porter-dev/porter/api/server/shared/config"
  8. "github.com/porter-dev/porter/api/types"
  9. )
  10. func NewClusterScopedRegisterer(children ...*Registerer) *Registerer {
  11. return &Registerer{
  12. GetRoutes: GetClusterScopedRoutes,
  13. Children: children,
  14. }
  15. }
  16. func GetClusterScopedRoutes(
  17. r chi.Router,
  18. config *config.Config,
  19. basePath *types.Path,
  20. factory shared.APIEndpointFactory,
  21. children ...*Registerer,
  22. ) []*Route {
  23. routes, projPath := getClusterRoutes(r, config, basePath, factory)
  24. if len(children) > 0 {
  25. r.Route(projPath.RelativePath, func(r chi.Router) {
  26. for _, child := range children {
  27. childRoutes := child.GetRoutes(r, config, basePath, factory, child.Children...)
  28. routes = append(routes, childRoutes...)
  29. }
  30. })
  31. }
  32. return routes
  33. }
  34. func getClusterRoutes(
  35. r chi.Router,
  36. config *config.Config,
  37. basePath *types.Path,
  38. factory shared.APIEndpointFactory,
  39. ) ([]*Route, *types.Path) {
  40. relPath := "/clusters/{cluster_id}"
  41. newPath := &types.Path{
  42. Parent: basePath,
  43. RelativePath: relPath,
  44. }
  45. routes := make([]*Route, 0)
  46. // POST /api/projects/{project_id}/clusters -> project.NewCreateClusterManualHandler
  47. createEndpoint := factory.NewAPIEndpoint(
  48. &types.APIRequestMetadata{
  49. Verb: types.APIVerbCreate,
  50. Method: types.HTTPVerbPost,
  51. Path: &types.Path{
  52. Parent: basePath,
  53. RelativePath: "/clusters",
  54. },
  55. Scopes: []types.PermissionScope{
  56. types.UserScope,
  57. types.ProjectScope,
  58. },
  59. },
  60. )
  61. createHandler := cluster.NewCreateClusterManualHandler(
  62. config,
  63. factory.GetDecoderValidator(),
  64. factory.GetResultWriter(),
  65. )
  66. routes = append(routes, &Route{
  67. Endpoint: createEndpoint,
  68. Handler: createHandler,
  69. Router: r,
  70. })
  71. // POST /api/projects/{project_id}/clusters/candidates -> project.NewCreateClusterCandidateHandler
  72. createCandidateEndpoint := factory.NewAPIEndpoint(
  73. &types.APIRequestMetadata{
  74. Verb: types.APIVerbCreate,
  75. Method: types.HTTPVerbPost,
  76. Path: &types.Path{
  77. Parent: basePath,
  78. RelativePath: "/clusters/candidates",
  79. },
  80. Scopes: []types.PermissionScope{
  81. types.UserScope,
  82. types.ProjectScope,
  83. },
  84. CheckUsage: true,
  85. UsageMetric: types.Clusters,
  86. },
  87. )
  88. createCandidateHandler := cluster.NewCreateClusterCandidateHandler(
  89. config,
  90. factory.GetDecoderValidator(),
  91. factory.GetResultWriter(),
  92. )
  93. routes = append(routes, &Route{
  94. Endpoint: createCandidateEndpoint,
  95. Handler: createCandidateHandler,
  96. Router: r,
  97. })
  98. // GET /api/projects/{project_id}/clusters/candidates -> project.NewListClusterCandidatesHandler
  99. listCandidatesEndpoint := factory.NewAPIEndpoint(
  100. &types.APIRequestMetadata{
  101. Verb: types.APIVerbList,
  102. Method: types.HTTPVerbGet,
  103. Path: &types.Path{
  104. Parent: basePath,
  105. RelativePath: "/clusters/candidates",
  106. },
  107. Scopes: []types.PermissionScope{
  108. types.UserScope,
  109. types.ProjectScope,
  110. },
  111. },
  112. )
  113. listCandidatesHandler := cluster.NewListClusterCandidatesHandler(
  114. config,
  115. factory.GetResultWriter(),
  116. )
  117. routes = append(routes, &Route{
  118. Endpoint: listCandidatesEndpoint,
  119. Handler: listCandidatesHandler,
  120. Router: r,
  121. })
  122. // POST /api/projects/{project_id}/clusters/candidates/{candidate_id}/resolve -> project.NewResolveClusterCandidateHandler
  123. resolveCandidateEndpoint := factory.NewAPIEndpoint(
  124. &types.APIRequestMetadata{
  125. Verb: types.APIVerbCreate,
  126. Method: types.HTTPVerbPost,
  127. Path: &types.Path{
  128. Parent: basePath,
  129. RelativePath: fmt.Sprintf(
  130. "/clusters/candidates/{%s}/resolve",
  131. types.URLParamCandidateID,
  132. ),
  133. },
  134. Scopes: []types.PermissionScope{
  135. types.UserScope,
  136. types.ProjectScope,
  137. },
  138. CheckUsage: true,
  139. UsageMetric: types.Clusters,
  140. },
  141. )
  142. resolveCandidateHandler := cluster.NewResolveClusterCandidateHandler(
  143. config,
  144. factory.GetDecoderValidator(),
  145. factory.GetResultWriter(),
  146. )
  147. routes = append(routes, &Route{
  148. Endpoint: resolveCandidateEndpoint,
  149. Handler: resolveCandidateHandler,
  150. Router: r,
  151. })
  152. // POST /api/projects/{project_id}/clusters/{cluster_id} -> project.NewClusterUpdateHandler
  153. updateClusterEndpoint := factory.NewAPIEndpoint(
  154. &types.APIRequestMetadata{
  155. Verb: types.APIVerbUpdate,
  156. Method: types.HTTPVerbPost,
  157. Path: &types.Path{
  158. Parent: basePath,
  159. RelativePath: relPath,
  160. },
  161. Scopes: []types.PermissionScope{
  162. types.UserScope,
  163. types.ProjectScope,
  164. types.ClusterScope,
  165. },
  166. },
  167. )
  168. updateClusterHandler := cluster.NewClusterUpdateHandler(
  169. config,
  170. factory.GetDecoderValidator(),
  171. factory.GetResultWriter(),
  172. )
  173. routes = append(routes, &Route{
  174. Endpoint: updateClusterEndpoint,
  175. Handler: updateClusterHandler,
  176. Router: r,
  177. })
  178. // DELETE /api/projects/{project_id}/clusters/{cluster_id} -> project.NewClusterDeleteHandler
  179. deleteClusterEndpoint := factory.NewAPIEndpoint(
  180. &types.APIRequestMetadata{
  181. Verb: types.APIVerbDelete,
  182. Method: types.HTTPVerbDelete,
  183. Path: &types.Path{
  184. Parent: basePath,
  185. RelativePath: relPath,
  186. },
  187. Scopes: []types.PermissionScope{
  188. types.UserScope,
  189. types.ProjectScope,
  190. types.ClusterScope,
  191. },
  192. },
  193. )
  194. deleteClusterHandler := cluster.NewClusterDeleteHandler(
  195. config,
  196. factory.GetResultWriter(),
  197. )
  198. routes = append(routes, &Route{
  199. Endpoint: deleteClusterEndpoint,
  200. Handler: deleteClusterHandler,
  201. Router: r,
  202. })
  203. // GET /api/projects/{project_id}/clusters/{cluster_id} -> project.NewClusterGetHandler
  204. getEndpoint := factory.NewAPIEndpoint(
  205. &types.APIRequestMetadata{
  206. Verb: types.APIVerbGet,
  207. Method: types.HTTPVerbGet,
  208. Path: &types.Path{
  209. Parent: basePath,
  210. RelativePath: relPath,
  211. },
  212. Scopes: []types.PermissionScope{
  213. types.UserScope,
  214. types.ProjectScope,
  215. types.ClusterScope,
  216. },
  217. },
  218. )
  219. getHandler := cluster.NewClusterGetHandler(
  220. config,
  221. factory.GetResultWriter(),
  222. )
  223. routes = append(routes, &Route{
  224. Endpoint: getEndpoint,
  225. Handler: getHandler,
  226. Router: r,
  227. })
  228. // GET /api/projects/{project_id}/clusters/{cluster_id}/namespaces -> cluster.NewClusterListNamespacesHandler
  229. listNamespacesEndpoint := factory.NewAPIEndpoint(
  230. &types.APIRequestMetadata{
  231. Verb: types.APIVerbGet,
  232. Method: types.HTTPVerbGet,
  233. Path: &types.Path{
  234. Parent: basePath,
  235. RelativePath: relPath + "/namespaces",
  236. },
  237. Scopes: []types.PermissionScope{
  238. types.UserScope,
  239. types.ProjectScope,
  240. types.ClusterScope,
  241. },
  242. },
  243. )
  244. listNamespacesHandler := cluster.NewListNamespacesHandler(
  245. config,
  246. factory.GetResultWriter(),
  247. )
  248. routes = append(routes, &Route{
  249. Endpoint: listNamespacesEndpoint,
  250. Handler: listNamespacesHandler,
  251. Router: r,
  252. })
  253. // GET /api/projects/{project_id}/clusters/{cluster_id}/nodes -> cluster.NewListNodesHandler
  254. listNodesEndpoint := factory.NewAPIEndpoint(
  255. &types.APIRequestMetadata{
  256. Verb: types.APIVerbGet,
  257. Method: types.HTTPVerbGet,
  258. Path: &types.Path{
  259. Parent: basePath,
  260. RelativePath: relPath + "/nodes",
  261. },
  262. Scopes: []types.PermissionScope{
  263. types.UserScope,
  264. types.ProjectScope,
  265. types.ClusterScope,
  266. },
  267. },
  268. )
  269. listNodesHandler := cluster.NewListNodesHandler(
  270. config,
  271. factory.GetResultWriter(),
  272. )
  273. routes = append(routes, &Route{
  274. Endpoint: listNodesEndpoint,
  275. Handler: listNodesHandler,
  276. Router: r,
  277. })
  278. // GET /api/projects/{project_id}/clusters/{cluster_id}/nodes/{node_name} -> cluster.NewGetNodeHandler
  279. getNodeEndpoint := factory.NewAPIEndpoint(
  280. &types.APIRequestMetadata{
  281. Verb: types.APIVerbGet,
  282. Method: types.HTTPVerbGet,
  283. Path: &types.Path{
  284. Parent: basePath,
  285. RelativePath: fmt.Sprintf("%s/nodes/{%s}", relPath, types.URLParamNodeName),
  286. },
  287. Scopes: []types.PermissionScope{
  288. types.UserScope,
  289. types.ProjectScope,
  290. types.ClusterScope,
  291. },
  292. },
  293. )
  294. getNodeHandler := cluster.NewGetNodeHandler(
  295. config,
  296. factory.GetResultWriter(),
  297. )
  298. routes = append(routes, &Route{
  299. Endpoint: getNodeEndpoint,
  300. Handler: getNodeHandler,
  301. Router: r,
  302. })
  303. // POST /api/projects/{project_id}/clusters/{cluster_id}/namespaces/create -> cluster.NewCreateNamespaceHandler
  304. createNamespaceEndpoint := factory.NewAPIEndpoint(
  305. &types.APIRequestMetadata{
  306. Verb: types.APIVerbCreate,
  307. Method: types.HTTPVerbPost,
  308. Path: &types.Path{
  309. Parent: basePath,
  310. RelativePath: relPath + "/namespaces/create",
  311. },
  312. Scopes: []types.PermissionScope{
  313. types.UserScope,
  314. types.ProjectScope,
  315. types.ClusterScope,
  316. },
  317. },
  318. )
  319. createNamespaceHandler := cluster.NewCreateNamespaceHandler(
  320. config,
  321. factory.GetDecoderValidator(),
  322. factory.GetResultWriter(),
  323. )
  324. routes = append(routes, &Route{
  325. Endpoint: createNamespaceEndpoint,
  326. Handler: createNamespaceHandler,
  327. Router: r,
  328. })
  329. // DELETE /api/projects/{project_id}/clusters/{cluster_id}/namespaces/delete -> cluster.NewDeleteNamespaceHandler
  330. deleteNamespaceEndpoint := factory.NewAPIEndpoint(
  331. &types.APIRequestMetadata{
  332. Verb: types.APIVerbDelete,
  333. Method: types.HTTPVerbDelete,
  334. Path: &types.Path{
  335. Parent: basePath,
  336. RelativePath: relPath + "/namespaces/delete",
  337. },
  338. Scopes: []types.PermissionScope{
  339. types.UserScope,
  340. types.ProjectScope,
  341. types.ClusterScope,
  342. },
  343. },
  344. )
  345. deleteNamespaceHandler := cluster.NewDeleteNamespaceHandler(
  346. config,
  347. factory.GetDecoderValidator(),
  348. )
  349. routes = append(routes, &Route{
  350. Endpoint: deleteNamespaceEndpoint,
  351. Handler: deleteNamespaceHandler,
  352. Router: r,
  353. })
  354. // GET /api/projects/{project_id}/clusters/{cluster_id}/kubeconfig -> cluster.NewGetTemporaryKubeconfigHandler
  355. getTemporaryKubeconfigEndpoint := factory.NewAPIEndpoint(
  356. &types.APIRequestMetadata{
  357. Verb: types.APIVerbGet,
  358. Method: types.HTTPVerbGet,
  359. Path: &types.Path{
  360. Parent: basePath,
  361. RelativePath: relPath + "/kubeconfig",
  362. },
  363. Scopes: []types.PermissionScope{
  364. types.UserScope,
  365. types.ProjectScope,
  366. types.ClusterScope,
  367. },
  368. },
  369. )
  370. getTemporaryKubeconfigHandler := cluster.NewGetTemporaryKubeconfigHandler(
  371. config,
  372. factory.GetResultWriter(),
  373. )
  374. routes = append(routes, &Route{
  375. Endpoint: getTemporaryKubeconfigEndpoint,
  376. Handler: getTemporaryKubeconfigHandler,
  377. Router: r,
  378. })
  379. // GET /api/projects/{project_id}/clusters/{cluster_id}/prometheus/detect -> cluster.NewDetectPrometheusInstalledHandler
  380. detectPrometheusInstalledEndpoint := factory.NewAPIEndpoint(
  381. &types.APIRequestMetadata{
  382. Verb: types.APIVerbGet,
  383. Method: types.HTTPVerbGet,
  384. Path: &types.Path{
  385. Parent: basePath,
  386. RelativePath: relPath + "/prometheus/detect",
  387. },
  388. Scopes: []types.PermissionScope{
  389. types.UserScope,
  390. types.ProjectScope,
  391. types.ClusterScope,
  392. },
  393. },
  394. )
  395. detectPrometheusInstalledHandler := cluster.NewDetectPrometheusInstalledHandler(config)
  396. routes = append(routes, &Route{
  397. Endpoint: detectPrometheusInstalledEndpoint,
  398. Handler: detectPrometheusInstalledHandler,
  399. Router: r,
  400. })
  401. // GET /api/projects/{project_id}/clusters/{cluster_id}/prometheus/ingresses -> cluster.NewListNGINXIngressesHandler
  402. listNGINXIngressesEndpoint := factory.NewAPIEndpoint(
  403. &types.APIRequestMetadata{
  404. Verb: types.APIVerbGet,
  405. Method: types.HTTPVerbGet,
  406. Path: &types.Path{
  407. Parent: basePath,
  408. RelativePath: relPath + "/prometheus/ingresses",
  409. },
  410. Scopes: []types.PermissionScope{
  411. types.UserScope,
  412. types.ProjectScope,
  413. types.ClusterScope,
  414. },
  415. },
  416. )
  417. listNGINXIngressesHandler := cluster.NewListNGINXIngressesHandler(
  418. config,
  419. factory.GetResultWriter(),
  420. )
  421. routes = append(routes, &Route{
  422. Endpoint: listNGINXIngressesEndpoint,
  423. Handler: listNGINXIngressesHandler,
  424. Router: r,
  425. })
  426. // GET /api/projects/{project_id}/clusters/{cluster_id}/metrics -> cluster.NewGetPodMetricsHandler
  427. getPodMetricsEndpoint := factory.NewAPIEndpoint(
  428. &types.APIRequestMetadata{
  429. Verb: types.APIVerbGet,
  430. Method: types.HTTPVerbGet,
  431. Path: &types.Path{
  432. Parent: basePath,
  433. RelativePath: relPath + "/metrics",
  434. },
  435. Scopes: []types.PermissionScope{
  436. types.UserScope,
  437. types.ProjectScope,
  438. types.ClusterScope,
  439. },
  440. },
  441. )
  442. getPodMetricsHandler := cluster.NewGetPodMetricsHandler(
  443. config,
  444. factory.GetDecoderValidator(),
  445. factory.GetResultWriter(),
  446. )
  447. routes = append(routes, &Route{
  448. Endpoint: getPodMetricsEndpoint,
  449. Handler: getPodMetricsHandler,
  450. Router: r,
  451. })
  452. // GET /api/projects/{project_id}/clusters/{cluster_id}/helm_release -> cluster.NewStreamHelmReleaseHandler
  453. streamHelmReleaseEndpoint := factory.NewAPIEndpoint(
  454. &types.APIRequestMetadata{
  455. Verb: types.APIVerbGet,
  456. Method: types.HTTPVerbGet,
  457. Path: &types.Path{
  458. Parent: basePath,
  459. RelativePath: relPath + "/helm_release",
  460. },
  461. Scopes: []types.PermissionScope{
  462. types.UserScope,
  463. types.ProjectScope,
  464. types.ClusterScope,
  465. },
  466. IsWebsocket: true,
  467. },
  468. )
  469. streamHelmReleaseHandler := cluster.NewStreamHelmReleaseHandler(
  470. config,
  471. factory.GetDecoderValidator(),
  472. factory.GetResultWriter(),
  473. )
  474. routes = append(routes, &Route{
  475. Endpoint: streamHelmReleaseEndpoint,
  476. Handler: streamHelmReleaseHandler,
  477. Router: r,
  478. })
  479. // GET /api/projects/{project_id}/clusters/{cluster_id}/{kind}/status -> cluster.NewStreamStatusHandler
  480. streamStatusEndpoint := factory.NewAPIEndpoint(
  481. &types.APIRequestMetadata{
  482. Verb: types.APIVerbGet,
  483. Method: types.HTTPVerbGet,
  484. Path: &types.Path{
  485. Parent: basePath,
  486. RelativePath: fmt.Sprintf(
  487. "%s/{%s}/status",
  488. relPath,
  489. types.URLParamKind,
  490. ),
  491. },
  492. Scopes: []types.PermissionScope{
  493. types.UserScope,
  494. types.ProjectScope,
  495. types.ClusterScope,
  496. },
  497. IsWebsocket: true,
  498. },
  499. )
  500. streamStatusHandler := cluster.NewStreamStatusHandler(
  501. config,
  502. factory.GetDecoderValidator(),
  503. factory.GetResultWriter(),
  504. )
  505. routes = append(routes, &Route{
  506. Endpoint: streamStatusEndpoint,
  507. Handler: streamStatusHandler,
  508. Router: r,
  509. })
  510. // GET /api/projects/{project_id}/clusters/{cluster_id}/pods -> cluster.NewGetPodsHandler
  511. getPodsEndpoint := factory.NewAPIEndpoint(
  512. &types.APIRequestMetadata{
  513. Verb: types.APIVerbGet,
  514. Method: types.HTTPVerbGet,
  515. Path: &types.Path{
  516. Parent: basePath,
  517. RelativePath: relPath + "/pods",
  518. },
  519. Scopes: []types.PermissionScope{
  520. types.UserScope,
  521. types.ProjectScope,
  522. types.ClusterScope,
  523. },
  524. },
  525. )
  526. getPodsHandler := cluster.NewGetPodsHandler(
  527. config,
  528. factory.GetDecoderValidator(),
  529. factory.GetResultWriter(),
  530. )
  531. routes = append(routes, &Route{
  532. Endpoint: getPodsEndpoint,
  533. Handler: getPodsHandler,
  534. Router: r,
  535. })
  536. return routes, newPath
  537. }