2
0

get_cluster_info.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package aws
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "github.com/aws/aws-sdk-go/aws"
  8. "github.com/aws/aws-sdk-go/service/ec2"
  9. "github.com/aws/aws-sdk-go/service/eks"
  10. "github.com/porter-dev/porter/api/server/handlers"
  11. "github.com/porter-dev/porter/api/server/shared"
  12. "github.com/porter-dev/porter/api/server/shared/apierrors"
  13. "github.com/porter-dev/porter/api/server/shared/config"
  14. "github.com/porter-dev/porter/api/types"
  15. "github.com/porter-dev/porter/internal/models"
  16. "gorm.io/gorm"
  17. )
  18. type GetClusterInfoHandler struct {
  19. handlers.PorterHandlerReadWriter
  20. }
  21. func NewGetClusterInfoHandler(
  22. config *config.Config,
  23. decoderValidator shared.RequestDecoderValidator,
  24. writer shared.ResultWriter,
  25. ) *GetClusterInfoHandler {
  26. return &GetClusterInfoHandler{
  27. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  28. }
  29. }
  30. func (c *GetClusterInfoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  31. proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  32. cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
  33. if cluster.AWSIntegrationID == 0 {
  34. c.HandleAPIError(w, r, apierrors.NewErrForbidden(fmt.Errorf("no AWS cluster found with cluster ID: %d", cluster.ID)))
  35. return
  36. }
  37. awsInt, err := c.Repo().AWSIntegration().ReadAWSIntegration(proj.ID, cluster.AWSIntegrationID)
  38. if err != nil {
  39. if errors.Is(err, gorm.ErrRecordNotFound) {
  40. c.HandleAPIError(w, r, apierrors.NewErrNotFound(fmt.Errorf("no AWS integration found with project ID: %d and "+
  41. "integration ID: %d", proj.ID, cluster.AWSIntegrationID)))
  42. return
  43. }
  44. c.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("error fetching AWS integration with project ID: %d and "+
  45. "integration ID: %d. Error: %w", proj.ID, cluster.AWSIntegrationID, err)))
  46. return
  47. }
  48. awsSession, err := awsInt.GetSession()
  49. if err != nil {
  50. c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(fmt.Errorf("error fetching new session for AWS with "+
  51. "project ID: %d and integration ID: %d. Error: %w", proj.ID, cluster.AWSIntegrationID, err), http.StatusConflict))
  52. return
  53. }
  54. clusterName := cluster.Name
  55. if strings.HasPrefix(clusterName, "arn:aws:eks:") {
  56. parts := strings.Split(clusterName, "/")
  57. clusterName = parts[len(parts)-1]
  58. }
  59. awsConf := aws.NewConfig()
  60. if awsInt.AWSRegion != "" {
  61. awsConf = awsConf.WithRegion(awsInt.AWSRegion)
  62. }
  63. eksSvc := eks.New(awsSession, awsConf)
  64. clusterInfo, err := eksSvc.DescribeCluster(&eks.DescribeClusterInput{
  65. Name: &clusterName,
  66. })
  67. if err != nil || clusterInfo.Cluster == nil {
  68. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  69. return
  70. }
  71. ec2Svc := ec2.New(awsSession, awsConf)
  72. res := &types.GetAWSClusterInfoResponse{
  73. Name: clusterName,
  74. ARN: *clusterInfo.Cluster.Arn,
  75. Status: *clusterInfo.Cluster.Status,
  76. K8sVersion: *clusterInfo.Cluster.Version,
  77. EKSVersion: *clusterInfo.Cluster.PlatformVersion,
  78. }
  79. err = ec2Svc.DescribeSubnetsPages(&ec2.DescribeSubnetsInput{
  80. Filters: []*ec2.Filter{
  81. {
  82. Name: aws.String("vpc-id"),
  83. Values: []*string{
  84. clusterInfo.Cluster.ResourcesVpcConfig.VpcId,
  85. },
  86. },
  87. },
  88. }, func(page *ec2.DescribeSubnetsOutput, lastPage bool) bool {
  89. if page == nil {
  90. return false
  91. }
  92. for _, subnet := range page.Subnets {
  93. res.Subnets = append(res.Subnets, &types.AWSSubnet{
  94. SubnetID: *subnet.SubnetId,
  95. AvailabilityZone: *subnet.AvailabilityZone,
  96. AvailableIPAddressCount: *subnet.AvailableIpAddressCount,
  97. })
  98. }
  99. return !lastPage
  100. })
  101. if err != nil {
  102. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  103. return
  104. }
  105. c.WriteResult(w, r, res)
  106. }