agent_handler.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. "secret": map[string]interface{}{
  75. "token": encoded,
  76. },
  77. "config": map[string]interface{}{
  78. "projectID": projID,
  79. "clusterID": releaseForm.Cluster.ID,
  80. "porterHost": app.ServerConf.ServerURL,
  81. },
  82. }
  83. conf := &helm.InstallChartConfig{
  84. Chart: chart,
  85. Name: "porter-agent",
  86. Namespace: releaseForm.Form.Namespace,
  87. Cluster: releaseForm.Cluster,
  88. Repo: *app.Repo,
  89. Values: porterAgentValues,
  90. }
  91. _, err = agent.InstallChart(conf, app.DOConf)
  92. if err != nil {
  93. app.sendExternalError(err, http.StatusInternalServerError, HTTPError{
  94. Code: ErrReleaseDeploy,
  95. Errors: []string{"error installing a new chart: " + err.Error()},
  96. }, w)
  97. return
  98. }
  99. w.WriteHeader(http.StatusOK)
  100. }
  101. // HandleDetectPorterAgentInstalled detects if the agent is installed in the cluster
  102. func (app *App) HandleDetectPorterAgentInstalled(w http.ResponseWriter, r *http.Request) {
  103. vals, err := url.ParseQuery(r.URL.RawQuery)
  104. if err != nil {
  105. app.handleErrorFormDecoding(err, ErrReleaseDecode, w)
  106. return
  107. }
  108. // get the filter options
  109. form := &forms.K8sForm{
  110. OutOfClusterConfig: &kubernetes.OutOfClusterConfig{
  111. Repo: app.Repo,
  112. DigitalOceanOAuth: app.DOConf,
  113. },
  114. }
  115. form.PopulateK8sOptionsFromQueryParams(vals, app.Repo.Cluster)
  116. // validate the form
  117. if err := app.validator.Struct(form); err != nil {
  118. app.handleErrorFormValidation(err, ErrK8sValidate, w)
  119. return
  120. }
  121. // create a new agent
  122. var agent *kubernetes.Agent
  123. if app.ServerConf.IsTesting {
  124. agent = app.TestAgents.K8sAgent
  125. } else {
  126. agent, err = kubernetes.GetAgentOutOfClusterConfig(form.OutOfClusterConfig)
  127. }
  128. // detect prometheus service
  129. porterAgent, err := agent.GetPorterAgent()
  130. if err != nil || porterAgent == nil {
  131. http.NotFound(w, r)
  132. return
  133. }
  134. w.WriteHeader(http.StatusOK)
  135. return
  136. }