sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/cloud/endpoints/endpoints.go (about)

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package endpoints
    18  
    19  import (
    20  	"errors"
    21  	"net/url"
    22  	"strings"
    23  
    24  	"github.com/aws/aws-sdk-go/aws/endpoints"
    25  
    26  	"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope"
    27  )
    28  
    29  var (
    30  	errServiceEndpointFormat             = errors.New("must be formatted as ${ServiceID}=${URL}")
    31  	errServiceEndpointSigningRegion      = errors.New("must be formatted as ${SigningRegion}:${ServiceID1}=${URL1},${ServiceID2}=${URL2...}")
    32  	errServiceEndpointURL                = errors.New("must use a valid URL as a service-endpoint")
    33  	errServiceEndpointServiceID          = errors.New("must use a valid serviceID from the AWS GO SDK")
    34  	errServiceEndpointDuplicateServiceID = errors.New("same serviceID defined twice for signing region")
    35  )
    36  
    37  func serviceEnum() []string {
    38  	var serviceIDs = []string{}
    39  	resolver := endpoints.DefaultResolver()
    40  	partitions := resolver.(endpoints.EnumPartitions).Partitions()
    41  	for _, p := range partitions {
    42  		for id := range p.Services() {
    43  			var add = true
    44  			for _, s := range serviceIDs {
    45  				if id == s {
    46  					add = false
    47  				}
    48  			}
    49  			if add {
    50  				serviceIDs = append(serviceIDs, id)
    51  			}
    52  		}
    53  	}
    54  
    55  	return serviceIDs
    56  }
    57  
    58  // ParseFlag parses the command line flag of service endponts in the format ${SigningRegion1}:${ServiceID1}=${URL1},${ServiceID2}=${URL2}...;${SigningRegion2}...
    59  // returning a set of ServiceEndpoints.
    60  func ParseFlag(serviceEndpoints string) ([]scope.ServiceEndpoint, error) {
    61  	if serviceEndpoints == "" {
    62  		return nil, nil
    63  	}
    64  	serviceIDs := serviceEnum()
    65  	signingRegionConfigs := strings.Split(serviceEndpoints, ";")
    66  	endpoints := []scope.ServiceEndpoint{}
    67  	for _, regionConfig := range signingRegionConfigs {
    68  		components := strings.SplitN(regionConfig, ":", 2)
    69  		if len(components) != 2 {
    70  			return nil, errServiceEndpointSigningRegion
    71  		}
    72  		signingRegion := components[0]
    73  		servicePairs := strings.Split(components[1], ",")
    74  		seenServices := []string{}
    75  		for _, servicePair := range servicePairs {
    76  			kv := strings.Split(servicePair, "=")
    77  			if len(kv) != 2 {
    78  				return nil, errServiceEndpointFormat
    79  			}
    80  			var serviceID = ""
    81  			for _, id := range serviceIDs {
    82  				if kv[0] == id {
    83  					serviceID = kv[0]
    84  
    85  					break
    86  				}
    87  			}
    88  			if serviceID == "" {
    89  				return nil, errServiceEndpointServiceID
    90  			}
    91  			if containsString(seenServices, serviceID) {
    92  				return nil, errServiceEndpointDuplicateServiceID
    93  			}
    94  			seenServices = append(seenServices, serviceID)
    95  			URL, err := url.ParseRequestURI(kv[1])
    96  			if err != nil {
    97  				return nil, errServiceEndpointURL
    98  			}
    99  			endpoints = append(endpoints, scope.ServiceEndpoint{
   100  				ServiceID:     serviceID,
   101  				URL:           URL.String(),
   102  				SigningRegion: signingRegion,
   103  			})
   104  		}
   105  	}
   106  
   107  	return endpoints, nil
   108  }
   109  
   110  func containsString(slice []string, s string) bool {
   111  	for _, item := range slice {
   112  		if item == s {
   113  			return true
   114  		}
   115  	}
   116  
   117  	return false
   118  }