clusterinfo.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package costmodel
  2. import (
  3. "fmt"
  4. "github.com/opencost/opencost/core/pkg/clusters"
  5. "github.com/opencost/opencost/core/pkg/log"
  6. "github.com/opencost/opencost/core/pkg/source"
  7. "github.com/opencost/opencost/core/pkg/util/json"
  8. cloudProvider "github.com/opencost/opencost/pkg/cloud/models"
  9. "github.com/opencost/opencost/pkg/config"
  10. "github.com/opencost/opencost/pkg/env"
  11. "k8s.io/client-go/kubernetes"
  12. )
  13. var (
  14. logCollectionEnabled bool = env.IsLogCollectionEnabled()
  15. productAnalyticsEnabled bool = env.IsProductAnalyticsEnabled()
  16. errorReportingEnabled bool = env.IsErrorReportingEnabled()
  17. valuesReportingEnabled bool = env.IsValuesReportingEnabled()
  18. clusterProfile string = env.GetClusterProfile()
  19. )
  20. // writeReportingFlags writes the reporting flags to the cluster info map
  21. func writeReportingFlags(clusterInfo map[string]string) {
  22. clusterInfo[clusters.ClusterInfoLogCollectionKey] = fmt.Sprintf("%t", logCollectionEnabled)
  23. clusterInfo[clusters.ClusterInfoProductAnalyticsKey] = fmt.Sprintf("%t", productAnalyticsEnabled)
  24. clusterInfo[clusters.ClusterInfoErrorReportingKey] = fmt.Sprintf("%t", errorReportingEnabled)
  25. clusterInfo[clusters.ClusterInfoValuesReportingKey] = fmt.Sprintf("%t", valuesReportingEnabled)
  26. }
  27. // writeClusterProfile writes the data associated with the cluster profile
  28. func writeClusterProfile(clusterInfo map[string]string) {
  29. clusterInfo[clusters.ClusterInfoProfileKey] = clusterProfile
  30. }
  31. // writeDataSourceMetaData includes the configured thanos flags on the cluster info
  32. func writeDataSourceMetaData(dataSource source.OpenCostDataSource, clusterInfo map[string]string) {
  33. md := dataSource.MetaData()
  34. for k, v := range md {
  35. clusterInfo[k] = v
  36. }
  37. }
  38. // localClusterInfoProvider gets the local cluster info from the cloud provider and kubernetes
  39. type localClusterInfoProvider struct {
  40. k8s kubernetes.Interface
  41. dataSource source.OpenCostDataSource
  42. provider cloudProvider.Provider
  43. }
  44. // GetClusterInfo returns a string map containing the local cluster info
  45. func (dlcip *localClusterInfoProvider) GetClusterInfo() map[string]string {
  46. data, err := dlcip.provider.ClusterInfo()
  47. // Ensure we create the info object if it doesn't exist
  48. if data == nil {
  49. data = make(map[string]string)
  50. }
  51. kc, ok := dlcip.k8s.(*kubernetes.Clientset)
  52. if ok && data != nil {
  53. v, err := kc.ServerVersion()
  54. if err != nil {
  55. log.Infof("Could not get k8s version info: %s", err.Error())
  56. } else if v != nil {
  57. data[clusters.ClusterInfoVersionKey] = v.Major + "." + v.Minor
  58. }
  59. } else {
  60. log.Infof("Could not get k8s version info: %s", err.Error())
  61. }
  62. writeClusterProfile(data)
  63. writeReportingFlags(data)
  64. writeDataSourceMetaData(dlcip.dataSource, data)
  65. return data
  66. }
  67. // NewLocalClusterInfoProvider creates a new clusters.LocalClusterInfoProvider implementation for providing local
  68. // cluster information
  69. func NewLocalClusterInfoProvider(k8s kubernetes.Interface, dataSource source.OpenCostDataSource, cloud cloudProvider.Provider) clusters.ClusterInfoProvider {
  70. return &localClusterInfoProvider{
  71. k8s: k8s,
  72. dataSource: dataSource,
  73. provider: cloud,
  74. }
  75. }
  76. // configuredClusterInfoProvider just provides the cluster info directly from the config file source.
  77. type configuredClusterInfoProvider struct {
  78. config *config.ConfigFile
  79. }
  80. // GetClusterInfo returns a string map containing the local cluster info
  81. func (ccip *configuredClusterInfoProvider) GetClusterInfo() map[string]string {
  82. clusterInfo := map[string]string{}
  83. data, err := ccip.config.Refresh()
  84. if err != nil {
  85. return clusterInfo
  86. }
  87. err = json.Unmarshal(data, &clusterInfo)
  88. if err != nil {
  89. log.Warnf("ClusterInfo failed to load from configuration: %s", err)
  90. return clusterInfo
  91. }
  92. return clusterInfo
  93. }
  94. // NewConfiguredClusterInfoProvider instantiates and returns a cluster info provider which loads cluster info from
  95. // a config file.
  96. func NewConfiguredClusterInfoProvider(config *config.ConfigFile) clusters.ClusterInfoProvider {
  97. return &configuredClusterInfoProvider{
  98. config: config,
  99. }
  100. }
  101. // clusterInfoWriteOnRequest writes the cluster info result to a config whenever it's requested
  102. type clusterInfoWriteOnRequest struct {
  103. clusterInfo clusters.ClusterInfoProvider
  104. config *config.ConfigFile
  105. }
  106. // GetClusterInfo returns a string map containing the local cluster info
  107. func (ciw *clusterInfoWriteOnRequest) GetClusterInfo() map[string]string {
  108. cInfo := ciw.clusterInfo.GetClusterInfo()
  109. result, err := json.Marshal(cInfo)
  110. if err != nil {
  111. log.Warnf("Failed to write the cluster info: %s", err)
  112. return cInfo
  113. }
  114. err = ciw.config.Write(result)
  115. if err != nil {
  116. log.Warnf("Failed to write the cluster info to config: %s", err)
  117. }
  118. return cInfo
  119. }
  120. // NewClusterInfoWriteOnRequest instantiates and returns a cluster info provider which writes the cluster info to a configuration
  121. // before each request.
  122. func NewClusterInfoWriteOnRequest(clusterInfo clusters.ClusterInfoProvider, config *config.ConfigFile) clusters.ClusterInfoProvider {
  123. return &clusterInfoWriteOnRequest{
  124. clusterInfo: clusterInfo,
  125. config: config,
  126. }
  127. }