porter_app.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. ) (*porter_app.ApplyPorterAppResponse, error) {
  184. resp := &porter_app.ApplyPorterAppResponse{}
  185. req := &porter_app.ApplyPorterAppRequest{
  186. Base64AppProto: base64AppProto,
  187. DeploymentTargetId: deploymentTarget,
  188. AppRevisionID: appRevisionID,
  189. }
  190. err := c.postRequest(
  191. fmt.Sprintf(
  192. "/projects/%d/clusters/%d/apps/apply",
  193. projectID, clusterID,
  194. ),
  195. req,
  196. resp,
  197. )
  198. return resp, err
  199. }
  200. // DefaultDeploymentTarget returns the default deployment target for a given project and cluster
  201. func (c *Client) DefaultDeploymentTarget(
  202. ctx context.Context,
  203. projectID, clusterID uint,
  204. ) (*porter_app.DefaultDeploymentTargetResponse, error) {
  205. resp := &porter_app.DefaultDeploymentTargetResponse{}
  206. req := &porter_app.DefaultDeploymentTargetRequest{}
  207. err := c.getRequest(
  208. fmt.Sprintf(
  209. "/projects/%d/clusters/%d/default-deployment-target",
  210. projectID, clusterID,
  211. ),
  212. req,
  213. resp,
  214. )
  215. return resp, err
  216. }
  217. // CurrentAppRevision returns the currently deployed app revision for a given project, app name and deployment target
  218. func (c *Client) CurrentAppRevision(
  219. ctx context.Context,
  220. projectID uint, clusterID uint,
  221. appName string, deploymentTarget string,
  222. ) (*porter_app.LatestAppRevisionResponse, error) {
  223. resp := &porter_app.LatestAppRevisionResponse{}
  224. req := &porter_app.LatestAppRevisionRequest{
  225. DeploymentTargetID: deploymentTarget,
  226. }
  227. err := c.getRequest(
  228. fmt.Sprintf(
  229. "/projects/%d/clusters/%d/apps/%s/latest",
  230. projectID, clusterID, appName,
  231. ),
  232. req,
  233. resp,
  234. )
  235. return resp, err
  236. }
  237. // CreatePorterAppDBEntryInput is the input struct to CreatePorterAppDBEntry
  238. type CreatePorterAppDBEntryInput struct {
  239. AppName string
  240. GitRepoName string
  241. GitRepoID uint
  242. GitBranch string
  243. ImageRepository string
  244. PorterYamlPath string
  245. ImageTag string
  246. Local bool
  247. }
  248. // CreatePorterAppDBEntry creates an entry in the porter app
  249. func (c *Client) CreatePorterAppDBEntry(
  250. ctx context.Context,
  251. projectID uint, clusterID uint,
  252. inp CreatePorterAppDBEntryInput,
  253. ) error {
  254. var sourceType porter_app.SourceType
  255. var image *porter_app.Image
  256. if inp.Local {
  257. sourceType = porter_app.SourceType_Local
  258. }
  259. if inp.GitRepoName != "" {
  260. sourceType = porter_app.SourceType_Github
  261. }
  262. if inp.ImageRepository != "" {
  263. sourceType = porter_app.SourceType_DockerRegistry
  264. image = &porter_app.Image{
  265. Repository: inp.ImageRepository,
  266. Tag: inp.ImageTag,
  267. }
  268. }
  269. if sourceType == "" {
  270. return fmt.Errorf("cannot determine source type")
  271. }
  272. req := &porter_app.CreateAppRequest{
  273. Name: inp.AppName,
  274. SourceType: sourceType,
  275. GitBranch: inp.GitBranch,
  276. GitRepoName: inp.GitRepoName,
  277. GitRepoID: inp.GitRepoID,
  278. PorterYamlPath: inp.PorterYamlPath,
  279. Image: image,
  280. }
  281. err := c.postRequest(
  282. fmt.Sprintf(
  283. "/projects/%d/clusters/%d/apps/create",
  284. projectID, clusterID,
  285. ),
  286. req,
  287. &types.PorterApp{},
  288. )
  289. return err
  290. }
  291. // CreateSubdomain returns a subdomain for a given service that point to the ingress-nginx service in the cluster
  292. func (c *Client) CreateSubdomain(
  293. ctx context.Context,
  294. projectID uint, clusterID uint,
  295. appName string, serviceName string,
  296. ) (*porter_app.CreateSubdomainResponse, error) {
  297. resp := &porter_app.CreateSubdomainResponse{}
  298. req := &porter_app.CreateSubdomainRequest{
  299. ServiceName: serviceName,
  300. }
  301. err := c.postRequest(
  302. fmt.Sprintf(
  303. "/projects/%d/clusters/%d/apps/%s/subdomain",
  304. projectID, clusterID, appName,
  305. ),
  306. req,
  307. resp,
  308. )
  309. return resp, err
  310. }
  311. // PredeployStatus checks the current status of a predeploy job for an app revision
  312. func (c *Client) PredeployStatus(
  313. ctx context.Context,
  314. projectID uint, clusterID uint,
  315. appName string, appRevisionId string,
  316. ) (*porter_app.PredeployStatusResponse, error) {
  317. resp := &porter_app.PredeployStatusResponse{}
  318. err := c.getRequest(
  319. fmt.Sprintf(
  320. "/projects/%d/clusters/%d/apps/%s/%s/predeploy-status",
  321. projectID, clusterID, appName, appRevisionId,
  322. ),
  323. nil,
  324. resp,
  325. )
  326. if resp.Status == "" {
  327. return nil, fmt.Errorf("no predeploy status found")
  328. }
  329. return resp, err
  330. }