porter_app.go 8.5 KB

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