4
0

api_entities_list_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package api
  2. import (
  3. "context"
  4. "testing"
  5. "connectrpc.com/connect"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. apiv1 "github.com/OliveTin/OliveTin/gen/olivetin/api/v1"
  9. config "github.com/OliveTin/OliveTin/internal/config"
  10. "github.com/OliveTin/OliveTin/internal/entities"
  11. "github.com/OliveTin/OliveTin/internal/executor"
  12. )
  13. func TestGetEntitiesPaginatesAndFiltersInstances(t *testing.T) {
  14. entities.ClearEntitiesOfType("server")
  15. entities.AddEntity("server", "0", map[string]any{"name": "alpha", "hostname": "alpha.example.com", "ip": "10.0.0.1"})
  16. entities.AddEntity("server", "1", map[string]any{"name": "beta", "hostname": "beta.example.com", "ip": "10.0.0.2"})
  17. entities.AddEntity("server", "2", map[string]any{"name": "gamma", "hostname": "gamma.example.com", "ip": "10.0.0.3"})
  18. t.Cleanup(func() {
  19. entities.ClearEntitiesOfType("server")
  20. })
  21. cfg := config.DefaultConfig()
  22. cfg.Entities = []*config.EntityFile{
  23. {
  24. Name: "server",
  25. Properties: []config.EntityProperty{
  26. {Name: "hostname", Title: "Hostname"},
  27. {Name: "ip", Title: "IP"},
  28. },
  29. },
  30. }
  31. cfg.Sanitize()
  32. ex := executor.DefaultExecutor(cfg)
  33. ex.RebuildActionMap()
  34. ts, client := getNewTestServerAndClientWithExecutor(cfg, ex)
  35. defer ts.Close()
  36. filteredResp, err := client.GetEntities(context.Background(), connect.NewRequest(&apiv1.GetEntitiesRequest{
  37. EntityType: "server",
  38. Filter: "beta",
  39. Page: 1,
  40. PageSize: 10,
  41. }))
  42. require.NoError(t, err)
  43. require.Len(t, filteredResp.Msg.EntityDefinitions, 1)
  44. assert.Equal(t, int32(1), filteredResp.Msg.EntityDefinitions[0].TotalInstances)
  45. require.Len(t, filteredResp.Msg.EntityDefinitions[0].Instances, 1)
  46. assert.Equal(t, "beta.example.com", filteredResp.Msg.EntityDefinitions[0].Instances[0].Fields["hostname"])
  47. pagedResp, err := client.GetEntities(context.Background(), connect.NewRequest(&apiv1.GetEntitiesRequest{
  48. EntityType: "server",
  49. Page: 2,
  50. PageSize: 1,
  51. }))
  52. require.NoError(t, err)
  53. require.Len(t, pagedResp.Msg.EntityDefinitions, 1)
  54. assert.Equal(t, int32(3), pagedResp.Msg.EntityDefinitions[0].TotalInstances)
  55. require.Len(t, pagedResp.Msg.EntityDefinitions[0].Instances, 1)
  56. assert.Equal(t, "1", pagedResp.Msg.EntityDefinitions[0].Instances[0].UniqueKey)
  57. }
  58. func TestGetEntitiesUnfilteredIncludesConfiguredProperties(t *testing.T) {
  59. entities.ClearEntitiesOfType("server")
  60. entities.AddEntity("server", "0", map[string]any{"name": "alpha", "hostname": "alpha.example.com", "ip": "10.0.0.1"})
  61. t.Cleanup(func() {
  62. entities.ClearEntitiesOfType("server")
  63. })
  64. cfg := config.DefaultConfig()
  65. cfg.Entities = []*config.EntityFile{
  66. {
  67. Name: "server",
  68. Properties: []config.EntityProperty{
  69. {Name: "hostname", Title: "Hostname"},
  70. },
  71. },
  72. }
  73. cfg.Sanitize()
  74. ex := executor.DefaultExecutor(cfg)
  75. ex.RebuildActionMap()
  76. ts, client := getNewTestServerAndClientWithExecutor(cfg, ex)
  77. defer ts.Close()
  78. resp, err := client.GetEntities(context.Background(), connect.NewRequest(&apiv1.GetEntitiesRequest{}))
  79. require.NoError(t, err)
  80. serverDef := findEntityDefinition(resp.Msg.EntityDefinitions, "server")
  81. require.NotNil(t, serverDef)
  82. require.Len(t, serverDef.Properties, 1)
  83. assert.Equal(t, "hostname", serverDef.Properties[0].Name)
  84. assert.Equal(t, int32(1), serverDef.TotalInstances)
  85. assert.Empty(t, serverDef.Instances)
  86. }
  87. func TestPaginateEntityInstancesHandlesLargePageValues(t *testing.T) {
  88. instances := []*apiv1.Entity{
  89. {UniqueKey: "0"},
  90. {UniqueKey: "1"},
  91. }
  92. assert.Empty(t, paginateEntityInstances(instances, 1<<30, 1))
  93. assert.Empty(t, paginateEntityInstances(instances, 2, 1<<30))
  94. assert.Equal(t, []*apiv1.Entity{{UniqueKey: "1"}}, paginateEntityInstances(instances, 2, 1))
  95. }
  96. func findEntityDefinition(definitions []*apiv1.EntityDefinition, title string) *apiv1.EntityDefinition {
  97. for _, definition := range definitions {
  98. if definition.Title == title {
  99. return definition
  100. }
  101. }
  102. return nil
  103. }
  104. func TestGetEntityRestrictsFieldsToConfiguredProperties(t *testing.T) {
  105. entities.ClearEntitiesOfType("server")
  106. entities.AddEntity("server", "0", map[string]any{
  107. "name": "alpha",
  108. "hostname": "alpha.example.com",
  109. "ip": "10.0.0.1",
  110. "groups": []string{"admins"},
  111. })
  112. t.Cleanup(func() {
  113. entities.ClearEntitiesOfType("server")
  114. })
  115. cfg := config.DefaultConfig()
  116. cfg.Entities = []*config.EntityFile{
  117. {
  118. Name: "server",
  119. Properties: []config.EntityProperty{
  120. {Name: "hostname", Title: "Hostname"},
  121. {Name: "ip", Title: "IP"},
  122. },
  123. },
  124. }
  125. cfg.Sanitize()
  126. ex := executor.DefaultExecutor(cfg)
  127. ex.RebuildActionMap()
  128. ts, client := getNewTestServerAndClientWithExecutor(cfg, ex)
  129. defer ts.Close()
  130. resp, err := client.GetEntity(context.Background(), connect.NewRequest(&apiv1.GetEntityRequest{
  131. Type: "server",
  132. UniqueKey: "0",
  133. }))
  134. require.NoError(t, err)
  135. require.NotNil(t, resp.Msg)
  136. assert.Equal(t, "alpha.example.com", resp.Msg.Fields["hostname"])
  137. assert.Equal(t, "10.0.0.1", resp.Msg.Fields["ip"])
  138. assert.NotContains(t, resp.Msg.Fields, "groups")
  139. assert.NotContains(t, resp.Msg.Fields, "name")
  140. }