diff --git a/daemon/daemon_test.go b/daemon/daemon_test.go index c3e4cda..ed43106 100644 --- a/daemon/daemon_test.go +++ b/daemon/daemon_test.go @@ -442,7 +442,7 @@ func createDaemon(t *testing.T) (*Daemon, *mockNotifier, *notify.MetricsLog, *mo HostId: "testhost-id", ExternalOrganization: "testorg", SocketCount: "1", - Product: "testproduct", + Product: []string{"69"}, Support: "testsupport", Usage: "testusage", Billing: hostinfo.BillingInfo{ diff --git a/hostinfo/info.go b/hostinfo/info.go index 8618a15..e25b5a5 100644 --- a/hostinfo/info.go +++ b/hostinfo/info.go @@ -10,7 +10,7 @@ type HostInfo struct { HostId string ExternalOrganization string SocketCount string - Product string + Product []string Support string Usage string ConversionsSuccess string diff --git a/hostinfo/info_test.go b/hostinfo/info_test.go index 028fbfc..158b165 100644 --- a/hostinfo/info_test.go +++ b/hostinfo/info_test.go @@ -25,7 +25,7 @@ func TestHostInfo(t *testing.T) { "| HostId: 01234567-89ab-cdef-0123-456789abcdef\n" + "| ExternalOrganization: 12345678\n" + "| SocketCount: 3\n" + - "| Product: Red Hat Enterprise Linux Server\n" + + "| Product: [394 69]\n" + "| Support: Premium\n" + "| Usage: Production\n" + "| ConversionsSuccess: true\n" + diff --git a/hostinfo/subscription.go b/hostinfo/subscription.go index 5c3ed58..3e477bf 100644 --- a/hostinfo/subscription.go +++ b/hostinfo/subscription.go @@ -59,8 +59,10 @@ func GetSocketCount(facts SubManValues) (string, error) { return facts.get("cpu.cpu_socket(s)") } -func GetProduct(facts SubManValues) (string, error) { - return facts.get("distribution.name") +func GetProduct(facts SubManValues) ([]string, error) { + output, _ := execSubManCommand("list --installed") + values := parseSubManOutputMultiVal(output) + return values.get("Product ID") } func GetConversionsSuccess(facts SubManValues) (string, error) { @@ -169,3 +171,57 @@ func (values SubManValues) get(name string) (string, error) { return v, nil } + +func parseSubManOutputMultiVal(output string) SubManMultiValues { + values := SubManMultiValues{} + reader := strings.NewReader(output) + scanner := bufio.NewScanner(reader) + + for scanner.Scan() { + line := scanner.Text() + line = strings.TrimSpace(line) + + // Skip empty lines and comments + if line == "" || strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") { + continue + } + + // Parse key-value pairs + parts := strings.SplitN(line, ":", 2) + + if len(parts) != 2 { + continue + } + + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) + values.add(key, value) + } + + return values +} + +type SubManMultiValues map[string][]string + +func (values SubManMultiValues) add(name string, value string) { + key := strings.ToLower(name) + v, ok := values[key] + if !ok { + values[key] = []string{value} + return + } + + values[key] = append(v, value) +} + +func (values SubManMultiValues) get(name string) ([]string, error) { + v, ok := values[strings.ToLower(name)] + + if !ok { + err := fmt.Errorf("`%s` not found", name) + logger.Warnf("Unable to get subscription info: %s", err.Error()) + return []string{}, err + } + + return v, nil +} diff --git a/hostinfo/subscription_test.go b/hostinfo/subscription_test.go index e9fcc0e..7e11a25 100644 --- a/hostinfo/subscription_test.go +++ b/hostinfo/subscription_test.go @@ -1,6 +1,7 @@ package hostinfo import ( + "reflect" "testing" ) @@ -10,7 +11,7 @@ func TestLoadSubManInformation(t *testing.T) { HostId: "01234567-89ab-cdef-0123-456789abcdef", ExternalOrganization: "12345678", SocketCount: "3", - Product: "Red Hat Enterprise Linux Server", + Product: []string{"394", "69"}, Support: "Premium", Usage: "Production", ConversionsSuccess: "true", @@ -69,7 +70,7 @@ func compareHostInfo(t *testing.T, hi *HostInfo, expected *HostInfo) { t.Fatalf("an unexpected value of SocketCount: %v", hi.SocketCount) } - if hi.Product != expected.Product { + if !reflect.DeepEqual(hi.Product, expected.Product) { t.Fatalf("an unexpected value of Product: %v", hi.Product) } diff --git a/mocks/subscription-manager b/mocks/subscription-manager index 2d6add2..3b6eb0e 100755 --- a/mocks/subscription-manager +++ b/mocks/subscription-manager @@ -136,6 +136,30 @@ FACTS_GCP=\ "gcp_project_number: 000000000000 gcp_instance_id: 1111111111111111111" +LIST_INSTALLED=\ +"+-------------------------------------------+ + Installed Product Status ++-------------------------------------------+ +Product Name: Red Hat Developer Tools (for RHEL Server) +Product ID: 394 +Version: 2021.3 +Arch: x86_64 +Status: Not Subscribed +Status Details: +Starts: +Ends: + +Product Name: Red Hat Enterprise Linux Server +Product ID: 69 +Version: 7.9 +Arch: x86_64 +Status: Not Subscribed +Status Details: +Starts: +Ends: + +" + show_identity() { # Show information about the host identity. echo "${IDENTITY}" @@ -170,6 +194,11 @@ show_facts() { esac } +show_list_installed() { + # Show the list of installed products. + echo "${LIST_INSTALLED}" +} + hard_coded() { # Handle the specified subscription-manager command. case "${command:=${1}}" in @@ -185,8 +214,14 @@ hard_coded() { facts) show_facts ;; + list) + show_list_installed + ;; + "list --installed") + show_list_installed + ;; *) - echo "This command is not supported." >&2 + echo "Unsupported command: ${command}" >&2 exit 1 ;; esac diff --git a/notify/policy_test.go b/notify/policy_test.go index b29fd10..b07a940 100644 --- a/notify/policy_test.go +++ b/notify/policy_test.go @@ -83,7 +83,7 @@ func fullyDefinedMockHostInfo() *hostinfo.HostInfo { HostId: "hostid", ExternalOrganization: "externalorganization", SocketCount: "socketcount", - Product: "product", + Product: []string{"69"}, Support: "support", Usage: "usage", Billing: fullyDefinedMockBillingInfo(), diff --git a/notify/prometheus.go b/notify/prometheus.go index 315d57d..3f1b6b1 100644 --- a/notify/prometheus.go +++ b/notify/prometheus.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "strings" "time" "github.com/RedHatInsights/host-metering/config" @@ -188,7 +189,7 @@ func hostInfo2WriteRequest(hostinfo *hostinfo.HostInfo, samples []prompb.Sample) }, { Name: "product", - Value: hostinfo.Product, + Value: strings.Join(hostinfo.Product, ","), }, { Name: "socket_count", diff --git a/notify/prometheus_test.go b/notify/prometheus_test.go index c6b8be1..306da13 100644 --- a/notify/prometheus_test.go +++ b/notify/prometheus_test.go @@ -312,7 +312,7 @@ func TestLabels(t *testing.T) { createRequestAndCheckLabels(t, samples, hi) hi.HostId = "" - hi.Product = "" + hi.Product = []string{} hi.Support = "" createRequestAndCheckLabels(t, samples, hi) @@ -491,7 +491,7 @@ func createHostInfo() *hostinfo.HostInfo { CpuCount: 1, HostId: "test", SocketCount: "1", - Product: "test product", + Product: []string{"123", "456"}, Support: "test support", Usage: "test usage", ConversionsSuccess: "true",