logging: Add query related message types (#169)
diff --git a/logging_query.go b/logging_query.go
new file mode 100644
index 0000000..7ec5912
--- /dev/null
+++ b/logging_query.go
@@ -0,0 +1,51 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+package tfjson
+
+import "encoding/json"
+
+const (
+ MessageListStart LogMessageType = "list_start"
+ MessageListResourceFound LogMessageType = "list_resource_found"
+ MessageListComplete LogMessageType = "list_complete"
+)
+
+// ListStartMessage represents "query" result message of type "list_start"
+type ListStartMessage struct {
+ baseLogMessage
+ ListStart ListStartData `json:"list_start"`
+}
+
+type ListStartData struct {
+ Address string `json:"address"`
+ ResourceType string `json:"resource_type"`
+ InputConfig map[string]json.RawMessage `json:"input_config,omitempty"`
+}
+
+// ListResourceFoundMessage represents "query" result message of type "list_resource_found"
+type ListResourceFoundMessage struct {
+ baseLogMessage
+ ListResourceFound ListResourceFoundData `json:"list_resource_found"`
+}
+
+type ListResourceFoundData struct {
+ Address string `json:"address"`
+ DisplayName string `json:"display_name"`
+ Identity map[string]json.RawMessage `json:"identity"`
+ ResourceType string `json:"resource_type"`
+ ResourceObject map[string]json.RawMessage `json:"resource_object,omitempty"`
+ Config string `json:"config,omitempty"`
+ ImportConfig string `json:"import_config,omitempty"`
+}
+
+// ListCompleteMessage represents "query" result message of type "list_complete"
+type ListCompleteMessage struct {
+ baseLogMessage
+ ListComplete ListCompleteData `json:"list_complete"`
+}
+
+type ListCompleteData struct {
+ Address string `json:"address"`
+ ResourceType string `json:"resource_type"`
+ Total int `json:"total"`
+}
diff --git a/logging_test.go b/logging_test.go
index 851cc2c..e6a1119 100644
--- a/logging_test.go
+++ b/logging_test.go
@@ -3,6 +3,7 @@
package tfjson
import (
+ "encoding/json"
"testing"
"time"
@@ -97,3 +98,70 @@
}
}
}
+
+func TestLogging_query(t *testing.T) {
+ testCases := []struct {
+ rawMessage string
+ expectedMessage LogMsg
+ }{
+ {
+ `{"@level":"info","@message":"list.concept_pet.pets: Starting query...","@module":"terraform.ui","@timestamp":"2025-08-28T18:07:11.534006+00:00","list_start":{"address":"list.concept_pet.pets","resource_type":"concept_pet"},"type":"list_start"}`,
+ ListStartMessage{
+ baseLogMessage: baseLogMessage{
+ Lvl: Info,
+ Msg: "list.concept_pet.pets: Starting query...",
+ Time: time.Date(2025, 8, 28, 18, 7, 11, 534006000, time.UTC),
+ },
+ ListStart: ListStartData{
+ Address: "list.concept_pet.pets",
+ ResourceType: "concept_pet",
+ InputConfig: nil,
+ },
+ },
+ },
+ {
+ `{"@level":"info","@message":"list.concept_pet.pets: Result found","@module":"terraform.ui","@timestamp":"2025-08-28T18:07:11.534589+00:00","list_resource_found":{"address":"list.concept_pet.pets","display_name":"This is a easy-antelope","identity":{"id":"easy-antelope","legs":6},"resource_type":"concept_pet"},"type":"list_resource_found"}`,
+ ListResourceFoundMessage{
+ baseLogMessage: baseLogMessage{
+ Lvl: Info,
+ Msg: "list.concept_pet.pets: Result found",
+ Time: time.Date(2025, 8, 28, 18, 7, 11, 534589000, time.UTC),
+ },
+ ListResourceFound: ListResourceFoundData{
+ Address: "list.concept_pet.pets",
+ ResourceType: "concept_pet",
+ DisplayName: "This is a easy-antelope",
+ Identity: map[string]json.RawMessage{
+ "id": json.RawMessage(`"easy-antelope"`),
+ "legs": json.RawMessage("6"),
+ },
+ },
+ },
+ },
+ {
+ `{"@level":"info","@message":"list.concept_pet.pets: List complete","@module":"terraform.ui","@timestamp":"2025-08-28T18:07:11.534661+00:00","list_complete":{"address":"list.concept_pet.pets","resource_type":"concept_pet","total":5},"type":"list_complete"}`,
+ ListCompleteMessage{
+ baseLogMessage: baseLogMessage{
+ Lvl: Info,
+ Msg: "list.concept_pet.pets: List complete",
+ Time: time.Date(2025, 8, 28, 18, 7, 11, 534661000, time.UTC),
+ },
+ ListComplete: ListCompleteData{
+ Address: "list.concept_pet.pets",
+ ResourceType: "concept_pet",
+ Total: 5,
+ },
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ msg, err := UnmarshalLogMessage([]byte(tc.rawMessage))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if diff := cmp.Diff(tc.expectedMessage, msg, cmpOpts); diff != "" {
+ t.Fatalf("unexpected message: %s", diff)
+ }
+ }
+}
diff --git a/logging_types.go b/logging_types.go
index e26522a..3e712a0 100644
--- a/logging_types.go
+++ b/logging_types.go
@@ -21,10 +21,17 @@
LogMessage{},
DiagnosticLogMessage{},
UnknownLogMessage{},
+
+ // query
+ ListStartMessage{},
+ ListResourceFoundMessage{},
+ ListCompleteMessage{},
}
func unmarshalByType(t LogMessageType, b []byte) (LogMsg, error) {
switch t {
+
+ // generic
case MessageTypeVersion:
v := VersionLogMessage{}
return v, json.Unmarshal(b, &v)
@@ -34,6 +41,17 @@
case MessageTypeDiagnostic:
v := DiagnosticLogMessage{}
return v, json.Unmarshal(b, &v)
+
+ // query
+ case MessageListStart:
+ v := ListStartMessage{}
+ return v, json.Unmarshal(b, &v)
+ case MessageListResourceFound:
+ v := ListResourceFoundMessage{}
+ return v, json.Unmarshal(b, &v)
+ case MessageListComplete:
+ v := ListCompleteMessage{}
+ return v, json.Unmarshal(b, &v)
}
v := UnknownLogMessage{}