vitess.io/vitess@v0.16.2/go/vt/vtorc/inst/audit_dao_test.go (about)

     1  /*
     2  Copyright 2022 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package inst
    18  
    19  import (
    20  	"os"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/stretchr/testify/require"
    25  
    26  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    27  	"vitess.io/vitess/go/vt/vtorc/config"
    28  	"vitess.io/vitess/go/vt/vtorc/db"
    29  )
    30  
    31  // TestAuditOperation tests that auditing a operation works as intended based on the configurations.
    32  func TestAuditOperation(t *testing.T) {
    33  	// Restore original configurations
    34  	originalAuditSysLog := config.Config.AuditToSyslog
    35  	originalAuditLogFile := config.Config.AuditLogFile
    36  	originalAuditBackend := config.Config.AuditToBackendDB
    37  	defer func() {
    38  		config.Config.AuditToSyslog = originalAuditSysLog
    39  		config.Config.AuditLogFile = originalAuditLogFile
    40  		config.Config.AuditToBackendDB = originalAuditBackend
    41  	}()
    42  
    43  	orcDb, err := db.OpenVTOrc()
    44  	require.NoError(t, err)
    45  	defer func() {
    46  		_, err = orcDb.Exec("delete from audit")
    47  		require.NoError(t, err)
    48  		_, err = orcDb.Exec("delete from vitess_tablet")
    49  		require.NoError(t, err)
    50  	}()
    51  
    52  	// Store a tablet in the database
    53  	ks := "ks"
    54  	shard := "0"
    55  	hostname := "localhost"
    56  	var port int32 = 100
    57  	tab100 := &topodatapb.Tablet{
    58  		Alias: &topodatapb.TabletAlias{
    59  			Cell: "zone-1",
    60  			Uid:  100,
    61  		},
    62  		Hostname:      hostname,
    63  		Keyspace:      ks,
    64  		Shard:         shard,
    65  		Type:          topodatapb.TabletType_PRIMARY,
    66  		MysqlHostname: hostname,
    67  		MysqlPort:     port,
    68  	}
    69  	err = SaveTablet(tab100)
    70  	require.NoError(t, err)
    71  
    72  	instance100 := &InstanceKey{
    73  		Hostname: hostname,
    74  		Port:     int(port),
    75  	}
    76  	auditType := "test-audit-operation"
    77  	message := "test-message"
    78  
    79  	t.Run("Audit to backend", func(t *testing.T) {
    80  		config.Config.AuditLogFile = ""
    81  		config.Config.AuditToSyslog = false
    82  		config.Config.AuditToBackendDB = true
    83  
    84  		// Auditing should succeed as expected
    85  		err = AuditOperation(auditType, instance100, message)
    86  		require.NoError(t, err)
    87  
    88  		audits, err := ReadRecentAudit(instance100, 0)
    89  		require.NoError(t, err)
    90  		require.Len(t, audits, 1)
    91  		require.EqualValues(t, 1, audits[0].AuditID)
    92  		require.EqualValues(t, auditType, audits[0].AuditType)
    93  		require.EqualValues(t, message, audits[0].Message)
    94  		require.EqualValues(t, *instance100, audits[0].AuditInstanceKey)
    95  	})
    96  
    97  	t.Run("Audit to File", func(t *testing.T) {
    98  		config.Config.AuditToBackendDB = false
    99  		config.Config.AuditToSyslog = false
   100  
   101  		file, err := os.CreateTemp("", "test-auditing-*")
   102  		require.NoError(t, err)
   103  		defer os.Remove(file.Name())
   104  		config.Config.AuditLogFile = file.Name()
   105  
   106  		err = AuditOperation(auditType, instance100, message)
   107  		require.NoError(t, err)
   108  
   109  		// Give a little time for the write to succeed since it happens in a separate go-routine
   110  		// There is no way to wait for that write to complete. This sleep is required to prevent this test from
   111  		// becoming flaky wherein we sometimes read the file before the contents are written.
   112  		time.Sleep(100 * time.Millisecond)
   113  		fileContent, err := os.ReadFile(file.Name())
   114  		require.NoError(t, err)
   115  		require.Contains(t, string(fileContent), "\ttest-audit-operation\tlocalhost\t100\t[ks:0]\ttest-message")
   116  	})
   117  }