porter_app.go 18 KB

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