porter_app.go 18 KB

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