porter_app.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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/api/types"
  7. )
  8. func (c *Client) NewGetPorterApp(
  9. ctx context.Context,
  10. projectID, clusterID uint,
  11. appName string,
  12. ) (*types.PorterApp, error) {
  13. resp := &types.PorterApp{}
  14. err := c.getRequest(
  15. fmt.Sprintf(
  16. "/projects/%d/clusters/%d/applications/%s",
  17. projectID, clusterID, appName,
  18. ),
  19. nil,
  20. resp,
  21. )
  22. return resp, err
  23. }
  24. func (c *Client) NewCreatePorterApp(
  25. ctx context.Context,
  26. projectID, clusterID uint,
  27. appName string,
  28. req *types.CreatePorterAppRequest,
  29. ) (*types.PorterApp, error) {
  30. resp := &types.PorterApp{}
  31. err := c.postRequest(
  32. fmt.Sprintf(
  33. "/projects/%d/clusters/%d/applications/%s",
  34. projectID, clusterID, appName,
  35. ),
  36. req,
  37. resp,
  38. )
  39. return resp, err
  40. }
  41. // 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
  42. func (c *Client) NewCreateOrUpdatePorterAppEvent(
  43. ctx context.Context,
  44. projectID, clusterID uint,
  45. appName string,
  46. req *types.CreateOrUpdatePorterAppEventRequest,
  47. ) (types.PorterAppEvent, error) {
  48. resp := &types.PorterAppEvent{}
  49. err := c.postRequest(
  50. fmt.Sprintf(
  51. "/projects/%d/clusters/%d/applications/%s/events",
  52. projectID, clusterID, appName,
  53. ),
  54. req,
  55. resp,
  56. )
  57. return *resp, err
  58. }
  59. // TODO: remove these functions once they are no longer called (check telemetry)
  60. func (c *Client) GetPorterApp(
  61. ctx context.Context,
  62. projectID, clusterID uint,
  63. stackName string,
  64. ) (*types.PorterApp, error) {
  65. resp := &types.PorterApp{}
  66. err := c.getRequest(
  67. fmt.Sprintf(
  68. "/projects/%d/clusters/%d/stacks/%s",
  69. projectID, clusterID, stackName,
  70. ),
  71. nil,
  72. resp,
  73. )
  74. return resp, err
  75. }
  76. func (c *Client) CreatePorterApp(
  77. ctx context.Context,
  78. projectID, clusterID uint,
  79. name string,
  80. req *types.CreatePorterAppRequest,
  81. ) (*types.PorterApp, error) {
  82. resp := &types.PorterApp{}
  83. err := c.postRequest(
  84. fmt.Sprintf(
  85. "/projects/%d/clusters/%d/stacks/%s",
  86. projectID, clusterID, name,
  87. ),
  88. req,
  89. resp,
  90. )
  91. return resp, err
  92. }
  93. // 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
  94. func (c *Client) CreateOrUpdatePorterAppEvent(
  95. ctx context.Context,
  96. projectID, clusterID uint,
  97. name string,
  98. req *types.CreateOrUpdatePorterAppEventRequest,
  99. ) (types.PorterAppEvent, error) {
  100. resp := &types.PorterAppEvent{}
  101. err := c.postRequest(
  102. fmt.Sprintf(
  103. "/projects/%d/clusters/%d/stacks/%s/events",
  104. projectID, clusterID, name,
  105. ),
  106. req,
  107. resp,
  108. )
  109. return *resp, err
  110. }
  111. // ListEnvGroups (List all Env Groups for a given cluster)
  112. func (c *Client) ListEnvGroups(
  113. ctx context.Context,
  114. projectID, clusterID uint,
  115. ) (types.ListEnvironmentGroupsResponse, error) {
  116. resp := &types.ListEnvironmentGroupsResponse{}
  117. err := c.getRequest(
  118. fmt.Sprintf(
  119. "/projects/%d/clusters/%d/environment-groups",
  120. projectID, clusterID,
  121. ),
  122. nil,
  123. resp,
  124. )
  125. return *resp, err
  126. }
  127. // ParseYAML takes in a base64 encoded porter yaml and returns an app proto
  128. func (c *Client) ParseYAML(
  129. ctx context.Context,
  130. projectID, clusterID uint,
  131. b64Yaml string,
  132. appName string,
  133. ) (*porter_app.ParsePorterYAMLToProtoResponse, error) {
  134. resp := &porter_app.ParsePorterYAMLToProtoResponse{}
  135. req := &porter_app.ParsePorterYAMLToProtoRequest{
  136. B64Yaml: b64Yaml,
  137. AppName: appName,
  138. }
  139. err := c.postRequest(
  140. fmt.Sprintf(
  141. "/projects/%d/clusters/%d/apps/parse",
  142. projectID, clusterID,
  143. ),
  144. req,
  145. resp,
  146. )
  147. return resp, err
  148. }
  149. // ValidatePorterApp takes in a base64 encoded app definition that is potentially partial and returns a complete definition
  150. // using any previous app revisions and defaults
  151. func (c *Client) ValidatePorterApp(
  152. ctx context.Context,
  153. projectID, clusterID uint,
  154. appName string,
  155. base64AppProto string,
  156. deploymentTarget string,
  157. commitSHA string,
  158. ) (*porter_app.ValidatePorterAppResponse, error) {
  159. resp := &porter_app.ValidatePorterAppResponse{}
  160. req := &porter_app.ValidatePorterAppRequest{
  161. AppName: appName,
  162. Base64AppProto: base64AppProto,
  163. DeploymentTargetId: deploymentTarget,
  164. CommitSHA: commitSHA,
  165. }
  166. err := c.postRequest(
  167. fmt.Sprintf(
  168. "/projects/%d/clusters/%d/apps/validate",
  169. projectID, clusterID,
  170. ),
  171. req,
  172. resp,
  173. )
  174. return resp, err
  175. }
  176. // ApplyPorterApp takes in a base64 encoded app definition and applies it to the cluster
  177. func (c *Client) ApplyPorterApp(
  178. ctx context.Context,
  179. projectID, clusterID uint,
  180. base64AppProto string,
  181. deploymentTarget string,
  182. appRevisionID string,
  183. forceBuild bool,
  184. ) (*porter_app.ApplyPorterAppResponse, error) {
  185. resp := &porter_app.ApplyPorterAppResponse{}
  186. req := &porter_app.ApplyPorterAppRequest{
  187. Base64AppProto: base64AppProto,
  188. DeploymentTargetId: deploymentTarget,
  189. AppRevisionID: appRevisionID,
  190. ForceBuild: forceBuild,
  191. }
  192. err := c.postRequest(
  193. fmt.Sprintf(
  194. "/projects/%d/clusters/%d/apps/apply",
  195. projectID, clusterID,
  196. ),
  197. req,
  198. resp,
  199. )
  200. return resp, err
  201. }
  202. // DefaultDeploymentTarget returns the default deployment target for a given project and cluster
  203. func (c *Client) DefaultDeploymentTarget(
  204. ctx context.Context,
  205. projectID, clusterID uint,
  206. ) (*porter_app.DefaultDeploymentTargetResponse, error) {
  207. resp := &porter_app.DefaultDeploymentTargetResponse{}
  208. req := &porter_app.DefaultDeploymentTargetRequest{}
  209. err := c.getRequest(
  210. fmt.Sprintf(
  211. "/projects/%d/clusters/%d/default-deployment-target",
  212. projectID, clusterID,
  213. ),
  214. req,
  215. resp,
  216. )
  217. return resp, err
  218. }
  219. // CurrentAppRevision returns the currently deployed app revision for a given project, app name and deployment target
  220. func (c *Client) CurrentAppRevision(
  221. ctx context.Context,
  222. projectID uint, clusterID uint,
  223. appName string, deploymentTarget string,
  224. ) (*porter_app.LatestAppRevisionResponse, error) {
  225. resp := &porter_app.LatestAppRevisionResponse{}
  226. req := &porter_app.LatestAppRevisionRequest{
  227. DeploymentTargetID: deploymentTarget,
  228. }
  229. err := c.getRequest(
  230. fmt.Sprintf(
  231. "/projects/%d/clusters/%d/apps/%s/latest",
  232. projectID, clusterID, appName,
  233. ),
  234. req,
  235. resp,
  236. )
  237. return resp, err
  238. }
  239. // CreatePorterAppDBEntryInput is the input struct to CreatePorterAppDBEntry
  240. type CreatePorterAppDBEntryInput struct {
  241. AppName string
  242. GitRepoName string
  243. GitRepoID uint
  244. GitBranch string
  245. ImageRepository string
  246. PorterYamlPath string
  247. ImageTag string
  248. Local bool
  249. }
  250. // CreatePorterAppDBEntry creates an entry in the porter app
  251. func (c *Client) CreatePorterAppDBEntry(
  252. ctx context.Context,
  253. projectID uint, clusterID uint,
  254. inp CreatePorterAppDBEntryInput,
  255. ) error {
  256. var sourceType porter_app.SourceType
  257. var image *porter_app.Image
  258. if inp.Local {
  259. sourceType = porter_app.SourceType_Local
  260. }
  261. if inp.GitRepoName != "" {
  262. sourceType = porter_app.SourceType_Github
  263. }
  264. if inp.ImageRepository != "" {
  265. sourceType = porter_app.SourceType_DockerRegistry
  266. image = &porter_app.Image{
  267. Repository: inp.ImageRepository,
  268. Tag: inp.ImageTag,
  269. }
  270. }
  271. if sourceType == "" {
  272. return fmt.Errorf("cannot determine source type")
  273. }
  274. req := &porter_app.CreateAppRequest{
  275. Name: inp.AppName,
  276. SourceType: sourceType,
  277. GitBranch: inp.GitBranch,
  278. GitRepoName: inp.GitRepoName,
  279. GitRepoID: inp.GitRepoID,
  280. PorterYamlPath: inp.PorterYamlPath,
  281. Image: image,
  282. }
  283. err := c.postRequest(
  284. fmt.Sprintf(
  285. "/projects/%d/clusters/%d/apps/create",
  286. projectID, clusterID,
  287. ),
  288. req,
  289. &types.PorterApp{},
  290. )
  291. return err
  292. }
  293. // CreateSubdomain returns a subdomain for a given service that point to the ingress-nginx service in the cluster
  294. func (c *Client) CreateSubdomain(
  295. ctx context.Context,
  296. projectID uint, clusterID uint,
  297. appName string, serviceName string,
  298. ) (*porter_app.CreateSubdomainResponse, error) {
  299. resp := &porter_app.CreateSubdomainResponse{}
  300. req := &porter_app.CreateSubdomainRequest{
  301. ServiceName: serviceName,
  302. }
  303. err := c.postRequest(
  304. fmt.Sprintf(
  305. "/projects/%d/clusters/%d/apps/%s/subdomain",
  306. projectID, clusterID, appName,
  307. ),
  308. req,
  309. resp,
  310. )
  311. return resp, err
  312. }
  313. // PredeployStatus checks the current status of a predeploy job for an app revision
  314. func (c *Client) PredeployStatus(
  315. ctx context.Context,
  316. projectID uint, clusterID uint,
  317. appName string, appRevisionId string,
  318. ) (*porter_app.PredeployStatusResponse, error) {
  319. resp := &porter_app.PredeployStatusResponse{}
  320. err := c.getRequest(
  321. fmt.Sprintf(
  322. "/projects/%d/clusters/%d/apps/%s/%s/predeploy-status",
  323. projectID, clusterID, appName, appRevisionId,
  324. ),
  325. nil,
  326. resp,
  327. )
  328. if resp.Status == "" {
  329. return nil, fmt.Errorf("no predeploy status found")
  330. }
  331. return resp, err
  332. }