agent_handler.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package api
  2. import (
  3. "net/http"
  4. "net/url"
  5. "strconv"
  6. "github.com/go-chi/chi"
  7. "github.com/porter-dev/porter/internal/auth/token"
  8. "github.com/porter-dev/porter/internal/forms"
  9. "github.com/porter-dev/porter/internal/helm"
  10. "github.com/porter-dev/porter/internal/helm/loader"
  11. "github.com/porter-dev/porter/internal/kubernetes"
  12. )
  13. // HandleDeployAgent deploys the agent in the Porter cluster
  14. func (app *App) HandleDeployAgent(w http.ResponseWriter, r *http.Request) {
  15. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  16. if err != nil || projID == 0 {
  17. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  18. return
  19. }
  20. chart, err := loader.LoadChartPublic(
  21. app.ServerConf.DefaultAddonHelmRepoURL,
  22. "porter-agent",
  23. "latest",
  24. )
  25. if err != nil {
  26. app.handleErrorFormDecoding(err, ErrReleaseDecode, w)
  27. return
  28. }
  29. vals, err := url.ParseQuery(r.URL.RawQuery)
  30. if err != nil {
  31. app.handleErrorFormDecoding(err, ErrReleaseDecode, w)
  32. return
  33. }
  34. releaseForm := &forms.ReleaseForm{
  35. Form: &helm.Form{
  36. Repo: app.Repo,
  37. DigitalOceanOAuth: app.DOConf,
  38. },
  39. }
  40. releaseForm.PopulateHelmOptionsFromQueryParams(
  41. vals,
  42. app.Repo.Cluster,
  43. )
  44. agent, err := app.getAgentFromReleaseForm(
  45. w,
  46. r,
  47. releaseForm,
  48. )
  49. if err != nil {
  50. app.handleErrorFormDecoding(err, ErrUserDecode, w)
  51. return
  52. }
  53. // create namespace if not exists
  54. _, err = agent.K8sAgent.CreateNamespace("porter")
  55. if err != nil {
  56. app.handleErrorFormDecoding(err, ErrUserDecode, w)
  57. return
  58. }
  59. // add api token to values
  60. userID, err := app.getUserIDFromRequest(r)
  61. if err != nil {
  62. app.handleErrorFormDecoding(err, ErrUserDecode, w)
  63. return
  64. }
  65. jwt, _ := token.GetTokenForAPI(userID, uint(projID))
  66. encoded, err := jwt.EncodeToken(&token.TokenGeneratorConf{
  67. TokenSecret: app.ServerConf.TokenGeneratorSecret,
  68. })
  69. if err != nil {
  70. app.handleErrorInternal(err, w)
  71. return
  72. }
  73. porterAgentValues := map[string]interface{}{
  74. "config": map[string]interface{}{
  75. "token": encoded,
  76. "projectID": projID,
  77. "clusterID": releaseForm.Cluster.ID,
  78. },
  79. }
  80. conf := &helm.InstallChartConfig{
  81. Chart: chart,
  82. Name: "porter-agent",
  83. Namespace: releaseForm.Form.Namespace,
  84. Cluster: releaseForm.Cluster,
  85. Repo: *app.Repo,
  86. Values: porterAgentValues,
  87. }
  88. _, err = agent.InstallChart(conf, app.DOConf)
  89. if err != nil {
  90. app.sendExternalError(err, http.StatusInternalServerError, HTTPError{
  91. Code: ErrReleaseDeploy,
  92. Errors: []string{"error installing a new chart: " + err.Error()},
  93. }, w)
  94. return
  95. }
  96. w.WriteHeader(http.StatusOK)
  97. }
  98. // HandleDetectPorterAgentInstalled detects if the agent is installed in the cluster
  99. func (app *App) HandleDetectPorterAgentInstalled(w http.ResponseWriter, r *http.Request) {
  100. vals, err := url.ParseQuery(r.URL.RawQuery)
  101. if err != nil {
  102. app.handleErrorFormDecoding(err, ErrReleaseDecode, w)
  103. return
  104. }
  105. // get the filter options
  106. form := &forms.K8sForm{
  107. OutOfClusterConfig: &kubernetes.OutOfClusterConfig{
  108. Repo: app.Repo,
  109. DigitalOceanOAuth: app.DOConf,
  110. },
  111. }
  112. form.PopulateK8sOptionsFromQueryParams(vals, app.Repo.Cluster)
  113. // validate the form
  114. if err := app.validator.Struct(form); err != nil {
  115. app.handleErrorFormValidation(err, ErrK8sValidate, w)
  116. return
  117. }
  118. // create a new agent
  119. var agent *kubernetes.Agent
  120. if app.ServerConf.IsTesting {
  121. agent = app.TestAgents.K8sAgent
  122. } else {
  123. agent, err = kubernetes.GetAgentOutOfClusterConfig(form.OutOfClusterConfig)
  124. }
  125. // detect prometheus service
  126. porterAgent, err := agent.GetPorterAgent()
  127. if err != nil || porterAgent == nil {
  128. http.NotFound(w, r)
  129. return
  130. }
  131. w.WriteHeader(http.StatusOK)
  132. return
  133. }