clusterinfo.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package costmodel
  2. import (
  3. "fmt"
  4. cloudProvider "github.com/kubecost/cost-model/pkg/cloud"
  5. "github.com/kubecost/cost-model/pkg/config"
  6. "github.com/kubecost/cost-model/pkg/costmodel/clusters"
  7. "github.com/kubecost/cost-model/pkg/env"
  8. "github.com/kubecost/cost-model/pkg/log"
  9. "github.com/kubecost/cost-model/pkg/thanos"
  10. "github.com/kubecost/cost-model/pkg/util/json"
  11. "k8s.io/client-go/kubernetes"
  12. "k8s.io/klog"
  13. )
  14. var (
  15. logCollectionEnabled bool = env.IsLogCollectionEnabled()
  16. productAnalyticsEnabled bool = env.IsProductAnalyticsEnabled()
  17. errorReportingEnabled bool = env.IsErrorReportingEnabled()
  18. valuesReportingEnabled bool = env.IsValuesReportingEnabled()
  19. clusterProfile string = env.GetClusterProfile()
  20. )
  21. // writeReportingFlags writes the reporting flags to the cluster info map
  22. func writeReportingFlags(clusterInfo map[string]string) {
  23. clusterInfo["logCollection"] = fmt.Sprintf("%t", logCollectionEnabled)
  24. clusterInfo["productAnalytics"] = fmt.Sprintf("%t", productAnalyticsEnabled)
  25. clusterInfo["errorReporting"] = fmt.Sprintf("%t", errorReportingEnabled)
  26. clusterInfo["valuesReporting"] = fmt.Sprintf("%t", valuesReportingEnabled)
  27. }
  28. // writeClusterProfile writes the data associated with the cluster profile
  29. func writeClusterProfile(clusterInfo map[string]string) {
  30. clusterInfo["clusterProfile"] = clusterProfile
  31. }
  32. // writeThanosFlags includes the configured thanos flags on the cluster info
  33. func writeThanosFlags(clusterInfo map[string]string) {
  34. // Include Thanos Offset Duration if Applicable
  35. clusterInfo["thanosEnabled"] = fmt.Sprintf("%t", thanos.IsEnabled())
  36. if thanos.IsEnabled() {
  37. clusterInfo["thanosOffset"] = thanos.Offset()
  38. }
  39. }
  40. // localClusterInfoProvider gets the local cluster info from the cloud provider and kubernetes
  41. type localClusterInfoProvider struct {
  42. k8s kubernetes.Interface
  43. provider cloudProvider.Provider
  44. }
  45. // GetClusterInfo returns a string map containing the local cluster info
  46. func (dlcip *localClusterInfoProvider) GetClusterInfo() map[string]string {
  47. data, err := dlcip.provider.ClusterInfo()
  48. // Ensure we create the info object if it doesn't exist
  49. if data == nil {
  50. data = make(map[string]string)
  51. }
  52. kc, ok := dlcip.k8s.(*kubernetes.Clientset)
  53. if ok && data != nil {
  54. v, err := kc.ServerVersion()
  55. if err != nil {
  56. klog.Infof("Could not get k8s version info: %s", err.Error())
  57. } else if v != nil {
  58. data["version"] = v.Major + "." + v.Minor
  59. }
  60. } else {
  61. klog.Infof("Could not get k8s version info: %s", err.Error())
  62. }
  63. writeClusterProfile(data)
  64. writeReportingFlags(data)
  65. writeThanosFlags(data)
  66. return data
  67. }
  68. // NewLocalClusterInfoProvider creates a new clusters.LocalClusterInfoProvider implementation for providing local
  69. // cluster information
  70. func NewLocalClusterInfoProvider(k8s kubernetes.Interface, cloud cloudProvider.Provider) clusters.ClusterInfoProvider {
  71. return &localClusterInfoProvider{
  72. k8s: k8s,
  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.Warningf("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.Warningf("Failed to write the cluster info: %s", err)
  112. return cInfo
  113. }
  114. err = ciw.config.Write(result)
  115. if err != nil {
  116. log.Warningf("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. }