99 "encoding/json"
1010 "errors"
1111 "fmt"
12- "math"
1312 "net/http"
1413 "os"
1514 "path/filepath"
@@ -26,7 +25,6 @@ import (
2625 "github.com/go-test/deep"
2726 "github.com/golang/protobuf/proto"
2827 "github.com/hashicorp/go-uuid"
29- "github.com/hashicorp/vault/builtin/credential/userpass"
3028 "github.com/hashicorp/vault/helper/constants"
3129 "github.com/hashicorp/vault/helper/namespace"
3230 "github.com/hashicorp/vault/helper/timeutil"
@@ -5086,193 +5084,3 @@ func TestActivityLog_reportPrecomputedQueryMetrics(t *testing.T) {
50865084 hasMetric (t , data , "identity.pki_acme.active.reporting_period" , 3 , nil )
50875085 })
50885086}
5089-
5090- // TestHandleQuery_MultipleMounts creates a cluster with
5091- // two userpass mounts. It then tests verifies that
5092- // the total new counts are calculated within a reasonably level of accuracy for
5093- // various numbers of clients in each mount.
5094- func TestHandleQuery_MultipleMounts (t * testing.T ) {
5095- tests := map [string ]struct {
5096- twoMonthsAgo [][]int
5097- oneMonthAgo [][]int
5098- currentMonth [][]int
5099- expectedNewClients int
5100- repeatPreviousMonth bool
5101- expectedTotalAccuracy float64
5102- }{
5103- "low volume, all mounts" : {
5104- twoMonthsAgo : [][]int {
5105- {20 , 20 },
5106- },
5107- oneMonthAgo : [][]int {
5108- {30 , 30 },
5109- },
5110- currentMonth : [][]int {
5111- {40 , 40 },
5112- },
5113- repeatPreviousMonth : true ,
5114- expectedNewClients : 80 ,
5115- expectedTotalAccuracy : 1 ,
5116- },
5117- "medium volume, all mounts" : {
5118- twoMonthsAgo : [][]int {
5119- {200 , 200 },
5120- },
5121- oneMonthAgo : [][]int {
5122- {300 , 300 },
5123- },
5124- currentMonth : [][]int {
5125- {400 , 400 },
5126- },
5127- repeatPreviousMonth : true ,
5128- expectedNewClients : 800 ,
5129- expectedTotalAccuracy : 0.98 ,
5130- },
5131- "higher volume, all mounts" : {
5132- twoMonthsAgo : [][]int {
5133- {200 , 200 },
5134- },
5135- oneMonthAgo : [][]int {
5136- {300 , 300 },
5137- },
5138- currentMonth : [][]int {
5139- {2000 , 5000 },
5140- },
5141- repeatPreviousMonth : true ,
5142- expectedNewClients : 7000 ,
5143- expectedTotalAccuracy : 0.95 ,
5144- },
5145- "higher volume, no repeats" : {
5146- twoMonthsAgo : [][]int {
5147- {200 , 200 },
5148- },
5149- oneMonthAgo : [][]int {
5150- {300 , 300 },
5151- },
5152- currentMonth : [][]int {
5153- {4000 , 6000 },
5154- },
5155- repeatPreviousMonth : false ,
5156- expectedNewClients : 10000 ,
5157- expectedTotalAccuracy : 0.98 ,
5158- },
5159- }
5160-
5161- for i , tt := range tests {
5162- testname := fmt .Sprintf ("%s" , i )
5163- t .Run (testname , func (t * testing.T ) {
5164- // Normalize to start of month to prevent end of month weirdness
5165- startOfMonth := timeutil .StartOfMonth (time .Now ().UTC ())
5166-
5167- storage := & logical.InmemStorage {}
5168- coreConfig := & CoreConfig {
5169- CredentialBackends : map [string ]logical.Factory {
5170- "userpass" : userpass .Factory ,
5171- },
5172- Physical : storage .Underlying (),
5173- }
5174-
5175- cluster := NewTestCluster (t , coreConfig , nil )
5176- cluster .Start ()
5177- defer cluster .Cleanup ()
5178- core := cluster .Cores [0 ].Core
5179- TestWaitActive (t , core )
5180-
5181- a := core .activityLog
5182- ctx := namespace .RootContext (nil )
5183- var err error
5184-
5185- namespaces := make ([]* namespace.Namespace , 0 , 6 )
5186- mounts := make (map [string ][]* MountEntry )
5187- ns := namespace .RootNamespace
5188- namespaces = append (namespaces , ns )
5189-
5190- // Add two userpass mounts to the root namespace
5191- for i := 0 ; i < 1 ; i ++ {
5192- me1 := & MountEntry {
5193- Table : credentialTableType ,
5194- Path : "up1/" ,
5195- Type : "userpass" ,
5196- }
5197- err = core .enableCredential (namespace .ContextWithNamespace (ctx , namespaces [i ]), me1 )
5198- require .NoError (t , err )
5199-
5200- me2 := & MountEntry {
5201- Table : credentialTableType ,
5202- Path : "up2/" ,
5203- Type : "userpass" ,
5204- }
5205- err = core .enableCredential (namespace .ContextWithNamespace (ctx , namespaces [i ]), me2 )
5206- require .NoError (t , err )
5207- mounts [namespaces [i ].ID ] = []* MountEntry {me1 , me2 }
5208- }
5209-
5210- // Generate data for two months ago
5211- clientPrefix := 1
5212- var entityRecordsMonth2 []* activity.EntityRecord
5213- for namespaceId , mountSlice := range mounts {
5214- for mountIndex , mount := range mountSlice {
5215- entityRecordsMonth2 = append (entityRecordsMonth2 , generateClientData (0 , tt .twoMonthsAgo [0 ][mountIndex ], mount .Accessor , namespaceId , fmt .Sprintf ("%d" , clientPrefix ))... )
5216- }
5217- }
5218-
5219- // Generate data for a month ago
5220- clientPrefix += 1
5221- var entityRecordsMonth1 []* activity.EntityRecord
5222- for namespaceId , mountSlice := range mounts {
5223- for mountIndex , mount := range mountSlice {
5224- entityRecordsMonth2 = append (entityRecordsMonth1 , generateClientData (0 , tt .oneMonthAgo [0 ][mountIndex ], mount .Accessor , namespaceId , fmt .Sprintf ("%d" , clientPrefix ))... )
5225- }
5226- }
5227-
5228- startOfTwoMonthsAgo := timeutil .StartOfMonth (startOfMonth .AddDate (0 , - 2 , 0 )).UTC ()
5229- startOfOneMonthAgo := timeutil .StartOfMonth (startOfMonth .AddDate (0 , - 1 , 0 )).UTC ()
5230- generatePreviousMonthClientData (t , core , startOfTwoMonthsAgo , entityRecordsMonth2 )
5231- generatePreviousMonthClientData (t , core , startOfOneMonthAgo , entityRecordsMonth1 )
5232-
5233- // Generate the current months data
5234- clientPrefix += 1
5235- var currentMonthData []* activity.EntityRecord
5236- for namespaceId , mountSlice := range mounts {
5237- for mountIndex , mount := range mountSlice {
5238- currentMonthData = append (currentMonthData , generateClientData (0 , tt .currentMonth [0 ][mountIndex ], mount .Accessor , namespaceId , fmt .Sprintf ("%d" , clientPrefix ))... )
5239- clientPrefix += 1
5240- mountIndex ++
5241- }
5242- }
5243- generateCurrentMonthClientData (t , core , entityRecordsMonth2 , currentMonthData )
5244-
5245- endOfCurrentMonth := timeutil .EndOfMonth (time .Now ().UTC ())
5246- actual , err := a .handleQuery (ctx , startOfTwoMonthsAgo , endOfCurrentMonth , 0 )
5247-
5248- // Ensure that the month response is the same as the totals, because all clients
5249- // are new clients and there will be no approximation in the single month partial
5250- // case
5251- monthsRaw , ok := actual ["months" ]
5252- if ! ok {
5253- t .Fatalf ("malformed results. got %v" , actual )
5254- }
5255- monthsResponse := make ([]ResponseMonth , 0 )
5256- err = mapstructure .Decode (monthsRaw , & monthsResponse )
5257-
5258- currentMonthClients := monthsResponse [len (monthsResponse )- 1 ]
5259-
5260- // New verify that the new client totals for ALL namespaces are approximately accurate
5261- newClientsError := math .Abs ((float64 )(currentMonthClients .NewClients .Counts .Clients - tt .expectedNewClients ))
5262- newClientsErrorMargin := newClientsError / (float64 )(tt .expectedNewClients )
5263- expectedAccuracyCalc := (1 - tt .expectedTotalAccuracy ) * 100 / 100
5264- if newClientsErrorMargin > expectedAccuracyCalc {
5265- t .Fatalf ("bad accuracy: expected %+v, found %+v" , expectedAccuracyCalc , newClientsErrorMargin )
5266- }
5267-
5268- // Verify that the totals for the clients are visibly sensible (that is the total of all the individual new clients per namespace)
5269- total := 0
5270- for _ , newClientCounts := range currentMonthClients .NewClients .Namespaces {
5271- total += newClientCounts .Counts .Clients
5272- }
5273- if diff := math .Abs (float64 (currentMonthClients .NewClients .Counts .Clients - total )); diff >= 1 {
5274- t .Fatalf ("total expected was %d but got %d" , currentMonthClients .NewClients .Counts .Clients , total )
5275- }
5276- })
5277- }
5278- }
0 commit comments