github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/targets/gcplog/pull_target_test.go (about)

     1  package gcplog
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"cloud.google.com/go/pubsub"
    10  	"cloud.google.com/go/pubsub/pstest"
    11  	"github.com/go-kit/log"
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	"github.com/prometheus/common/model"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  	"google.golang.org/api/option"
    17  	"google.golang.org/grpc"
    18  	"google.golang.org/grpc/credentials/insecure"
    19  
    20  	"github.com/grafana/loki/clients/pkg/promtail/api"
    21  	"github.com/grafana/loki/clients/pkg/promtail/client/fake"
    22  	"github.com/grafana/loki/clients/pkg/promtail/scrapeconfig"
    23  	"github.com/grafana/loki/clients/pkg/promtail/targets/target"
    24  )
    25  
    26  func TestPullTarget_Run(t *testing.T) {
    27  	// Goal: Check message written to pubsub topic is received by the target.
    28  	tt, apiclient, pubsubClient, teardown := testPullTarget(t)
    29  	defer teardown()
    30  
    31  	// seed pubsub
    32  	ctx := context.Background()
    33  	tp, err := pubsubClient.CreateTopic(ctx, topic)
    34  	require.NoError(t, err)
    35  	_, err = pubsubClient.CreateSubscription(ctx, subscription, pubsub.SubscriptionConfig{
    36  		Topic: tp,
    37  	})
    38  	require.NoError(t, err)
    39  
    40  	var wg sync.WaitGroup
    41  
    42  	wg.Add(1)
    43  	go func() {
    44  		defer wg.Done()
    45  		_ = tt.run()
    46  	}()
    47  
    48  	publishMessage(t, tp)
    49  
    50  	// Wait till message is received by the run loop.
    51  	// NOTE(kavi): sleep is not ideal. but not other way to confirm if api.Handler received messages
    52  	time.Sleep(1 * time.Second)
    53  
    54  	err = tt.Stop()
    55  	require.NoError(t, err)
    56  
    57  	// wait till `run` stops.
    58  	wg.Wait()
    59  
    60  	assert.Equal(t, 1, len(apiclient.Received()))
    61  }
    62  
    63  func TestPullTarget_Stop(t *testing.T) {
    64  	// Goal: To test that `run()` stops when you invoke `target.Stop()`
    65  
    66  	errs := make(chan error, 1)
    67  
    68  	tt, _, _, teardown := testPullTarget(t)
    69  	defer teardown()
    70  
    71  	var wg sync.WaitGroup
    72  
    73  	wg.Add(1)
    74  	go func() {
    75  		defer wg.Done()
    76  		errs <- tt.run()
    77  	}()
    78  
    79  	// invoke stop
    80  	_ = tt.Stop()
    81  
    82  	// wait till run returns
    83  	wg.Wait()
    84  
    85  	// wouldn't block as 1 error is buffered into the channel.
    86  	err := <-errs
    87  
    88  	// returned error should be cancelled context error
    89  	assert.Equal(t, tt.ctx.Err(), err)
    90  }
    91  
    92  func TestPullTarget_Type(t *testing.T) {
    93  	tt, _, _, teardown := testPullTarget(t)
    94  	defer teardown()
    95  
    96  	assert.Equal(t, target.TargetType("Gcplog"), tt.Type())
    97  }
    98  
    99  func TestPullTarget_Ready(t *testing.T) {
   100  	tt, _, _, teardown := testPullTarget(t)
   101  	defer teardown()
   102  
   103  	assert.Equal(t, true, tt.Ready())
   104  }
   105  
   106  func TestPullTarget_Labels(t *testing.T) {
   107  	tt, _, _, teardown := testPullTarget(t)
   108  	defer teardown()
   109  
   110  	assert.Equal(t, model.LabelSet{"job": "test-gcplogtarget"}, tt.Labels())
   111  }
   112  
   113  func testPullTarget(t *testing.T) (*pullTarget, *fake.Client, *pubsub.Client, func()) {
   114  	t.Helper()
   115  
   116  	ctx, cancel := context.WithCancel(context.Background())
   117  
   118  	mockSvr := pstest.NewServer()
   119  	conn, err := grpc.Dial(mockSvr.Addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
   120  	require.NoError(t, err)
   121  
   122  	mockpubsubClient, err := pubsub.NewClient(ctx, testConfig.ProjectID, option.WithGRPCConn(conn))
   123  	require.NoError(t, err)
   124  
   125  	fakeClient := fake.New(func() {})
   126  
   127  	var handler api.EntryHandler = fakeClient
   128  	target := &pullTarget{
   129  		metrics:       NewMetrics(prometheus.NewRegistry()),
   130  		logger:        log.NewNopLogger(),
   131  		handler:       handler,
   132  		relabelConfig: nil,
   133  		config:        testConfig,
   134  		jobName:       "job-test-gcplogtarget",
   135  		ctx:           ctx,
   136  		cancel:        cancel,
   137  		ps:            mockpubsubClient,
   138  		msgs:          make(chan *pubsub.Message),
   139  	}
   140  
   141  	// cleanup
   142  	return target, fakeClient, mockpubsubClient, func() {
   143  		cancel()
   144  		conn.Close()
   145  		mockSvr.Close()
   146  	}
   147  }
   148  
   149  func publishMessage(t *testing.T, topic *pubsub.Topic) {
   150  	t.Helper()
   151  
   152  	ctx := context.Background()
   153  	res := topic.Publish(ctx, &pubsub.Message{Data: []byte(gcpLogEntry)})
   154  	_, err := res.Get(ctx) // wait till message is actully published
   155  	require.NoError(t, err)
   156  }
   157  
   158  const (
   159  	project      = "test-project"
   160  	topic        = "test-topic"
   161  	subscription = "test-subscription"
   162  
   163  	gcpLogEntry = `
   164  {
   165    "insertId": "ajv4d1f1ch8dr",
   166    "logName": "projects/grafanalabs-dev/logs/cloudaudit.googleapis.com%2Fdata_access",
   167    "protoPayload": {
   168      "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
   169      "authenticationInfo": {
   170        "principalEmail": "1040409107725-compute@developer.gserviceaccount.com",
   171        "serviceAccountDelegationInfo": [
   172          {
   173            "firstPartyPrincipal": {
   174              "principalEmail": "service-1040409107725@compute-system.iam.gserviceaccount.com"
   175            }
   176          }
   177        ]
   178      },
   179      "authorizationInfo": [
   180        {
   181          "granted": true,
   182          "permission": "storage.objects.list",
   183          "resource": "projects/_/buckets/dev-us-central1-cortex-tsdb-dev",
   184          "resourceAttributes": {
   185          }
   186        },
   187        {
   188          "permission": "storage.objects.get",
   189          "resource": "projects/_/buckets/dev-us-central1-cortex-tsdb-dev/objects/load-generator-20/01EM34PFBC2SCV3ETBGRAQZ090/deletion-mark.json",
   190          "resourceAttributes": {
   191          }
   192        }
   193      ],
   194      "methodName": "storage.objects.get",
   195      "requestMetadata": {
   196        "callerIp": "34.66.19.193",
   197        "callerNetwork": "//compute.googleapis.com/projects/grafanalabs-dev/global/networks/__unknown__",
   198        "callerSuppliedUserAgent": "thanos-store-gateway/1.5.0 (go1.14.9),gzip(gfe)",
   199        "destinationAttributes": {
   200        },
   201        "requestAttributes": {
   202          "auth": {
   203          },
   204          "time": "2021-01-01T02:17:10.661405637Z"
   205        }
   206      },
   207      "resourceLocation": {
   208        "currentLocations": [
   209          "us-central1"
   210        ]
   211      },
   212      "resourceName": "projects/_/buckets/dev-us-central1-cortex-tsdb-dev/objects/load-generator-20/01EM34PFBC2SCV3ETBGRAQZ090/deletion-mark.json",
   213      "serviceName": "storage.googleapis.com",
   214      "status": {
   215      }
   216    },
   217    "receiveTimestamp": "2021-01-01T02:17:10.82013623Z",
   218    "resource": {
   219      "labels": {
   220        "bucket_name": "dev-us-central1-cortex-tsdb-dev",
   221        "location": "us-central1",
   222        "project_id": "grafanalabs-dev"
   223      },
   224      "type": "gcs_bucket"
   225    },
   226    "severity": "INFO",
   227    "timestamp": "2021-01-01T02:17:10.655982344Z"
   228  }
   229  `
   230  )
   231  
   232  var testConfig = &scrapeconfig.GcplogTargetConfig{
   233  	ProjectID:    project,
   234  	Subscription: subscription,
   235  	Labels: model.LabelSet{
   236  		"job": "test-gcplogtarget",
   237  	},
   238  	SubscriptionType: "pull",
   239  }