Bladeren bron

Merge branch 'develop' into kaelan-remove-strict-unmarshal

Kaelan Patel 3 jaren geleden
bovenliggende
commit
a4d20a552f

+ 30 - 0
.github/ISSUE_TEMPLATE/opencost-bug-report.md

@@ -0,0 +1,30 @@
+---
+name: OpenCost Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the OpenCost bug is. Please ensure this is an issue related to the OpenCost cost model, API, UI or specification. Public Kubecost bugs may be opened at https://github.com/kubecost/cost-analyzer-helm-chart/ 
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Which version of OpenCost are you using?**
+This may be the Kubecost release.
+
+**Additional context**
+Add any other context about the problem here. Kubernetes versions and which public clouds you are working with are especially important.

+ 20 - 0
.github/ISSUE_TEMPLATE/opencost-feature-request.md

@@ -0,0 +1,20 @@
+---
+name: OpenCost Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context, documentation links, or screenshots about the feature request here.

+ 7 - 8
go.mod

@@ -46,7 +46,7 @@ require (
 	go.etcd.io/bbolt v1.3.5
 	golang.org/x/exp v0.0.0-20220609121020-a51bd0440498
 	golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
-	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
+	golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
 	google.golang.org/api v0.44.0
 	gopkg.in/yaml.v2 v2.4.0
 	k8s.io/api v0.20.4
@@ -121,14 +121,13 @@ require (
 	go.opencensus.io v0.23.0 // indirect
 	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
 	golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
-	golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
-	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
-	golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
-	golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
-	golang.org/x/text v0.3.7 // indirect
+	golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+	golang.org/x/net v0.1.0 // indirect
+	golang.org/x/sys v0.1.0 // indirect
+	golang.org/x/term v0.1.0 // indirect
+	golang.org/x/text v0.4.0 // indirect
 	golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
-	golang.org/x/tools v0.1.10 // indirect
-	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
+	golang.org/x/tools v0.1.12 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
 	google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
 	google.golang.org/grpc v1.38.0 // indirect

+ 14 - 10
go.sum

@@ -684,8 +684,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -733,8 +733,9 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -759,8 +760,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -822,11 +824,13 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -835,8 +839,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -898,8 +902,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
-golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
-golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
+golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

+ 31 - 10
pkg/cloud/azureprovider.go

@@ -19,6 +19,8 @@ import (
 	"github.com/opencost/opencost/pkg/util"
 	"github.com/opencost/opencost/pkg/util/fileutil"
 	"github.com/opencost/opencost/pkg/util/json"
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
 
 	"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"
@@ -40,6 +42,8 @@ const (
 	AzureStorageUpdateType           = "AzureStorage"
 )
 
+var toTitle = cases.Title(language.Und, cases.NoLower)
+
 var (
 	regionCodeMappings = map[string]string{
 		"ap": "asia",
@@ -355,7 +359,7 @@ type AzureRetailPricing struct {
 	Count              int                            `json:"Count"`
 }
 
-//AzureRetailPricingAttributes struct for unmarshalling Azure Retail pricing api JSON response
+// AzureRetailPricingAttributes struct for unmarshalling Azure Retail pricing api JSON response
 type AzureRetailPricingAttributes struct {
 	CurrencyCode         string     `json:"currencyCode"`
 	TierMinimumUnits     float32    `json:"tierMinimumUnits"`
@@ -531,9 +535,15 @@ func (az *Azure) getAzureRateCardAuth(forceReload bool, cp *CustomPricing) (subs
 		tenantID = cp.AzureTenantID
 		return
 	}
-
-	// 3. Empty values
+	// 3. Check if AzureSubscriptionID is set in config (set though endpoint)
+	// MSI credentials will be attempted if the subscription ID is set, but clientID, clientSecret and tenantID are not
+	if cp.AzureSubscriptionID != "" {
+		subscriptionID = cp.AzureSubscriptionID
+		return
+	}
+	// 4. Empty values
 	return "", "", "", ""
+
 }
 
 // GetAzureStorageConfig retrieves storage config from secret and sets default values
@@ -571,7 +581,7 @@ func (az *Azure) GetAzureStorageConfig(forceReload bool, cp *CustomPricing) (*Az
 			asc.SubscriptionId = defaultSubscriptionID
 		}
 		// check for required fields
-		if asc.AccessKey != "" && asc.AccountName != "" && asc.ContainerName != "" && asc.SubscriptionId == "" {
+		if asc.AccessKey != "" && asc.AccountName != "" && asc.ContainerName != "" && asc.SubscriptionId != "" {
 			az.serviceAccountChecks.set("hasStorage", &ServiceAccountCheck{
 				Message: "Azure Storage Config exists",
 				Status:  true,
@@ -1190,7 +1200,7 @@ func (az *Azure) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, e
 			asc := &AzureStorageConfig{}
 			err := json.NewDecoder(r).Decode(&asc)
 			if err != nil {
-				return err
+				return fmt.Errorf("error decoding AzureStorageConfig: %s", err)
 			}
 
 			c.AzureStorageSubscriptionID = asc.SubscriptionId
@@ -1202,35 +1212,46 @@ func (az *Azure) UpdateConfig(r io.Reader, updateType string) (*CustomPricing, e
 			c.AzureContainerPath = asc.ContainerPath
 			c.AzureCloud = asc.AzureCloud
 		} else {
-			defer az.DownloadPricingData()
+			// This will block if not in a goroutine. It calls GetConfig(), which
+			// in turn calls GetCustomPricingData, which acquires the same lock
+			// that is acquired by az.Config.Update, which is the function to
+			// which this function gets passed, and subsequently called. Booo.
+			defer func() {
+				go az.DownloadPricingData()
+			}()
+
 			a := make(map[string]interface{})
 			err := json.NewDecoder(r).Decode(&a)
 			if err != nil {
-				return err
+				return fmt.Errorf("error decoding AzureStorageConfig: %s", err)
 			}
+
 			for k, v := range a {
-				kUpper := strings.Title(k) // Just so we consistently supply / receive the same values, uppercase the first letter.
+				// Just so we consistently supply / receive the same values, uppercase the first letter.
+				kUpper := toTitle.String(k)
 				vstr, ok := v.(string)
 				if ok {
 					err := SetCustomPricingField(c, kUpper, vstr)
 					if err != nil {
-						return err
+						return fmt.Errorf("error setting custom pricing field on AzureStorageConfig: %s", err)
 					}
 				} else {
 					return fmt.Errorf("type error while updating config for %s", kUpper)
 				}
 			}
 		}
+
 		if env.IsRemoteEnabled() {
 			err := UpdateClusterMeta(env.GetClusterID(), c.ClusterName)
 			if err != nil {
-				return err
+				return fmt.Errorf("error updating cluster metadata: %s", err)
 			}
 		}
 
 		return nil
 	})
 }
+
 func (az *Azure) GetConfig() (*CustomPricing, error) {
 	c, err := az.Config.GetCustomPricingData()
 	if err != nil {

+ 1 - 19
pkg/clustercache/clustercache.go

@@ -7,7 +7,6 @@ import (
 	"github.com/opencost/opencost/pkg/log"
 
 	appsv1 "k8s.io/api/apps/v1"
-	autoscaling "k8s.io/api/autoscaling/v2beta1"
 	batchv1 "k8s.io/api/batch/v1"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/api/policy/v1beta1"
@@ -61,9 +60,6 @@ type ClusterCache interface {
 	// GetAllJobs returns all the cached jobs
 	GetAllJobs() []*batchv1.Job
 
-	// GetAllHorizontalPodAutoscalers returns all cached horizontal pod autoscalers
-	GetAllHorizontalPodAutoscalers() []*autoscaling.HorizontalPodAutoscaler
-
 	// GetAllPodDisruptionBudgets returns all cached pod disruption budgets
 	GetAllPodDisruptionBudgets() []*v1beta1.PodDisruptionBudget
 
@@ -91,7 +87,6 @@ type KubernetesClusterCache struct {
 	pvcWatch                   WatchController
 	storageClassWatch          WatchController
 	jobsWatch                  WatchController
-	hpaWatch                   WatchController
 	pdbWatch                   WatchController
 	replicationControllerWatch WatchController
 	stop                       chan struct{}
@@ -107,7 +102,6 @@ func NewKubernetesClusterCache(client kubernetes.Interface) ClusterCache {
 	appsRestClient := client.AppsV1().RESTClient()
 	storageRestClient := client.StorageV1().RESTClient()
 	batchClient := client.BatchV1().RESTClient()
-	autoscalingClient := client.AutoscalingV2beta1().RESTClient()
 	pdbClient := client.PolicyV1beta1().RESTClient()
 
 	kubecostNamespace := env.GetKubecostNamespace()
@@ -128,7 +122,6 @@ func NewKubernetesClusterCache(client kubernetes.Interface) ClusterCache {
 		pvcWatch:                   NewCachingWatcher(coreRestClient, "persistentvolumeclaims", &v1.PersistentVolumeClaim{}, "", fields.Everything()),
 		storageClassWatch:          NewCachingWatcher(storageRestClient, "storageclasses", &stv1.StorageClass{}, "", fields.Everything()),
 		jobsWatch:                  NewCachingWatcher(batchClient, "jobs", &batchv1.Job{}, "", fields.Everything()),
-		hpaWatch:                   NewCachingWatcher(autoscalingClient, "horizontalpodautoscalers", &autoscaling.HorizontalPodAutoscaler{}, "", fields.Everything()),
 		pdbWatch:                   NewCachingWatcher(pdbClient, "poddisruptionbudgets", &v1beta1.PodDisruptionBudget{}, "", fields.Everything()),
 		replicationControllerWatch: NewCachingWatcher(coreRestClient, "replicationcontrollers", &v1.ReplicationController{}, "", fields.Everything()),
 	}
@@ -140,7 +133,7 @@ func NewKubernetesClusterCache(client kubernetes.Interface) ClusterCache {
 		wg.Add(1)
 		go initializeCache(kcc.kubecostConfigMapWatch, &wg, cancel)
 	} else {
-		wg.Add(16)
+		wg.Add(15)
 		go initializeCache(kcc.kubecostConfigMapWatch, &wg, cancel)
 		go initializeCache(kcc.namespaceWatch, &wg, cancel)
 		go initializeCache(kcc.nodeWatch, &wg, cancel)
@@ -154,7 +147,6 @@ func NewKubernetesClusterCache(client kubernetes.Interface) ClusterCache {
 		go initializeCache(kcc.pvcWatch, &wg, cancel)
 		go initializeCache(kcc.storageClassWatch, &wg, cancel)
 		go initializeCache(kcc.jobsWatch, &wg, cancel)
-		go initializeCache(kcc.hpaWatch, &wg, cancel)
 		go initializeCache(kcc.podWatch, &wg, cancel)
 		go initializeCache(kcc.replicationControllerWatch, &wg, cancel)
 	}
@@ -185,7 +177,6 @@ func (kcc *KubernetesClusterCache) Run() {
 	go kcc.pvcWatch.Run(1, stopCh)
 	go kcc.storageClassWatch.Run(1, stopCh)
 	go kcc.jobsWatch.Run(1, stopCh)
-	go kcc.hpaWatch.Run(1, stopCh)
 	go kcc.pdbWatch.Run(1, stopCh)
 	go kcc.replicationControllerWatch.Run(1, stopCh)
 
@@ -309,15 +300,6 @@ func (kcc *KubernetesClusterCache) GetAllJobs() []*batchv1.Job {
 	return jobs
 }
 
-func (kcc *KubernetesClusterCache) GetAllHorizontalPodAutoscalers() []*autoscaling.HorizontalPodAutoscaler {
-	var hpas []*autoscaling.HorizontalPodAutoscaler
-	items := kcc.hpaWatch.GetAll()
-	for _, hpa := range items {
-		hpas = append(hpas, hpa.(*autoscaling.HorizontalPodAutoscaler))
-	}
-	return hpas
-}
-
 func (kcc *KubernetesClusterCache) GetAllPodDisruptionBudgets() []*v1beta1.PodDisruptionBudget {
 	var pdbs []*v1beta1.PodDisruptionBudget
 	items := kcc.pdbWatch.GetAll()

+ 28 - 31
pkg/clustercache/clusterexporter.go

@@ -9,7 +9,6 @@ import (
 	"github.com/opencost/opencost/pkg/util/json"
 
 	appsv1 "k8s.io/api/apps/v1"
-	autoscaling "k8s.io/api/autoscaling/v2beta1"
 	batchv1 "k8s.io/api/batch/v1"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/api/policy/v1beta1"
@@ -18,21 +17,20 @@ import (
 
 // clusterEncoding is used to represent the cluster objects in the encoded states.
 type clusterEncoding struct {
-	Namespaces               []*v1.Namespace                        `json:"namespaces,omitempty"`
-	Nodes                    []*v1.Node                             `json:"nodes,omitempty"`
-	Pods                     []*v1.Pod                              `json:"pods,omitempty"`
-	Services                 []*v1.Service                          `json:"services,omitempty"`
-	DaemonSets               []*appsv1.DaemonSet                    `json:"daemonSets,omitempty"`
-	Deployments              []*appsv1.Deployment                   `json:"deployments,omitempty"`
-	StatefulSets             []*appsv1.StatefulSet                  `json:"statefulSets,omitempty"`
-	ReplicaSets              []*appsv1.ReplicaSet                   `json:"replicaSets,omitempty"`
-	PersistentVolumes        []*v1.PersistentVolume                 `json:"persistentVolumes,omitempty"`
-	PersistentVolumeClaims   []*v1.PersistentVolumeClaim            `json:"persistentVolumeClaims,omitempty"`
-	StorageClasses           []*stv1.StorageClass                   `json:"storageClasses,omitempty"`
-	Jobs                     []*batchv1.Job                         `json:"jobs,omitempty"`
-	HorizontalPodAutoscalers []*autoscaling.HorizontalPodAutoscaler `json:"horizontalPodAutoscalers,omitempty"`
-	PodDisruptionBudgets     []*v1beta1.PodDisruptionBudget         `json:"podDisruptionBudgets,omitEmpty"`
-	ReplicationControllers   []*v1.ReplicationController            `json:"replicationController,omitEmpty"`
+	Namespaces             []*v1.Namespace                `json:"namespaces,omitempty"`
+	Nodes                  []*v1.Node                     `json:"nodes,omitempty"`
+	Pods                   []*v1.Pod                      `json:"pods,omitempty"`
+	Services               []*v1.Service                  `json:"services,omitempty"`
+	DaemonSets             []*appsv1.DaemonSet            `json:"daemonSets,omitempty"`
+	Deployments            []*appsv1.Deployment           `json:"deployments,omitempty"`
+	StatefulSets           []*appsv1.StatefulSet          `json:"statefulSets,omitempty"`
+	ReplicaSets            []*appsv1.ReplicaSet           `json:"replicaSets,omitempty"`
+	PersistentVolumes      []*v1.PersistentVolume         `json:"persistentVolumes,omitempty"`
+	PersistentVolumeClaims []*v1.PersistentVolumeClaim    `json:"persistentVolumeClaims,omitempty"`
+	StorageClasses         []*stv1.StorageClass           `json:"storageClasses,omitempty"`
+	Jobs                   []*batchv1.Job                 `json:"jobs,omitempty"`
+	PodDisruptionBudgets   []*v1beta1.PodDisruptionBudget `json:"podDisruptionBudgets,omitEmpty"`
+	ReplicationControllers []*v1.ReplicationController    `json:"replicationController,omitEmpty"`
 }
 
 // ClusterExporter manages and runs an file export process which dumps the local kubernetes cluster to a target location.
@@ -90,21 +88,20 @@ func (ce *ClusterExporter) Stop() {
 func (ce *ClusterExporter) Export() error {
 	c := ce.cluster
 	encoding := &clusterEncoding{
-		Namespaces:               c.GetAllNamespaces(),
-		Nodes:                    c.GetAllNodes(),
-		Pods:                     c.GetAllPods(),
-		Services:                 c.GetAllServices(),
-		DaemonSets:               c.GetAllDaemonSets(),
-		Deployments:              c.GetAllDeployments(),
-		StatefulSets:             c.GetAllStatefulSets(),
-		ReplicaSets:              c.GetAllReplicaSets(),
-		PersistentVolumes:        c.GetAllPersistentVolumes(),
-		PersistentVolumeClaims:   c.GetAllPersistentVolumeClaims(),
-		StorageClasses:           c.GetAllStorageClasses(),
-		Jobs:                     c.GetAllJobs(),
-		HorizontalPodAutoscalers: c.GetAllHorizontalPodAutoscalers(),
-		PodDisruptionBudgets:     c.GetAllPodDisruptionBudgets(),
-		ReplicationControllers:   c.GetAllReplicationControllers(),
+		Namespaces:             c.GetAllNamespaces(),
+		Nodes:                  c.GetAllNodes(),
+		Pods:                   c.GetAllPods(),
+		Services:               c.GetAllServices(),
+		DaemonSets:             c.GetAllDaemonSets(),
+		Deployments:            c.GetAllDeployments(),
+		StatefulSets:           c.GetAllStatefulSets(),
+		ReplicaSets:            c.GetAllReplicaSets(),
+		PersistentVolumes:      c.GetAllPersistentVolumes(),
+		PersistentVolumeClaims: c.GetAllPersistentVolumeClaims(),
+		StorageClasses:         c.GetAllStorageClasses(),
+		Jobs:                   c.GetAllJobs(),
+		PodDisruptionBudgets:   c.GetAllPodDisruptionBudgets(),
+		ReplicationControllers: c.GetAllReplicationControllers(),
 	}
 
 	data, err := json.Marshal(encoding)

+ 0 - 16
pkg/clustercache/clusterimporter.go

@@ -7,7 +7,6 @@ import (
 	"github.com/opencost/opencost/pkg/log"
 	"github.com/opencost/opencost/pkg/util/json"
 	appsv1 "k8s.io/api/apps/v1"
-	autoscaling "k8s.io/api/autoscaling/v2beta1"
 	batchv1 "k8s.io/api/batch/v1"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/api/policy/v1beta1"
@@ -271,21 +270,6 @@ func (ci *ClusterImporter) GetAllJobs() []*batchv1.Job {
 	return cloneList
 }
 
-// GetAllHorizontalPodAutoscalers() returns all cached horizontal pod autoscalers
-func (ci *ClusterImporter) GetAllHorizontalPodAutoscalers() []*autoscaling.HorizontalPodAutoscaler {
-	ci.dataLock.Lock()
-	defer ci.dataLock.Unlock()
-
-	// Deep copy here to avoid callers from corrupting the cache
-	// This also mimics the behavior of the default cluster cache impl.
-	hpas := ci.data.HorizontalPodAutoscalers
-	cloneList := make([]*autoscaling.HorizontalPodAutoscaler, 0, len(hpas))
-	for _, v := range hpas {
-		cloneList = append(cloneList, v.DeepCopy())
-	}
-	return cloneList
-}
-
 // GetAllPodDisruptionBudgets returns all cached pod disruption budgets
 func (ci *ClusterImporter) GetAllPodDisruptionBudgets() []*v1beta1.PodDisruptionBudget {
 	ci.dataLock.Lock()