github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/pkg/opensearch_dashboards/opensearch_dashboards_upgrade_test.go (about)

     1  // Copyright (C) 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 dashboards
     5  
     6  import (
     7  	"errors"
     8  	"github.com/stretchr/testify/assert"
     9  	vmcontrollerv1 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/apis/vmcontroller/v1"
    10  	"github.com/verrazzano/verrazzano-monitoring-operator/pkg/util/logs/vzlog"
    11  	"io"
    12  	"net/http"
    13  	"strings"
    14  	"testing"
    15  )
    16  
    17  const fakeGetPatternOutput = `{
    18    "page": 1,
    19    "per_page": 20,
    20    "total": 2,
    21    "saved_objects": [
    22      {
    23        "type": "index-pattern",
    24        "id": "0f2ede70-8e15-11ec-abc1-6bc5e972b077",
    25        "attributes": {
    26          "title": "verrazzano-namespace-bobs-books"
    27        },
    28        "references": [],
    29        "migrationVersion": {
    30          "index-pattern": "7.6.0"
    31        },
    32        "updated_at": "2022-02-15T04:09:24.182Z",
    33        "version": "WzQsMV0=",
    34        "namespaces": [
    35          "default"
    36        ],
    37        "score": 0
    38      },
    39      {
    40        "type": "index-pattern",
    41        "id": "1cb7fcc0-8e15-11ec-abc1-6bc5e972b077",
    42        "attributes": {
    43          "title": "verrazzano-namespace-todo*"
    44        },
    45        "references": [],
    46        "migrationVersion": {
    47          "index-pattern": "7.6.0"
    48        },
    49        "updated_at": "2022-02-15T04:09:46.892Z",
    50        "version": "WzksMV0=",
    51        "namespaces": [
    52          "default"
    53        ],
    54        "score": 0
    55      }
    56    ]
    57  }`
    58  
    59  const openSearchDashboardsEP = "http://localhost:5601/"
    60  
    61  func TestUpdatePatterns(t *testing.T) {
    62  	vmiOSDEnabled := &vmcontrollerv1.VerrazzanoMonitoringInstance{
    63  		Spec: vmcontrollerv1.VerrazzanoMonitoringInstanceSpec{
    64  			Kibana: vmcontrollerv1.Kibana{
    65  				Enabled: true,
    66  			},
    67  		},
    68  	}
    69  	var tests = []struct {
    70  		name       string
    71  		httpFunc   func(request *http.Request) (*http.Response, error)
    72  		vmi        *vmcontrollerv1.VerrazzanoMonitoringInstance
    73  		successful bool
    74  	}{
    75  		{
    76  			"successful when all patterns updated without error",
    77  			func(request *http.Request) (*http.Response, error) {
    78  				if request.Method == "GET" {
    79  					return &http.Response{
    80  						StatusCode: http.StatusOK,
    81  						Body:       io.NopCloser(strings.NewReader(fakeGetPatternOutput)),
    82  					}, nil
    83  				}
    84  				return &http.Response{
    85  					StatusCode: http.StatusOK,
    86  					Body:       io.NopCloser(strings.NewReader("")),
    87  				}, nil
    88  			},
    89  			vmiOSDEnabled,
    90  			true,
    91  		},
    92  		{
    93  			"successful when OSD is disabled",
    94  			nil,
    95  			&vmcontrollerv1.VerrazzanoMonitoringInstance{},
    96  			true,
    97  		},
    98  		{
    99  			"unsuccessful when get patterns fails",
   100  			func(request *http.Request) (*http.Response, error) {
   101  				return &http.Response{
   102  					StatusCode: http.StatusServiceUnavailable,
   103  					Body:       io.NopCloser(strings.NewReader("boom!")),
   104  				}, nil
   105  			},
   106  			vmiOSDEnabled,
   107  			false,
   108  		},
   109  		{
   110  			"unsuccessful when update index fails",
   111  			func(request *http.Request) (*http.Response, error) {
   112  				if request.Method == "GET" {
   113  					return &http.Response{
   114  						StatusCode: http.StatusOK,
   115  						Body:       io.NopCloser(strings.NewReader(fakeGetPatternOutput)),
   116  					}, nil
   117  				}
   118  				return &http.Response{
   119  					StatusCode: http.StatusInternalServerError,
   120  					Body:       io.NopCloser(strings.NewReader("boom!")),
   121  				}, nil
   122  			},
   123  			vmiOSDEnabled,
   124  			false,
   125  		},
   126  	}
   127  
   128  	for _, tt := range tests {
   129  		t.Run(tt.name, func(t *testing.T) {
   130  			osd := NewOSDashboardsClient()
   131  			osd.DoHTTP = tt.httpFunc
   132  			err := osd.UpdatePatterns(vzlog.DefaultLogger(), tt.vmi)
   133  			assert.Equal(t, tt.successful, err == nil)
   134  		})
   135  	}
   136  }
   137  
   138  func TestExecuteUpdate(t *testing.T) {
   139  	var tests = []struct {
   140  		name       string
   141  		httpFunc   func(request *http.Request) (*http.Response, error)
   142  		successful bool
   143  	}{
   144  		{
   145  			"successful when PUT updated policy succeeds",
   146  			func(request *http.Request) (*http.Response, error) {
   147  				return &http.Response{
   148  					StatusCode: http.StatusOK,
   149  					Body:       io.NopCloser(strings.NewReader("")),
   150  				}, nil
   151  			},
   152  			true,
   153  		},
   154  		{
   155  			"unsuccessful when PUT updated policy fails",
   156  			func(request *http.Request) (*http.Response, error) {
   157  				return nil, errors.New("boom")
   158  			},
   159  			false,
   160  		},
   161  		{
   162  			"unsuccessful when PUT updated policy has HTTP error code",
   163  			func(request *http.Request) (*http.Response, error) {
   164  				return &http.Response{
   165  					StatusCode: http.StatusNotFound,
   166  					Body:       io.NopCloser(strings.NewReader("")),
   167  				}, nil
   168  			},
   169  			false,
   170  		},
   171  	}
   172  
   173  	for _, tt := range tests {
   174  		t.Run(tt.name, func(t *testing.T) {
   175  			osd := NewOSDashboardsClient()
   176  			osd.DoHTTP = tt.httpFunc
   177  			err := osd.executeUpdate(vzlog.DefaultLogger(), "http://localhost:5601", "id", "original", "updated")
   178  			assert.Equal(t, tt.successful, err == nil)
   179  		})
   180  	}
   181  }
   182  
   183  // TestGetPatterns tests the getPatterns function.
   184  func TestGetPatterns(t *testing.T) {
   185  	a := assert.New(t)
   186  
   187  	// GIVEN an OpenSearch Dashboards pod
   188  	//  WHEN getPatterns is called
   189  	//  THEN a command should be executed to get the index pattern information
   190  	//   AND then a map of index pattern id and title should be returned
   191  	od := NewOSDashboardsClient()
   192  	od.DoHTTP = func(request *http.Request) (*http.Response, error) {
   193  		return &http.Response{
   194  			StatusCode: http.StatusOK,
   195  			Body:       io.NopCloser(strings.NewReader(fakeGetPatternOutput)),
   196  		}, nil
   197  	}
   198  	savedObjects, err := od.getPatterns(openSearchDashboardsEP, 100)
   199  	a.NoError(err, "Failed to get patterns from OpenSearch Dashboards")
   200  	a.Equal(2, len(savedObjects))
   201  	a.Contains(savedObjects, SavedObject{
   202  		ID: "0f2ede70-8e15-11ec-abc1-6bc5e972b077",
   203  		Attributes: Attributes{
   204  			Title: "verrazzano-namespace-bobs-books",
   205  		},
   206  	})
   207  	a.Contains(savedObjects, SavedObject{
   208  		ID: "1cb7fcc0-8e15-11ec-abc1-6bc5e972b077",
   209  		Attributes: Attributes{
   210  			Title: "verrazzano-namespace-todo*",
   211  		},
   212  	})
   213  
   214  }
   215  
   216  func TestCreateIndexPatternPayload(t *testing.T) {
   217  	expected := `{"attributes":{"title":"my-pattern"}}`
   218  	actual := createIndexPatternPayload("my-pattern")
   219  	assert.Equal(t, expected, actual)
   220  }
   221  
   222  // TestConstructUpdatedPattern tests the constructUpdatedPattern function.
   223  func TestConstructUpdatedPattern(t *testing.T) {
   224  	asrt := assert.New(t)
   225  	pattern := constructUpdatedPattern("verrazzano-*")
   226  	asrt.Equal("verrazzano-*", pattern)
   227  	pattern = constructUpdatedPattern("verrazzano-namespace-bobs-books")
   228  	asrt.Equal("verrazzano-application-bobs-books", pattern)
   229  	pattern = constructUpdatedPattern("verrazzano-systemd-journal")
   230  	asrt.Equal("verrazzano-system", pattern)
   231  	pattern = constructUpdatedPattern("verrazzano-namespace-kube-system")
   232  	asrt.Equal("verrazzano-system", pattern)
   233  	pattern = constructUpdatedPattern("verrazzano-namespace-todo-*")
   234  	asrt.Equal("verrazzano-application-todo-*", pattern)
   235  	pattern = constructUpdatedPattern("verrazzano-namespace-s*,verrazzano-namespace-bobs-books")
   236  	asrt.Equal("verrazzano-application-s*,verrazzano-application-bobs-books", pattern)
   237  	pattern = constructUpdatedPattern("verrazzano-namespace-k*,verrazzano-namespace-sock-shop")
   238  	// As verrazzano-namespace-k* matches system index verrazzano-namespace-kube-system,
   239  	// system data stream name should also be added
   240  	asrt.Equal("verrazzano-system,verrazzano-application-k*,verrazzano-application-sock-shop", pattern)
   241  	pattern = constructUpdatedPattern("verrazzano-namespace-*")
   242  	assert.Equal(t, "verrazzano-system,verrazzano-application-*", pattern)
   243  }
   244  
   245  func TestIsSystemIndexMatch(t *testing.T) {
   246  	var tests = []struct {
   247  		pattern string
   248  		isMatch bool
   249  	}{
   250  		{
   251  			"not a system index",
   252  			false,
   253  		},
   254  		{
   255  			"verrazzano-logstash-*",
   256  			true,
   257  		},
   258  		{
   259  			"verrazzano-systemd-journal",
   260  			true,
   261  		},
   262  		{
   263  			"verrazzano-namespace-*",
   264  			true,
   265  		},
   266  	}
   267  
   268  	for _, tt := range tests {
   269  		t.Run(tt.pattern, func(t *testing.T) {
   270  			assert.Equal(t, tt.isMatch, isSystemIndexMatch(tt.pattern))
   271  		})
   272  	}
   273  }