porter_app.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  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. PatchOperations []v2.PatchOperation
  193. }
  194. // UpdateApp updates a porter app
  195. func (c *Client) UpdateApp(
  196. ctx context.Context,
  197. inp UpdateAppInput,
  198. ) (*porter_app.UpdateAppResponse, error) {
  199. resp := &porter_app.UpdateAppResponse{}
  200. req := &porter_app.UpdateAppRequest{
  201. Name: inp.Name,
  202. GitSource: inp.GitSource,
  203. DeploymentTargetId: inp.DeploymentTargetId,
  204. DeploymentTargetName: inp.DeploymentTargetName,
  205. CommitSHA: inp.CommitSHA,
  206. ImageTagOverride: inp.ImageTagOverride,
  207. AppRevisionID: inp.AppRevisionID,
  208. Base64AppProto: inp.Base64AppProto,
  209. Base64PorterYAML: inp.Base64PorterYAML,
  210. IsEnvOverride: inp.IsEnvOverride,
  211. WithPredeploy: inp.WithPredeploy,
  212. Exact: inp.Exact,
  213. Variables: inp.Variables,
  214. Secrets: inp.Secrets,
  215. Deletions: inp.Deletions,
  216. PatchOperations: inp.PatchOperations,
  217. }
  218. err := c.postRequest(
  219. fmt.Sprintf(
  220. "/projects/%d/clusters/%d/apps/update",
  221. inp.ProjectID, inp.ClusterID,
  222. ),
  223. req,
  224. resp,
  225. )
  226. return resp, err
  227. }
  228. // DefaultDeploymentTarget returns the default deployment target for a given project and cluster
  229. func (c *Client) DefaultDeploymentTarget(
  230. ctx context.Context,
  231. projectID, clusterID uint,
  232. ) (*porter_app.DefaultDeploymentTargetResponse, error) {
  233. resp := &porter_app.DefaultDeploymentTargetResponse{}
  234. req := &porter_app.DefaultDeploymentTargetRequest{}
  235. err := c.getRequest(
  236. fmt.Sprintf(
  237. "/projects/%d/clusters/%d/default-deployment-target",
  238. projectID, clusterID,
  239. ),
  240. req,
  241. resp,
  242. )
  243. return resp, err
  244. }
  245. // CurrentAppRevisionInput is the input struct to CurrentAppRevision
  246. type CurrentAppRevisionInput struct {
  247. ProjectID uint
  248. ClusterID uint
  249. AppName string
  250. // DeploymentTargetName is the name of the deployment target to get the current app revision for. One of this or DeploymentTargetID must be set.
  251. DeploymentTargetName string
  252. // DeploymentTargetID is the id of the deployment target to get the current app revision for. One of this or DeploymentTargetName must be set.
  253. DeploymentTargetID string
  254. }
  255. // CurrentAppRevision returns the currently deployed app revision for a given project, app name and deployment target
  256. func (c *Client) CurrentAppRevision(
  257. ctx context.Context,
  258. input CurrentAppRevisionInput,
  259. ) (*porter_app.LatestAppRevisionResponse, error) {
  260. resp := &porter_app.LatestAppRevisionResponse{}
  261. req := &porter_app.LatestAppRevisionRequest{
  262. DeploymentTargetName: input.DeploymentTargetName,
  263. DeploymentTargetID: input.DeploymentTargetID,
  264. }
  265. err := c.getRequest(
  266. fmt.Sprintf(
  267. "/projects/%d/clusters/%d/apps/%s/latest",
  268. input.ProjectID, input.ClusterID, input.AppName,
  269. ),
  270. req,
  271. resp,
  272. )
  273. return resp, err
  274. }
  275. // CreatePorterAppDBEntryInput is the input struct to CreatePorterAppDBEntry
  276. type CreatePorterAppDBEntryInput struct {
  277. AppName string
  278. GitRepoName string
  279. GitRepoID uint
  280. GitBranch string
  281. ImageRepository string
  282. PorterYamlPath string
  283. ImageTag string
  284. Local bool
  285. DeploymentTargetID string
  286. }
  287. // CreatePorterAppDBEntry creates an entry in the porter app
  288. func (c *Client) CreatePorterAppDBEntry(
  289. ctx context.Context,
  290. projectID uint, clusterID uint,
  291. inp CreatePorterAppDBEntryInput,
  292. ) error {
  293. var sourceType appInternal.SourceType
  294. var image *appInternal.Image
  295. if inp.Local {
  296. sourceType = appInternal.SourceType_Local
  297. }
  298. if inp.GitRepoName != "" {
  299. sourceType = appInternal.SourceType_Github
  300. }
  301. if inp.ImageRepository != "" {
  302. sourceType = appInternal.SourceType_DockerRegistry
  303. image = &appInternal.Image{
  304. Repository: inp.ImageRepository,
  305. Tag: inp.ImageTag,
  306. }
  307. }
  308. req := &porter_app.CreateAppRequest{
  309. Name: inp.AppName,
  310. SourceType: sourceType,
  311. GitSource: porter_app.GitSource{
  312. GitBranch: inp.GitBranch,
  313. GitRepoName: inp.GitRepoName,
  314. GitRepoID: inp.GitRepoID,
  315. },
  316. Image: image,
  317. PorterYamlPath: inp.PorterYamlPath,
  318. DeploymentTargetID: inp.DeploymentTargetID,
  319. }
  320. err := c.postRequest(
  321. fmt.Sprintf(
  322. "/projects/%d/clusters/%d/apps/create",
  323. projectID, clusterID,
  324. ),
  325. req,
  326. &types.PorterApp{},
  327. )
  328. return err
  329. }
  330. // CreateSubdomain returns a subdomain for a given service that point to the ingress-nginx service in the cluster
  331. func (c *Client) CreateSubdomain(
  332. ctx context.Context,
  333. projectID uint, clusterID uint,
  334. appName string, serviceName string,
  335. ) (*porter_app.CreateSubdomainResponse, error) {
  336. resp := &porter_app.CreateSubdomainResponse{}
  337. req := &porter_app.CreateSubdomainRequest{
  338. ServiceName: serviceName,
  339. }
  340. err := c.postRequest(
  341. fmt.Sprintf(
  342. "/projects/%d/clusters/%d/apps/%s/subdomain",
  343. projectID, clusterID, appName,
  344. ),
  345. req,
  346. resp,
  347. )
  348. return resp, err
  349. }
  350. // PredeployStatus checks the current status of a predeploy job for an app revision
  351. func (c *Client) PredeployStatus(
  352. ctx context.Context,
  353. projectID uint, clusterID uint,
  354. appName string, appRevisionId string,
  355. ) (*porter_app.PredeployStatusResponse, error) {
  356. resp := &porter_app.PredeployStatusResponse{}
  357. err := c.getRequest(
  358. fmt.Sprintf(
  359. "/projects/%d/clusters/%d/apps/%s/%s/predeploy-status",
  360. projectID, clusterID, appName, appRevisionId,
  361. ),
  362. nil,
  363. resp,
  364. )
  365. if resp.Status == "" {
  366. return nil, fmt.Errorf("no predeploy status found")
  367. }
  368. return resp, err
  369. }
  370. // GetRevision returns an app revision
  371. func (c *Client) GetRevision(
  372. ctx context.Context,
  373. projectID uint, clusterID uint,
  374. appName string, appRevisionId string,
  375. ) (*porter_app.GetAppRevisionResponse, error) {
  376. resp := &porter_app.GetAppRevisionResponse{}
  377. err := c.getRequest(
  378. fmt.Sprintf(
  379. "/projects/%d/clusters/%d/apps/%s/revisions/%s",
  380. projectID, clusterID, appName, appRevisionId,
  381. ),
  382. nil,
  383. resp,
  384. )
  385. return resp, err
  386. }
  387. // GetRevisionStatus returns the status of an app revision
  388. func (c *Client) GetRevisionStatus(
  389. ctx context.Context,
  390. projectID uint, clusterID uint,
  391. appName string, appRevisionId string,
  392. ) (*porter_app.GetAppRevisionStatusResponse, error) {
  393. resp := &porter_app.GetAppRevisionStatusResponse{}
  394. err := c.getRequest(
  395. fmt.Sprintf(
  396. "/projects/%d/clusters/%d/apps/%s/revisions/%s/status",
  397. projectID, clusterID, appName, appRevisionId,
  398. ),
  399. nil,
  400. resp,
  401. )
  402. return resp, err
  403. }
  404. // UpdateRevisionStatus updates the status of an app revision
  405. func (c *Client) UpdateRevisionStatus(
  406. ctx context.Context,
  407. projectID uint, clusterID uint,
  408. appName string, appRevisionId string,
  409. status models.AppRevisionStatus,
  410. ) (*porter_app.UpdateAppRevisionStatusResponse, error) {
  411. resp := &porter_app.UpdateAppRevisionStatusResponse{}
  412. req := &porter_app.UpdateAppRevisionStatusRequest{
  413. Status: status,
  414. }
  415. err := c.postRequest(
  416. fmt.Sprintf(
  417. "/projects/%d/clusters/%d/apps/%s/revisions/%s",
  418. projectID, clusterID, appName, appRevisionId,
  419. ),
  420. req,
  421. resp,
  422. )
  423. return resp, err
  424. }
  425. // GetBuildEnv returns the build environment for a given app proto
  426. func (c *Client) GetBuildEnv(
  427. ctx context.Context,
  428. projectID uint, clusterID uint,
  429. appName string, appRevisionId string,
  430. ) (*porter_app.GetBuildEnvResponse, error) {
  431. resp := &porter_app.GetBuildEnvResponse{}
  432. err := c.getRequest(
  433. fmt.Sprintf(
  434. "/projects/%d/clusters/%d/apps/%s/revisions/%s/build-env",
  435. projectID, clusterID, appName, appRevisionId,
  436. ),
  437. nil,
  438. resp,
  439. )
  440. return resp, err
  441. }
  442. // GetAppEnvVariables returns all env variables for a given app
  443. func (c *Client) GetAppEnvVariables(
  444. ctx context.Context,
  445. projectID uint, clusterID uint,
  446. appName string,
  447. deploymentTargetName string,
  448. ) (*porter_app.AppEnvVariablesResponse, error) {
  449. resp := &porter_app.AppEnvVariablesResponse{}
  450. req := &porter_app.AppEnvVariablesRequest{
  451. DeploymentTargetName: deploymentTargetName,
  452. }
  453. err := c.getRequest(
  454. fmt.Sprintf(
  455. "/projects/%d/clusters/%d/apps/%s/env-variables",
  456. projectID, clusterID, appName,
  457. ),
  458. req,
  459. resp,
  460. )
  461. return resp, err
  462. }
  463. // GetBuildFromRevisionInput is the input struct to GetBuildFromRevision
  464. type GetBuildFromRevisionInput struct {
  465. ProjectID uint
  466. ClusterID uint
  467. AppName string
  468. AppRevisionID string
  469. PatchOperations []v2.PatchOperation
  470. }
  471. // GetBuildFromRevision returns the build environment for a given app proto
  472. func (c *Client) GetBuildFromRevision(
  473. ctx context.Context,
  474. inp GetBuildFromRevisionInput,
  475. ) (*porter_app.GetBuildFromRevisionResponse, error) {
  476. by, err := json.Marshal(inp.PatchOperations)
  477. if err != nil {
  478. return nil, fmt.Errorf("error marshalling patch operations: %w", err)
  479. }
  480. encoded := base64.StdEncoding.EncodeToString(by)
  481. req := &porter_app.GetBuildFromRevisionRequest{
  482. B64PatchOperations: encoded,
  483. }
  484. resp := &porter_app.GetBuildFromRevisionResponse{}
  485. err = c.getRequest(
  486. fmt.Sprintf(
  487. "/projects/%d/clusters/%d/apps/%s/revisions/%s/build",
  488. inp.ProjectID, inp.ClusterID, inp.AppName, inp.AppRevisionID,
  489. ),
  490. req,
  491. resp,
  492. )
  493. return resp, err
  494. }
  495. // ReportRevisionStatusInput is the input struct to ReportRevisionStatus
  496. type ReportRevisionStatusInput struct {
  497. ProjectID uint
  498. ClusterID uint
  499. AppName string
  500. AppRevisionID string
  501. PRNumber int
  502. CommitSHA string
  503. }
  504. // ReportRevisionStatus reports the status of an app revision to external services
  505. func (c *Client) ReportRevisionStatus(
  506. ctx context.Context,
  507. inp ReportRevisionStatusInput,
  508. ) (*porter_app.ReportRevisionStatusResponse, error) {
  509. resp := &porter_app.ReportRevisionStatusResponse{}
  510. req := &porter_app.ReportRevisionStatusRequest{
  511. PRNumber: inp.PRNumber,
  512. CommitSHA: inp.CommitSHA,
  513. }
  514. err := c.postRequest(
  515. fmt.Sprintf(
  516. "/projects/%d/clusters/%d/apps/%s/revisions/%s/status",
  517. inp.ProjectID, inp.ClusterID, inp.AppName, inp.AppRevisionID,
  518. ),
  519. req,
  520. resp,
  521. )
  522. return resp, err
  523. }
  524. // PorterYamlV2Pods gets all pods for a given deployment target id and app name
  525. func (c *Client) PorterYamlV2Pods(
  526. ctx context.Context,
  527. projectID, clusterID uint,
  528. porterAppName string,
  529. deploymentTargetName string,
  530. ) (*types.GetReleaseAllPodsResponse, error) {
  531. req := &porter_app.PodStatusRequest{
  532. DeploymentTargetName: deploymentTargetName,
  533. }
  534. resp := &types.GetReleaseAllPodsResponse{}
  535. err := c.getRequest(
  536. fmt.Sprintf(
  537. "/projects/%d/clusters/%d/apps/%s/pods",
  538. projectID, clusterID,
  539. porterAppName,
  540. ),
  541. req,
  542. resp,
  543. )
  544. return resp, err
  545. }
  546. // UpdateImage updates the image for a porter app (porter yaml v2 only)
  547. func (c *Client) UpdateImage(
  548. ctx context.Context,
  549. projectID, clusterID uint,
  550. appName, deploymentTargetName, tag string,
  551. ) (*porter_app.UpdateImageResponse, error) {
  552. req := &porter_app.UpdateImageRequest{
  553. Tag: tag,
  554. DeploymentTargetName: deploymentTargetName,
  555. }
  556. resp := &porter_app.UpdateImageResponse{}
  557. err := c.postRequest(
  558. fmt.Sprintf(
  559. "/projects/%d/clusters/%d/apps/%s/update-image",
  560. projectID, clusterID, appName,
  561. ),
  562. &req,
  563. resp,
  564. )
  565. return resp, err
  566. }
  567. // ListAppRevisions lists the last ten app revisions for a given app
  568. func (c *Client) ListAppRevisions(
  569. ctx context.Context,
  570. projectID, clusterID uint,
  571. appName string,
  572. deploymentTargetID string,
  573. ) (*porter_app.ListAppRevisionsResponse, error) {
  574. resp := &porter_app.ListAppRevisionsResponse{}
  575. req := &porter_app.ListAppRevisionsRequest{
  576. DeploymentTargetID: deploymentTargetID,
  577. }
  578. err := c.getRequest(
  579. fmt.Sprintf(
  580. "/projects/%d/clusters/%d/apps/%s/revisions",
  581. projectID, clusterID,
  582. appName,
  583. ),
  584. req,
  585. resp,
  586. )
  587. return resp, err
  588. }
  589. // RollbackRevision reverts an app to a previous revision
  590. func (c *Client) RollbackRevision(
  591. ctx context.Context,
  592. projectID, clusterID uint,
  593. appName string,
  594. deploymentTargetName string,
  595. ) (*porter_app.RollbackAppRevisionResponse, error) {
  596. resp := &porter_app.RollbackAppRevisionResponse{}
  597. req := &porter_app.RollbackAppRevisionRequest{
  598. DeploymentTargetName: deploymentTargetName,
  599. }
  600. err := c.postRequest(
  601. fmt.Sprintf(
  602. "/projects/%d/clusters/%d/apps/%s/rollback",
  603. projectID, clusterID,
  604. appName,
  605. ),
  606. req,
  607. resp,
  608. )
  609. return resp, err
  610. }
  611. // RunAppJob runs a job for an app
  612. func (c *Client) RunAppJob(
  613. ctx context.Context,
  614. projectID, clusterID uint,
  615. appName string, jobName string,
  616. deploymentTargetName string,
  617. ) (*porter_app.RunAppJobResponse, error) {
  618. resp := &porter_app.RunAppJobResponse{}
  619. req := &porter_app.RunAppJobRequest{
  620. ServiceName: jobName,
  621. DeploymentTargetName: deploymentTargetName,
  622. }
  623. err := c.postRequest(
  624. fmt.Sprintf(
  625. "/projects/%d/clusters/%d/apps/%s/run",
  626. projectID, clusterID,
  627. appName,
  628. ),
  629. req,
  630. resp,
  631. )
  632. return resp, err
  633. }
  634. // RunAppJobStatusInput contains all the information necessary to check the status of a job
  635. type RunAppJobStatusInput struct {
  636. // AppName is the name of the app associated with the job
  637. AppName string
  638. // Cluster is the id of the cluster against which to retrieve a helm agent for
  639. ClusterID uint
  640. // DeploymentTargetName is the id of the deployment target the job was run against
  641. DeploymentTargetName string
  642. // ServiceName is the name of the app service that was triggered
  643. ServiceName string
  644. // JobRunID is the UID returned from the /apps/{porter_app_name}/run endpoint
  645. JobRunID string
  646. // ProjectID is the project in which the cluster exists
  647. ProjectID uint
  648. }
  649. // RunAppJobStatus gets the status for a job app run
  650. func (c *Client) RunAppJobStatus(
  651. ctx context.Context,
  652. input RunAppJobStatusInput,
  653. ) (*porter_app.AppJobRunStatusResponse, error) {
  654. resp := &porter_app.AppJobRunStatusResponse{}
  655. req := &porter_app.AppJobRunStatusRequest{
  656. DeploymentTargetName: input.DeploymentTargetName,
  657. JobRunID: input.JobRunID,
  658. ServiceName: input.ServiceName,
  659. }
  660. err := c.getRequest(
  661. fmt.Sprintf(
  662. "/projects/%d/clusters/%d/apps/%s/run-status",
  663. input.ProjectID, input.ClusterID,
  664. input.AppName,
  665. ),
  666. req,
  667. resp,
  668. )
  669. return resp, err
  670. }