github.com/jenkins-x/jx/v2@v2.1.155/pkg/cloud/amazon/session/common.go (about) 1 package session 2 3 import ( 4 "os" 5 "regexp" 6 "runtime" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/aws/session" 10 "github.com/aws/aws-sdk-go/service/eks" 11 "github.com/jenkins-x/jx/v2/pkg/kube" 12 "github.com/pkg/errors" 13 ) 14 15 const DefaultRegion = "us-west-2" 16 17 func NewAwsSession(profileOption string, regionOption string) (*session.Session, error) { 18 config := aws.Config{} 19 if regionOption != "" { 20 config.Region = aws.String(regionOption) 21 } 22 23 sessionOptions := session.Options{ 24 SharedConfigState: session.SharedConfigEnable, 25 Config: config, 26 } 27 28 if profileOption != "" { 29 sessionOptions.Profile = profileOption 30 } 31 32 awsSession, err := session.NewSessionWithOptions(sessionOptions) 33 if err != nil { 34 return nil, err 35 } 36 37 if *awsSession.Config.Region == "" { 38 awsSession.Config.Region = aws.String(DefaultRegion) 39 } 40 41 return awsSession, nil 42 } 43 44 func NewAwsSessionWithoutOptions() (*session.Session, error) { 45 return NewAwsSession("", "") 46 } 47 48 func ResolveRegion(profileOption string, regionOption string) (string, error) { 49 session, err := NewAwsSession(profileOption, regionOption) 50 if err != nil { 51 return "", err 52 } 53 return *session.Config.Region, nil 54 } 55 56 func ResolveRegionWithoutOptions() (string, error) { 57 return ResolveRegion("", "") 58 } 59 60 // GetClusterNameAndRegionFromAWS uses the AWS SDK to parse through each EKS cluster until it finds one that matches the endpoint in 61 // the kubeconfig. From there it will retrieve the cluster name 62 func GetClusterNameAndRegionFromAWS(profileOption string, regionOption string, kubeEndpoint string) (string, string, error) { 63 session, err := NewAwsSession(profileOption, regionOption) 64 if err != nil { 65 return "", "", errors.Wrapf(err, "Error creating AWS Session") 66 } 67 svc := eks.New(session) 68 69 input := &eks.ListClustersInput{} 70 result, err := svc.ListClusters(input) 71 if err != nil { 72 return "", "", errors.Wrapf(err, "Error calling Eks List Clusters") 73 } 74 75 for _, cluster := range result.Clusters { 76 input := &eks.DescribeClusterInput{ 77 Name: aws.String(*cluster), 78 } 79 result, err := svc.DescribeCluster(input) 80 if err != nil { 81 return "", "", errors.Wrapf(err, "Error calling Describe Cluster on "+*cluster) 82 } 83 84 if *result.Cluster.Endpoint == kubeEndpoint { 85 return *result.Cluster.Name, *session.Config.Region, nil 86 } 87 } 88 89 return "", "", errors.Errorf("Unable to get cluster name from AWS") 90 } 91 92 // ParseContext parses the EKS cluster context to extract the cluster name and the region 93 func ParseContext(context string) (string, string, error) { 94 // First check if context name matches <cluster-name>.<region>.* 95 reg := regexp.MustCompile(`([a-zA-Z][-a-zA-Z0-9]*)\.((us(-gov)?|ap|ca|cn|eu|sa)-(central|(north|south)?(east|west)?)-\d)\.*`) 96 result := reg.FindStringSubmatch(context) 97 if len(result) >= 3 { 98 return result[1], result[2], nil 99 } 100 101 // or else if the context name matchesAWS ARN format as defined: 102 // https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html 103 reg = regexp.MustCompile(`arn:aws:eks:((?:us(?:-gov)?|ap|ca|cn|eu|sa)-(?:central|(?:north|south)?(?:east|west)?)-\d):[0-9]*:cluster\/([a-zA-Z][-a-zA-Z0-9]*)`) 104 result = reg.FindStringSubmatch(context) 105 if len(result) >= 3 { 106 return result[2], result[1], nil 107 } 108 109 return "", "", errors.Errorf("unable to parse %s as <cluster_name>.<region>.* or arn:aws:<region>:account-id:cluster/<cluster_name>", context) 110 111 } 112 113 // GetCurrentlyConnectedRegionAndClusterName gets the current context for the connected cluster and parses it 114 // to extract both the Region and the ClusterName 115 func GetCurrentlyConnectedRegionAndClusterName() (string, string, error) { 116 kubeConfig, _, err := kube.NewKubeConfig().LoadConfig() 117 if err != nil { 118 return "", "", errors.Wrapf(err, "loading kubeconfig") 119 } 120 121 context := kube.Cluster(kubeConfig) 122 server := kube.CurrentServer(kubeConfig) 123 currentClusterName, currentRegion, err := GetClusterNameAndRegionFromAWS("", "", server) 124 if err != nil { 125 currentClusterName, currentRegion, err := ParseContext(context) 126 if err != nil { 127 return "", "", errors.Wrapf(err, "parsing the current Kubernetes context %s", context) 128 } 129 return currentClusterName, currentRegion, nil 130 } 131 return currentClusterName, currentRegion, nil 132 } 133 134 // UserHomeDir returns the home directory for the user the process is running under. 135 // This is a copy of shareddefaults.UserHomeDir in the internal AWS package. 136 // We can't user user.Current().HomeDir as we want to override this during testing. :-| 137 func UserHomeDir() string { 138 if runtime.GOOS == "windows" { // Windows 139 return os.Getenv("USERPROFILE") 140 } 141 142 // *nix 143 return os.Getenv("HOME") 144 }