porter_app.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. package client
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/porter-dev/porter/api/server/handlers/porter_app"
  6. "github.com/porter-dev/porter/internal/models"
  7. appInternal "github.com/porter-dev/porter/internal/porter_app"
  8. "github.com/porter-dev/porter/api/types"
  9. )
  10. func (c *Client) NewGetPorterApp(
  11. ctx context.Context,
  12. projectID, clusterID uint,
  13. appName string,
  14. ) (*types.PorterApp, error) {
  15. resp := &types.PorterApp{}
  16. err := c.getRequest(
  17. fmt.Sprintf(
  18. "/projects/%d/clusters/%d/applications/%s",
  19. projectID, clusterID, appName,
  20. ),
  21. nil,
  22. resp,
  23. )
  24. return resp, err
  25. }
  26. func (c *Client) NewCreatePorterApp(
  27. ctx context.Context,
  28. projectID, clusterID uint,
  29. appName string,
  30. req *types.CreatePorterAppRequest,
  31. ) (*types.PorterApp, error) {
  32. resp := &types.PorterApp{}
  33. err := c.postRequest(
  34. fmt.Sprintf(
  35. "/projects/%d/clusters/%d/applications/%s",
  36. projectID, clusterID, appName,
  37. ),
  38. req,
  39. resp,
  40. )
  41. return resp, err
  42. }
  43. // NewCreateOrUpdatePorterAppEvent will create a porter app event if one does not exist, or else it will update the existing one if an ID is passed in the object
  44. func (c *Client) NewCreateOrUpdatePorterAppEvent(
  45. ctx context.Context,
  46. projectID, clusterID uint,
  47. appName string,
  48. req *types.CreateOrUpdatePorterAppEventRequest,
  49. ) (types.PorterAppEvent, error) {
  50. resp := &types.PorterAppEvent{}
  51. err := c.postRequest(
  52. fmt.Sprintf(
  53. "/projects/%d/clusters/%d/applications/%s/events",
  54. projectID, clusterID, appName,
  55. ),
  56. req,
  57. resp,
  58. )
  59. return *resp, err
  60. }
  61. // TODO: remove these functions once they are no longer called (check telemetry)
  62. func (c *Client) GetPorterApp(
  63. ctx context.Context,
  64. projectID, clusterID uint,
  65. stackName string,
  66. ) (*types.PorterApp, error) {
  67. resp := &types.PorterApp{}
  68. err := c.getRequest(
  69. fmt.Sprintf(
  70. "/projects/%d/clusters/%d/stacks/%s",
  71. projectID, clusterID, stackName,
  72. ),
  73. nil,
  74. resp,
  75. )
  76. return resp, err
  77. }
  78. func (c *Client) CreatePorterApp(
  79. ctx context.Context,
  80. projectID, clusterID uint,
  81. name string,
  82. req *types.CreatePorterAppRequest,
  83. ) (*types.PorterApp, error) {
  84. resp := &types.PorterApp{}
  85. err := c.postRequest(
  86. fmt.Sprintf(
  87. "/projects/%d/clusters/%d/stacks/%s",
  88. projectID, clusterID, name,
  89. ),
  90. req,
  91. resp,
  92. )
  93. return resp, err
  94. }
  95. // CreateOrUpdatePorterAppEvent will create a porter app event if one does not exist, or else it will update the existing one if an ID is passed in the object
  96. func (c *Client) CreateOrUpdatePorterAppEvent(
  97. ctx context.Context,
  98. projectID, clusterID uint,
  99. name string,
  100. req *types.CreateOrUpdatePorterAppEventRequest,
  101. ) (types.PorterAppEvent, error) {
  102. resp := &types.PorterAppEvent{}
  103. err := c.postRequest(
  104. fmt.Sprintf(
  105. "/projects/%d/clusters/%d/stacks/%s/events",
  106. projectID, clusterID, name,
  107. ),
  108. req,
  109. resp,
  110. )
  111. return *resp, err
  112. }
  113. // ListEnvGroups (List all Env Groups for a given cluster)
  114. func (c *Client) ListEnvGroups(
  115. ctx context.Context,
  116. projectID, clusterID uint,
  117. ) (types.ListEnvironmentGroupsResponse, error) {
  118. resp := &types.ListEnvironmentGroupsResponse{}
  119. err := c.getRequest(
  120. fmt.Sprintf(
  121. "/projects/%d/clusters/%d/environment-groups",
  122. projectID, clusterID,
  123. ),
  124. nil,
  125. resp,
  126. )
  127. return *resp, err
  128. }
  129. // ParseYAML takes in a base64 encoded porter yaml and returns an app proto
  130. func (c *Client) ParseYAML(
  131. ctx context.Context,
  132. projectID, clusterID uint,
  133. b64Yaml string,
  134. appName string,
  135. ) (*porter_app.ParsePorterYAMLToProtoResponse, error) {
  136. resp := &porter_app.ParsePorterYAMLToProtoResponse{}
  137. req := &porter_app.ParsePorterYAMLToProtoRequest{
  138. B64Yaml: b64Yaml,
  139. AppName: appName,
  140. }
  141. err := c.postRequest(
  142. fmt.Sprintf(
  143. "/projects/%d/clusters/%d/apps/parse",
  144. projectID, clusterID,
  145. ),
  146. req,
  147. resp,
  148. )
  149. return resp, err
  150. }
  151. // GetAppManifests returns the manifests for a given app based on the latest successful app revision
  152. func (c *Client) GetAppManifests(
  153. ctx context.Context,
  154. projectID, clusterID uint,
  155. appName string,
  156. ) (*porter_app.AppManifestsResponse, error) {
  157. resp := &porter_app.AppManifestsResponse{}
  158. err := c.getRequest(
  159. fmt.Sprintf(
  160. "/projects/%d/clusters/%d/apps/%s/manifests",
  161. projectID, clusterID, appName,
  162. ),
  163. nil,
  164. resp,
  165. )
  166. return resp, err
  167. }
  168. // ValidatePorterAppInput is the input struct to ValidatePorterApp
  169. type ValidatePorterAppInput struct {
  170. ProjectID uint
  171. ClusterID uint
  172. AppName string
  173. Base64AppProto string
  174. Base64AppOverrides string
  175. DeploymentTarget string
  176. CommitSHA string
  177. }
  178. // ValidatePorterApp takes in a base64 encoded app definition that is potentially partial and returns a complete definition
  179. // using any previous app revisions and defaults
  180. func (c *Client) ValidatePorterApp(
  181. ctx context.Context,
  182. inp ValidatePorterAppInput,
  183. ) (*porter_app.ValidatePorterAppResponse, error) {
  184. resp := &porter_app.ValidatePorterAppResponse{}
  185. req := &porter_app.ValidatePorterAppRequest{
  186. AppName: inp.AppName,
  187. Base64AppProto: inp.Base64AppProto,
  188. Base64AppOverrides: inp.Base64AppOverrides,
  189. DeploymentTargetId: inp.DeploymentTarget,
  190. CommitSHA: inp.CommitSHA,
  191. }
  192. err := c.postRequest(
  193. fmt.Sprintf(
  194. "/projects/%d/clusters/%d/apps/validate",
  195. inp.ProjectID, inp.ClusterID,
  196. ),
  197. req,
  198. resp,
  199. )
  200. return resp, err
  201. }
  202. // ApplyPorterAppInput is the input struct to ApplyPorterApp
  203. type ApplyPorterAppInput struct {
  204. ProjectID uint
  205. ClusterID uint
  206. Base64AppProto string
  207. DeploymentTarget string
  208. AppRevisionID string
  209. ForceBuild bool
  210. Variables map[string]string
  211. Secrets map[string]string
  212. HardEnvUpdate bool
  213. }
  214. // ApplyPorterApp takes in a base64 encoded app definition and applies it to the cluster
  215. func (c *Client) ApplyPorterApp(
  216. ctx context.Context,
  217. inp ApplyPorterAppInput,
  218. ) (*porter_app.ApplyPorterAppResponse, error) {
  219. resp := &porter_app.ApplyPorterAppResponse{}
  220. req := &porter_app.ApplyPorterAppRequest{
  221. Base64AppProto: inp.Base64AppProto,
  222. DeploymentTargetId: inp.DeploymentTarget,
  223. AppRevisionID: inp.AppRevisionID,
  224. ForceBuild: inp.ForceBuild,
  225. Variables: inp.Variables,
  226. Secrets: inp.Secrets,
  227. HardEnvUpdate: inp.HardEnvUpdate,
  228. }
  229. err := c.postRequest(
  230. fmt.Sprintf(
  231. "/projects/%d/clusters/%d/apps/apply",
  232. inp.ProjectID, inp.ClusterID,
  233. ),
  234. req,
  235. resp,
  236. postRequestOpts{
  237. retryCount: 3,
  238. onlyRetry500: true,
  239. },
  240. )
  241. return resp, err
  242. }
  243. // UpdateAppInput is the input struct to UpdateApp
  244. type UpdateAppInput struct {
  245. ProjectID uint
  246. ClusterID uint
  247. Name string
  248. GitSource porter_app.GitSource
  249. DeploymentTargetId string
  250. CommitSHA string
  251. AppRevisionID string
  252. Base64AppProto string
  253. Base64PorterYAML string
  254. IsEnvOverride bool
  255. }
  256. // UpdateApp updates a porter app
  257. func (c *Client) UpdateApp(
  258. ctx context.Context,
  259. inp UpdateAppInput,
  260. ) (*porter_app.UpdateAppResponse, error) {
  261. resp := &porter_app.UpdateAppResponse{}
  262. req := &porter_app.UpdateAppRequest{
  263. Name: inp.Name,
  264. GitSource: inp.GitSource,
  265. DeploymentTargetId: inp.DeploymentTargetId,
  266. CommitSHA: inp.CommitSHA,
  267. AppRevisionID: inp.AppRevisionID,
  268. Base64AppProto: inp.Base64AppProto,
  269. Base64PorterYAML: inp.Base64PorterYAML,
  270. IsEnvOverride: inp.IsEnvOverride,
  271. }
  272. err := c.postRequest(
  273. fmt.Sprintf(
  274. "/projects/%d/clusters/%d/apps/update",
  275. inp.ProjectID, inp.ClusterID,
  276. ),
  277. req,
  278. resp,
  279. )
  280. return resp, err
  281. }
  282. // DefaultDeploymentTarget returns the default deployment target for a given project and cluster
  283. func (c *Client) DefaultDeploymentTarget(
  284. ctx context.Context,
  285. projectID, clusterID uint,
  286. ) (*porter_app.DefaultDeploymentTargetResponse, error) {
  287. resp := &porter_app.DefaultDeploymentTargetResponse{}
  288. req := &porter_app.DefaultDeploymentTargetRequest{}
  289. err := c.getRequest(
  290. fmt.Sprintf(
  291. "/projects/%d/clusters/%d/default-deployment-target",
  292. projectID, clusterID,
  293. ),
  294. req,
  295. resp,
  296. )
  297. return resp, err
  298. }
  299. // CurrentAppRevision returns the currently deployed app revision for a given project, app name and deployment target
  300. func (c *Client) CurrentAppRevision(
  301. ctx context.Context,
  302. projectID uint, clusterID uint,
  303. appName string, deploymentTarget string,
  304. ) (*porter_app.LatestAppRevisionResponse, error) {
  305. resp := &porter_app.LatestAppRevisionResponse{}
  306. req := &porter_app.LatestAppRevisionRequest{
  307. DeploymentTargetID: deploymentTarget,
  308. }
  309. err := c.getRequest(
  310. fmt.Sprintf(
  311. "/projects/%d/clusters/%d/apps/%s/latest",
  312. projectID, clusterID, appName,
  313. ),
  314. req,
  315. resp,
  316. )
  317. return resp, err
  318. }
  319. // CreatePorterAppDBEntryInput is the input struct to CreatePorterAppDBEntry
  320. type CreatePorterAppDBEntryInput struct {
  321. AppName string
  322. GitRepoName string
  323. GitRepoID uint
  324. GitBranch string
  325. ImageRepository string
  326. PorterYamlPath string
  327. ImageTag string
  328. Local bool
  329. DeploymentTargetID string
  330. }
  331. // CreatePorterAppDBEntry creates an entry in the porter app
  332. func (c *Client) CreatePorterAppDBEntry(
  333. ctx context.Context,
  334. projectID uint, clusterID uint,
  335. inp CreatePorterAppDBEntryInput,
  336. ) error {
  337. var sourceType appInternal.SourceType
  338. var image *appInternal.Image
  339. if inp.Local {
  340. sourceType = appInternal.SourceType_Local
  341. }
  342. if inp.GitRepoName != "" {
  343. sourceType = appInternal.SourceType_Github
  344. }
  345. if inp.ImageRepository != "" {
  346. sourceType = appInternal.SourceType_DockerRegistry
  347. image = &appInternal.Image{
  348. Repository: inp.ImageRepository,
  349. Tag: inp.ImageTag,
  350. }
  351. }
  352. req := &porter_app.CreateAppRequest{
  353. Name: inp.AppName,
  354. SourceType: sourceType,
  355. GitSource: porter_app.GitSource{
  356. GitBranch: inp.GitBranch,
  357. GitRepoName: inp.GitRepoName,
  358. GitRepoID: inp.GitRepoID,
  359. },
  360. Image: image,
  361. PorterYamlPath: inp.PorterYamlPath,
  362. DeploymentTargetID: inp.DeploymentTargetID,
  363. }
  364. err := c.postRequest(
  365. fmt.Sprintf(
  366. "/projects/%d/clusters/%d/apps/create",
  367. projectID, clusterID,
  368. ),
  369. req,
  370. &types.PorterApp{},
  371. )
  372. return err
  373. }
  374. // CreateSubdomain returns a subdomain for a given service that point to the ingress-nginx service in the cluster
  375. func (c *Client) CreateSubdomain(
  376. ctx context.Context,
  377. projectID uint, clusterID uint,
  378. appName string, serviceName string,
  379. ) (*porter_app.CreateSubdomainResponse, error) {
  380. resp := &porter_app.CreateSubdomainResponse{}
  381. req := &porter_app.CreateSubdomainRequest{
  382. ServiceName: serviceName,
  383. }
  384. err := c.postRequest(
  385. fmt.Sprintf(
  386. "/projects/%d/clusters/%d/apps/%s/subdomain",
  387. projectID, clusterID, appName,
  388. ),
  389. req,
  390. resp,
  391. )
  392. return resp, err
  393. }
  394. // PredeployStatus checks the current status of a predeploy job for an app revision
  395. func (c *Client) PredeployStatus(
  396. ctx context.Context,
  397. projectID uint, clusterID uint,
  398. appName string, appRevisionId string,
  399. ) (*porter_app.PredeployStatusResponse, error) {
  400. resp := &porter_app.PredeployStatusResponse{}
  401. err := c.getRequest(
  402. fmt.Sprintf(
  403. "/projects/%d/clusters/%d/apps/%s/%s/predeploy-status",
  404. projectID, clusterID, appName, appRevisionId,
  405. ),
  406. nil,
  407. resp,
  408. )
  409. if resp.Status == "" {
  410. return nil, fmt.Errorf("no predeploy status found")
  411. }
  412. return resp, err
  413. }
  414. // GetRevision returns an app revision
  415. func (c *Client) GetRevision(
  416. ctx context.Context,
  417. projectID uint, clusterID uint,
  418. appName string, appRevisionId string,
  419. ) (*porter_app.GetAppRevisionResponse, error) {
  420. resp := &porter_app.GetAppRevisionResponse{}
  421. err := c.getRequest(
  422. fmt.Sprintf(
  423. "/projects/%d/clusters/%d/apps/%s/revisions/%s",
  424. projectID, clusterID, appName, appRevisionId,
  425. ),
  426. nil,
  427. resp,
  428. )
  429. return resp, err
  430. }
  431. // GetRevisionStatus returns the status of an app revision
  432. func (c *Client) GetRevisionStatus(
  433. ctx context.Context,
  434. projectID uint, clusterID uint,
  435. appName string, appRevisionId string,
  436. ) (*porter_app.GetAppRevisionStatusResponse, error) {
  437. resp := &porter_app.GetAppRevisionStatusResponse{}
  438. err := c.getRequest(
  439. fmt.Sprintf(
  440. "/projects/%d/clusters/%d/apps/%s/revisions/%s/status",
  441. projectID, clusterID, appName, appRevisionId,
  442. ),
  443. nil,
  444. resp,
  445. )
  446. return resp, err
  447. }
  448. // UpdateRevisionStatus updates the status of an app revision
  449. func (c *Client) UpdateRevisionStatus(
  450. ctx context.Context,
  451. projectID uint, clusterID uint,
  452. appName string, appRevisionId string,
  453. status models.AppRevisionStatus,
  454. ) (*porter_app.UpdateAppRevisionStatusResponse, error) {
  455. resp := &porter_app.UpdateAppRevisionStatusResponse{}
  456. req := &porter_app.UpdateAppRevisionStatusRequest{
  457. Status: status,
  458. }
  459. err := c.postRequest(
  460. fmt.Sprintf(
  461. "/projects/%d/clusters/%d/apps/%s/revisions/%s",
  462. projectID, clusterID, appName, appRevisionId,
  463. ),
  464. req,
  465. resp,
  466. )
  467. return resp, err
  468. }
  469. // GetBuildEnv returns the build environment for a given app proto
  470. func (c *Client) GetBuildEnv(
  471. ctx context.Context,
  472. projectID uint, clusterID uint,
  473. appName string, appRevisionId string,
  474. ) (*porter_app.GetBuildEnvResponse, error) {
  475. resp := &porter_app.GetBuildEnvResponse{}
  476. err := c.getRequest(
  477. fmt.Sprintf(
  478. "/projects/%d/clusters/%d/apps/%s/revisions/%s/build-env",
  479. projectID, clusterID, appName, appRevisionId,
  480. ),
  481. nil,
  482. resp,
  483. )
  484. return resp, err
  485. }
  486. // GetAppEnvVariables returns all env variables for a given app
  487. func (c *Client) GetAppEnvVariables(
  488. ctx context.Context,
  489. projectID uint, clusterID uint,
  490. appName string,
  491. ) (*porter_app.AppEnvVariablesResponse, error) {
  492. resp := &porter_app.AppEnvVariablesResponse{}
  493. req := &porter_app.AppEnvVariablesRequest{}
  494. err := c.getRequest(
  495. fmt.Sprintf(
  496. "/projects/%d/clusters/%d/apps/%s/env-variables",
  497. projectID, clusterID, appName,
  498. ),
  499. req,
  500. resp,
  501. )
  502. return resp, err
  503. }
  504. // GetBuildFromRevision returns the build environment for a given app proto
  505. func (c *Client) GetBuildFromRevision(
  506. ctx context.Context,
  507. projectID uint, clusterID uint,
  508. appName string, appRevisionId string,
  509. ) (*porter_app.GetBuildFromRevisionResponse, error) {
  510. resp := &porter_app.GetBuildFromRevisionResponse{}
  511. err := c.getRequest(
  512. fmt.Sprintf(
  513. "/projects/%d/clusters/%d/apps/%s/revisions/%s/build",
  514. projectID, clusterID, appName, appRevisionId,
  515. ),
  516. nil,
  517. resp,
  518. )
  519. return resp, err
  520. }
  521. // ReportRevisionStatusInput is the input struct to ReportRevisionStatus
  522. type ReportRevisionStatusInput struct {
  523. ProjectID uint
  524. ClusterID uint
  525. AppName string
  526. AppRevisionID string
  527. PRNumber int
  528. CommitSHA string
  529. }
  530. // ReportRevisionStatus reports the status of an app revision to external services
  531. func (c *Client) ReportRevisionStatus(
  532. ctx context.Context,
  533. inp ReportRevisionStatusInput,
  534. ) (*porter_app.ReportRevisionStatusResponse, error) {
  535. resp := &porter_app.ReportRevisionStatusResponse{}
  536. req := &porter_app.ReportRevisionStatusRequest{
  537. PRNumber: inp.PRNumber,
  538. CommitSHA: inp.CommitSHA,
  539. }
  540. err := c.postRequest(
  541. fmt.Sprintf(
  542. "/projects/%d/clusters/%d/apps/%s/revisions/%s/status",
  543. inp.ProjectID, inp.ClusterID, inp.AppName, inp.AppRevisionID,
  544. ),
  545. req,
  546. resp,
  547. )
  548. return resp, err
  549. }
  550. // CreateOrUpdateAppEnvironment updates the app environment group and creates it if it doesn't exist
  551. func (c *Client) CreateOrUpdateAppEnvironment(
  552. ctx context.Context,
  553. projectID uint, clusterID uint,
  554. appName string,
  555. deploymentTargetID string,
  556. variables map[string]string,
  557. secrets map[string]string,
  558. Base64AppProto string,
  559. ) (*porter_app.UpdateAppEnvironmentResponse, error) {
  560. resp := &porter_app.UpdateAppEnvironmentResponse{}
  561. req := &porter_app.UpdateAppEnvironmentRequest{
  562. DeploymentTargetID: deploymentTargetID,
  563. Variables: variables,
  564. Secrets: secrets,
  565. HardUpdate: false,
  566. Base64AppProto: Base64AppProto,
  567. }
  568. err := c.postRequest(
  569. fmt.Sprintf(
  570. "/projects/%d/clusters/%d/apps/%s/update-environment",
  571. projectID, clusterID, appName,
  572. ),
  573. req,
  574. resp,
  575. )
  576. return resp, err
  577. }
  578. // PorterYamlV2Pods gets all pods for a given deployment target id and app name
  579. func (c *Client) PorterYamlV2Pods(
  580. ctx context.Context,
  581. projectID, clusterID uint,
  582. porterAppName string,
  583. deploymentTargetName string,
  584. ) (*types.GetReleaseAllPodsResponse, error) {
  585. req := &porter_app.PodStatusRequest{
  586. DeploymentTargetName: deploymentTargetName,
  587. }
  588. resp := &types.GetReleaseAllPodsResponse{}
  589. err := c.getRequest(
  590. fmt.Sprintf(
  591. "/projects/%d/clusters/%d/apps/%s/pods",
  592. projectID, clusterID,
  593. porterAppName,
  594. ),
  595. req,
  596. resp,
  597. )
  598. return resp, err
  599. }
  600. // UpdateImage updates the image for a porter app (porter yaml v2 only)
  601. func (c *Client) UpdateImage(
  602. ctx context.Context,
  603. projectID, clusterID uint,
  604. appName, deploymentTargetName, tag string,
  605. ) (*porter_app.UpdateImageResponse, error) {
  606. req := &porter_app.UpdateImageRequest{
  607. Tag: tag,
  608. DeploymentTargetName: deploymentTargetName,
  609. }
  610. resp := &porter_app.UpdateImageResponse{}
  611. err := c.postRequest(
  612. fmt.Sprintf(
  613. "/projects/%d/clusters/%d/apps/%s/update-image",
  614. projectID, clusterID, appName,
  615. ),
  616. &req,
  617. resp,
  618. )
  619. return resp, err
  620. }
  621. // ListAppRevisions lists the last ten app revisions for a given app
  622. func (c *Client) ListAppRevisions(
  623. ctx context.Context,
  624. projectID, clusterID uint,
  625. appName string,
  626. deploymentTargetID string,
  627. ) (*porter_app.ListAppRevisionsResponse, error) {
  628. resp := &porter_app.ListAppRevisionsResponse{}
  629. req := &porter_app.ListAppRevisionsRequest{
  630. DeploymentTargetID: deploymentTargetID,
  631. }
  632. err := c.getRequest(
  633. fmt.Sprintf(
  634. "/projects/%d/clusters/%d/apps/%s/revisions",
  635. projectID, clusterID,
  636. appName,
  637. ),
  638. req,
  639. resp,
  640. )
  641. return resp, err
  642. }
  643. // RollbackRevision reverts an app to a previous revision
  644. func (c *Client) RollbackRevision(
  645. ctx context.Context,
  646. projectID, clusterID uint,
  647. appName string,
  648. deploymentTargetID string,
  649. ) (*porter_app.RollbackAppRevisionResponse, error) {
  650. resp := &porter_app.RollbackAppRevisionResponse{}
  651. req := &porter_app.RollbackAppRevisionRequest{
  652. DeploymentTargetID: deploymentTargetID,
  653. }
  654. err := c.postRequest(
  655. fmt.Sprintf(
  656. "/projects/%d/clusters/%d/apps/%s/rollback",
  657. projectID, clusterID,
  658. appName,
  659. ),
  660. req,
  661. resp,
  662. )
  663. return resp, err
  664. }
  665. // UseNewApplyLogic checks whether the CLI should use the new apply logic
  666. func (c *Client) UseNewApplyLogic(
  667. ctx context.Context,
  668. projectID, clusterID uint,
  669. ) (*porter_app.UseNewApplyLogicResponse, error) {
  670. resp := &porter_app.UseNewApplyLogicResponse{}
  671. req := &porter_app.UseNewApplyLogicRequest{}
  672. err := c.getRequest(
  673. fmt.Sprintf(
  674. "/projects/%d/clusters/%d/apps/use-new-apply-logic",
  675. projectID, clusterID,
  676. ),
  677. req,
  678. resp,
  679. )
  680. return resp, err
  681. }
  682. // RunAppJob runs a job for an app
  683. func (c *Client) RunAppJob(
  684. ctx context.Context,
  685. projectID, clusterID uint,
  686. appName string, jobName string,
  687. deploymentTargetID string,
  688. ) (*porter_app.RunAppJobResponse, error) {
  689. resp := &porter_app.RunAppJobResponse{}
  690. req := &porter_app.RunAppJobRequest{
  691. ServiceName: jobName,
  692. DeploymentTargetID: deploymentTargetID,
  693. }
  694. err := c.postRequest(
  695. fmt.Sprintf(
  696. "/projects/%d/clusters/%d/apps/%s/run",
  697. projectID, clusterID,
  698. appName,
  699. ),
  700. req,
  701. resp,
  702. )
  703. return resp, err
  704. }
  705. // RunAppJobStatusInput contains all the information necessary to check the status of a job
  706. type RunAppJobStatusInput struct {
  707. // AppName is the name of the app associated with the job
  708. AppName string
  709. // Cluster is the id of the cluster against which to retrieve a helm agent for
  710. ClusterID uint
  711. // DeploymentTargetID is the id of the deployment target the job was run against
  712. DeploymentTargetID string
  713. // DeploymentTargetNamespace is the namespace in which the job was deployed
  714. DeploymentTargetNamespace string
  715. // ServiceName is the name of the app service that was triggered
  716. ServiceName string
  717. // JobRunID is the UID returned from the /apps/{porter_app_name}/run endpoint
  718. JobRunID string
  719. // ProjectID is the project in which the cluster exists
  720. ProjectID uint
  721. }
  722. // RunAppJobStatus gets the status for a job app run
  723. func (c *Client) RunAppJobStatus(
  724. ctx context.Context,
  725. input RunAppJobStatusInput,
  726. ) (*porter_app.AppJobRunStatusResponse, error) {
  727. resp := &porter_app.AppJobRunStatusResponse{}
  728. req := &porter_app.AppJobRunStatusRequest{
  729. DeploymentTargetID: input.DeploymentTargetID,
  730. JobRunID: input.JobRunID,
  731. Namespace: input.DeploymentTargetNamespace,
  732. ServiceName: input.ServiceName,
  733. }
  734. err := c.getRequest(
  735. fmt.Sprintf(
  736. "/projects/%d/clusters/%d/apps/%s/run-status",
  737. input.ProjectID, input.ClusterID,
  738. input.AppName,
  739. ),
  740. req,
  741. resp,
  742. )
  743. return resp, err
  744. }