Kaynağa Gözat

Simplify config retrieval for KCM, configurable DurableOfferID for rate card, support gov cloud for rate card api

Sean Holcomb 4 yıl önce
ebeveyn
işleme
52262663f4
4 değiştirilmiş dosya ile 43 ekleme ve 71 silme
  1. 1 0
      go.mod
  2. 41 66
      pkg/cloud/azureprovider.go
  3. 1 0
      pkg/cloud/provider.go
  4. 0 5
      pkg/env/costmodelenv.go

+ 1 - 0
go.mod

@@ -10,6 +10,7 @@ require (
 	github.com/Azure/go-autorest/autorest/azure/auth v0.5.6
 	github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
 	github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
+	github.com/Azure/go-autorest/tracing v0.6.0 // indirect
 	github.com/aws/aws-sdk-go v1.28.9
 	github.com/aws/aws-sdk-go-v2 v1.13.0
 	github.com/aws/aws-sdk-go-v2/config v1.13.1

+ 41 - 66
pkg/cloud/azureprovider.go

@@ -21,8 +21,6 @@ import (
 	"github.com/kubecost/cost-model/pkg/util/fileutil"
 	"github.com/kubecost/cost-model/pkg/util/json"
 
-	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-09-01/skus"
-	"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2018-03-31/containerservice"
 	"github.com/Azure/azure-sdk-for-go/services/preview/commerce/mgmt/2015-06-01-preview/commerce"
 	"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-06-01/subscriptions"
 	"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources"
@@ -150,6 +148,10 @@ var azureRegions = []string{
 	"ukwest",
 	"uaecentral",
 	"brazilsoutheast",
+	"usgovarizona",
+	"usgoviowa",
+	"usgovvirginia",
+	"usgovtexas",
 }
 
 type regionParts []string
@@ -297,7 +299,11 @@ func toRegionID(meterRegion string, regions map[string]string) (string, error) {
 	regionCode := regionCodeMappings[rp[0]]
 	lastPart := rp[len(rp)-1]
 	var regionIds []string
-	if _, err := strconv.Atoi(lastPart); err == nil {
+	if regionID, ok := regionIdByDisplayName[meterRegion]; ok {
+		regionIds = []string{
+			regionID,
+		}
+	} else if _, err := strconv.Atoi(lastPart); err == nil {
 		regionIds = []string{
 			fmt.Sprintf("%s%s%s", regionCode, rp[1:len(rp)-1], lastPart),
 			fmt.Sprintf("%s%s%s", rp[1:len(rp)-1], regionCode, lastPart),
@@ -316,6 +322,14 @@ func toRegionID(meterRegion string, regions map[string]string) (string, error) {
 	return "", fmt.Errorf("Couldn't find region")
 }
 
+// azure has very inconsistent naming standards between display names from the rate card api and display names from the regions api
+// this map is to connect display names from the ratecard api to the appropriate id.
+var regionIdByDisplayName = map[string]string{
+	"US Gov AZ": "usgovarizona",
+	"US Gov TX": "usgovtexas",
+	"US Gov": "usgovvirginia",
+}
+
 func checkRegionID(regionID string, regions map[string]string) bool {
 	for region := range regions {
 		if regionID == region {
@@ -454,6 +468,7 @@ type AzureStorageConfig struct {
 	AccountName    string `json:"azureStorageAccount"`
 	AccessKey      string `json:"azureStorageAccessKey"`
 	ContainerName  string `json:"azureStorageContainer"`
+	AzureCloud     string `json:"azureCloud"`
 }
 
 // Represents an azure app key
@@ -488,6 +503,7 @@ func (az *Azure) getAzureAuth(forceReload bool, cp *CustomPricing) (subscription
 		clientID = cp.AzureClientID
 		clientSecret = cp.AzureClientSecret
 		tenantID = cp.AzureTenantID
+
 		return
 	}
 
@@ -505,29 +521,8 @@ func (az *Azure) getAzureAuth(forceReload bool, cp *CustomPricing) (subscription
 	return "", "", "", ""
 }
 
-func (az *Azure) ConfigureAzureStorage() error {
-	subscriptionID, accessKey, accountName, containerName := az.getAzureStorageConfig(false)
-	if subscriptionID != "" && accessKey != "" && accountName != "" && containerName != "" {
-		err := env.Set(env.AzureStorageSubscriptionIDEnvVar, subscriptionID)
-		if err != nil {
-			return err
-		}
-		err = env.Set(env.AzureStorageAccessKeyEnvVar, accessKey)
-		if err != nil {
-			return err
-		}
-		err = env.Set(env.AzureStorageAccountNameEnvVar, accountName)
-		if err != nil {
-			return err
-		}
-		err = env.Set(env.AzureStorageContainerNameEnvVar, containerName)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-func (az *Azure) getAzureStorageConfig(forceReload bool) (subscriptionId, accessKey, accountName, containerName string) {
+// GetAzureStorageConfig retrieves storage config from secret and sets default values
+func (az *Azure) GetAzureStorageConfig(forceReload bool) (*AzureStorageConfig, error) {
 	// retrieve config for default subscription id
 	defaultSubscriptionID := ""
 	config, err := az.GetConfig()
@@ -551,34 +546,17 @@ func (az *Azure) getAzureStorageConfig(forceReload bool) (subscriptionId, access
 
 		// To support already configured users, subscriptionID may not be set in secret in which case, the subscriptionID
 		// for the rate card API is used
-		subscriptionId = defaultSubscriptionID
-		if s.SubscriptionId != "" {
-			subscriptionId = s.SubscriptionId
+		if s.SubscriptionId == "" {
+			s.SubscriptionId  = defaultSubscriptionID
 		}
-
-		accessKey = s.AccessKey
-		accountName = s.AccountName
-		containerName = s.ContainerName
-		return
+		return s, nil
 	}
-
-	// 3. Fall back to env vars
-	subscriptionId = env.Get(env.AzureStorageSubscriptionIDEnvVar, config.AzureSubscriptionID)
-	accountName = env.Get(env.AzureStorageAccountNameEnvVar, "")
-	accessKey = env.Get(env.AzureStorageAccessKeyEnvVar, "")
-	containerName = env.Get(env.AzureStorageContainerNameEnvVar, "")
-	if accessKey != "" && accountName != "" && containerName != "" {
-		az.ServiceAccountChecks["hasStorage"] = &ServiceAccountCheck{
-			Message: "Azure Storage Config exists",
-			Status:  true,
-		}
-	} else {
-		az.ServiceAccountChecks["hasStorage"] = &ServiceAccountCheck{
-			Message: "Azure Storage Config exists",
-			Status:  false,
-		}
+	az.ServiceAccountChecks["hasStorage"] = &ServiceAccountCheck{
+		Message: "Azure Storage Config exists",
+		Status:  false,
 	}
-	return
+	return nil, fmt.Errorf("azure storage config not found")
+
 }
 
 // Load once and cache the result (even on failure). This is an install time secret, so
@@ -756,7 +734,7 @@ func (az *Azure) DownloadPricingData() error {
 	}
 
 	// Load the service provider keys
-	subscriptionID, clientID, clientSecret, tenantID := az.getAzureAuth(false, config)
+	subscriptionID, clientID, clientSecret, tenantID := az.getAzureAuth(true, config)
 	config.AzureSubscriptionID = subscriptionID
 	config.AzureClientID = clientID
 	config.AzureClientSecret = clientSecret
@@ -764,8 +742,7 @@ func (az *Azure) DownloadPricingData() error {
 
 	var authorizer autorest.Authorizer
 
-	azureEnv := determineCloudByRegion(config.AzureBillingRegion)
-
+	azureEnv := determineCloudByRegion(az.clusterRegion)
 
 	if config.AzureClientID != "" && config.AzureClientSecret != "" && config.AzureTenantID != "" {
 		credentialsConfig := NewClientCredentialsConfig(config.AzureClientID, config.AzureClientSecret, config.AzureTenantID, azureEnv)
@@ -790,22 +767,16 @@ func (az *Azure) DownloadPricingData() error {
 		}
 	}
 
-	sClient := subscriptions.NewClient()
+	sClient := subscriptions.NewClientWithBaseURI(azureEnv.ResourceManagerEndpoint)
 	sClient.Authorizer = authorizer
 
-	rcClient := commerce.NewRateCardClient(config.AzureSubscriptionID)
+	rcClient := commerce.NewRateCardClientWithBaseURI(azureEnv.ResourceManagerEndpoint, config.AzureSubscriptionID)
 	rcClient.Authorizer = authorizer
 
-	skusClient := skus.NewResourceSkusClient(config.AzureSubscriptionID)
-	skusClient.Authorizer = authorizer
-
-	providersClient := resources.NewProvidersClient(config.AzureSubscriptionID)
+	providersClient := resources.NewProvidersClientWithBaseURI(azureEnv.ResourceManagerEndpoint, config.AzureSubscriptionID)
 	providersClient.Authorizer = authorizer
 
-	containerServiceClient := containerservice.NewContainerServicesClient(config.AzureSubscriptionID)
-	containerServiceClient.Authorizer = authorizer
-
-	rateCardFilter := fmt.Sprintf("OfferDurableId eq 'MS-AZR-0003p' and Currency eq '%s' and Locale eq 'en-US' and RegionInfo eq '%s'", config.CurrencyCode, config.AzureBillingRegion)
+	rateCardFilter := fmt.Sprintf("OfferDurableId eq '%s' and Currency eq '%s' and Locale eq 'en-US' and RegionInfo eq '%s'", config.AzureOfferDurableID, config.CurrencyCode, config.AzureBillingRegion)
 
 	klog.Infof("Using ratecard query %s", rateCardFilter)
 	result, err := rcClient.Get(context.TODO(), rateCardFilter)
@@ -814,7 +785,7 @@ func (az *Azure) DownloadPricingData() error {
 		az.RateCardPricingError = err
 		return err
 	}
-	allPrices := make(map[string]*AzurePricing)
+
 	regions, err := getRegions("compute", sClient, providersClient, config.AzureSubscriptionID)
 	if err != nil {
 		klog.Warningf("Error in pricing download regions from API")
@@ -823,6 +794,7 @@ func (az *Azure) DownloadPricingData() error {
 	}
 
 	baseCPUPrice := config.CPU
+	allPrices := make(map[string]*AzurePricing)
 
 	for _, v := range *result.Meters {
 		meterName := *v.MeterName
@@ -970,7 +942,6 @@ func NewClientCredentialsConfig(clientID string, clientSecret string, tenantID s
 	}
 }
 
-
 func (az *Azure) addPricing(features string, azurePricing *AzurePricing) {
 	if az.Pricing == nil {
 		az.Pricing = map[string]*AzurePricing{}
@@ -1241,6 +1212,10 @@ func (az *Azure) GetConfig() (*CustomPricing, error) {
 	if c.AzureBillingRegion == "" {
 		c.AzureBillingRegion = "US"
 	}
+	// Default to pay-as-you-go Durable offer id
+	if c.AzureOfferDurableID == "" {
+		c.AzureOfferDurableID = "MS-AZR-0003p"
+	}
 	if c.ShareTenancyCosts == "" {
 		c.ShareTenancyCosts = defaultShareTenancyCost
 	}

+ 1 - 0
pkg/cloud/provider.go

@@ -175,6 +175,7 @@ type CustomPricing struct {
 	AzureClientSecret            string `json:"azureClientSecret"`
 	AzureTenantID                string `json:"azureTenantID"`
 	AzureBillingRegion           string `json:"azureBillingRegion"`
+	AzureOfferDurableID          string `json:"azureOfferDurableID"`
 	CurrencyCode                 string `json:"currencyCode"`
 	Discount                     string `json:"discount"`
 	NegotiatedDiscount           string `json:"negotiatedDiscount"`

+ 0 - 5
pkg/env/costmodelenv.go

@@ -16,11 +16,6 @@ const (
 	AWSAccessKeySecretEnvVar = "AWS_SECRET_ACCESS_KEY"
 	AWSClusterIDEnvVar       = "AWS_CLUSTER_ID"
 
-	AzureStorageSubscriptionIDEnvVar = "AZURE_SUBSCRIPTION_ID"
-	AzureStorageAccessKeyEnvVar      = "AZURE_STORAGE_ACCESS_KEY"
-	AzureStorageAccountNameEnvVar    = "AZURE_STORAGE_ACCOUNT"
-	AzureStorageContainerNameEnvVar  = "AZURE_STORAGE_CONTAINER"
-
 	KubecostNamespaceEnvVar        = "KUBECOST_NAMESPACE"
 	ClusterIDEnvVar                = "CLUSTER_ID"
 	ClusterProfileEnvVar           = "CLUSTER_PROFILE"