github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/pkg/test/framework/metrics/search_writer.go (about)

     1  // Copyright (c) 2021, 2022, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package metrics
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/base64"
     9  	"fmt"
    10  	"github.com/hashicorp/go-retryablehttp"
    11  	"io"
    12  	"net/http"
    13  	"os"
    14  	"time"
    15  )
    16  
    17  // SearchWriter writes to a search endpoint, as an io.Writer and zapcore.WriteSyncer S
    18  type SearchWriter struct {
    19  	hc    *retryablehttp.Client
    20  	url   string
    21  	index string
    22  	auth  string
    23  }
    24  
    25  // SearchWriterFromEnv creates a SearchWriter using environment variables
    26  func SearchWriterFromEnv(index string) (SearchWriter, error) {
    27  	uri := os.Getenv(searchURL)
    28  	if uri == "" {
    29  		return SearchWriter{}, fmt.Errorf("%s is empty", searchURL)
    30  	}
    31  	auth := ""
    32  	user := os.Getenv(searchUser)
    33  	pw := os.Getenv(searchPW)
    34  	if user != "" && pw != "" {
    35  		auth = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", user, pw)))
    36  	}
    37  
    38  	return SearchWriter{
    39  		hc:    retryablehttp.NewClient(),
    40  		url:   uri,
    41  		index: index,
    42  		auth:  auth,
    43  	}, nil
    44  }
    45  
    46  // Close implement as needed
    47  func (s SearchWriter) Close() error {
    48  	return nil
    49  }
    50  
    51  // Sync implement as needed
    52  func (s SearchWriter) Sync() error {
    53  	return nil
    54  }
    55  
    56  // postRecord sends the reader record to the search data store via HTTP Post
    57  // Basic Authorization is used, if encoded auth is provided for basicAuth
    58  func postRecord(hc *retryablehttp.Client, basicAuth, uri string, reader io.Reader) error {
    59  	req, err := retryablehttp.NewRequest("POST", uri, reader)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	req.Header.Set("Content-Type", "application/json")
    64  
    65  	if basicAuth != "" { // Basic Auth is used if provided
    66  		req.Header.Set("Authorization", fmt.Sprintf("basic %s", basicAuth))
    67  	}
    68  	resp, err := hc.Do(req)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	if resp != nil && resp.StatusCode != http.StatusCreated {
    73  		logger.Errorf("error when posting record[%d: %s]", resp.StatusCode, resp.Status)
    74  	}
    75  	return nil
    76  }
    77  
    78  // Write out the record to the search data store
    79  func (s SearchWriter) Write(data []byte) (int, error) {
    80  	index := s.timeStampIndex()
    81  	uri := fmt.Sprintf("%s/%s/_doc", s.url, index)
    82  	reader := bytes.NewReader(data)
    83  	if err := postRecord(s.hc, s.auth, uri, reader); err != nil {
    84  		return 0, err
    85  	}
    86  
    87  	return len(data), nil
    88  }
    89  
    90  // timeStampIndex formats the current index in %s-YYYY.mm.dd format
    91  func (s SearchWriter) timeStampIndex() string {
    92  	return fmt.Sprintf("%s-%s", s.index, time.Now().Format(timeFormatString))
    93  }