github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/pkg/opensearch/opensearch_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 opensearch 5 6 import ( 7 "errors" 8 "io" 9 "net/http" 10 "strings" 11 "testing" 12 13 "github.com/stretchr/testify/assert" 14 vmcontrollerv1 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/apis/vmcontroller/v1" 15 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/config" 16 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/util/logs/vzlog" 17 ) 18 19 const fakeIndicesResponse = `{ 20 "verrazzano-namespace-dummyapp": { 21 "aliases": {} 22 }, 23 "verrazzano-namespace-testapp": { 24 "aliases": {} 25 }, 26 "verrazzano-namespace-metallb-system": { 27 "aliases": {} 28 }, 29 "verrazzano-namespace-verrazzano-system": { 30 "aliases": {} 31 }, 32 "verrazzano-systemd-journal": { 33 "aliases": {} 34 }, 35 "verrazzano-namespace-keycloak": { 36 "aliases": {} 37 }, 38 "verrazzano-namespace-local-path-storage": { 39 "aliases": {} 40 }, 41 "verrazzano-namespace-istio-system": { 42 "aliases": {} 43 }, 44 "verrazzano-namespace-ingress-nginx": { 45 "aliases": {} 46 }, 47 "verrazzano-namespace-cert-manager": { 48 "aliases": {} 49 }, 50 "verrazzano-namespace-kube-system": { 51 "aliases": {} 52 }, 53 "verrazzano-namespace-monitoring": { 54 "aliases": {} 55 }, 56 ".kibana_1": { 57 "aliases": { 58 ".kibana": {} 59 } 60 } 61 }` 62 63 const openSearchEP = "http://localhost:9200/" 64 65 // TestGetIndices tests that indices can be fetched from the OpenSearch server 66 // GIVEN an OpenSearch server with indices 67 // WHEN I call getIndices, getSystemIndices, and getApplicationIndices 68 // THEN I get back the expected indices, system indices, and application indices 69 func TestGetIndices(t *testing.T) { 70 o := NewOSClient(statefulSetLister) 71 o.DoHTTP = func(request *http.Request) (*http.Response, error) { 72 return &http.Response{ 73 StatusCode: http.StatusOK, 74 Body: io.NopCloser(strings.NewReader(fakeIndicesResponse)), 75 }, nil 76 } 77 log := vzlog.DefaultLogger() 78 indices, err := o.getIndices(log, openSearchEP) 79 assert.NoError(t, err) 80 assert.Contains(t, indices, "verrazzano-namespace-keycloak") 81 assert.Contains(t, indices, "verrazzano-namespace-istio-system") 82 assert.Equal(t, 13, len(indices)) 83 84 systemIndices := getSystemIndices(log, indices) 85 assert.Contains(t, systemIndices, "verrazzano-namespace-keycloak") 86 assert.Contains(t, systemIndices, "verrazzano-namespace-istio-system") 87 assert.Equal(t, 10, len(systemIndices)) 88 89 applicationIndices := getApplicationIndices(log, indices) 90 assert.Contains(t, applicationIndices, "verrazzano-namespace-testapp") 91 assert.Contains(t, applicationIndices, "verrazzano-namespace-dummyapp") 92 assert.Equal(t, 2, len(applicationIndices)) 93 } 94 95 // TestDataStreamExists Tests the expected data streams can be retrieved on an OpenSearch cluster 96 // GIVEN a cluster with data streams on it 97 // WHEN I call DataStreamExists 98 // THEN true is returned if the data stream is present 99 func TestDataStreamExists(t *testing.T) { 100 a := assert.New(t) 101 o := NewOSClient(statefulSetLister) 102 o.DoHTTP = func(request *http.Request) (*http.Response, error) { 103 if strings.Contains(request.URL.Path, config.DataStreamName()) { 104 return &http.Response{ 105 StatusCode: http.StatusOK, 106 Body: io.NopCloser(strings.NewReader("")), 107 }, nil 108 } 109 return &http.Response{ 110 StatusCode: http.StatusNotFound, 111 Body: io.NopCloser(strings.NewReader("")), 112 }, nil 113 } 114 exists, err := o.DataStreamExists(openSearchEP, config.DataStreamName()) 115 a.NoError(err) 116 a.True(exists) 117 exists, err = o.DataStreamExists(openSearchEP, "unknown") 118 a.NoError(err) 119 a.False(exists) 120 } 121 122 // TestCalculateSeconds Tests formatting of OpenSearch time units to seconds 123 // GIVEN an aribtrary time unit string 124 // WHEN I call calculateSeconds 125 // THEN the number of seconds that the time unit string represents is returned 126 func TestCalculateSeconds(t *testing.T) { 127 a := assert.New(t) 128 _, err := calculateSeconds("ww5s") 129 a.Error(err, "Error should be returned from exec") 130 _, err = calculateSeconds("12y") 131 a.Error(err, "should fail for 'months'") 132 _, err = calculateSeconds("10M") 133 a.Error(err, "should fail for 'months'") 134 seconds, err := calculateSeconds("6d") 135 a.NoError(err, "Should not fail for valid day unit") 136 a.Equal(uint64(518400), seconds) 137 seconds, err = calculateSeconds("120m") 138 a.NoError(err, "Should not fail for valid minute unit") 139 a.Equal(uint64(7200), seconds) 140 seconds, err = calculateSeconds("5h") 141 a.NoError(err, "Should not fail for valid hour unit") 142 a.Equal(uint64(18000), seconds) 143 seconds, err = calculateSeconds("20s") 144 a.NoError(err, "Should not fail for valid second unit") 145 a.Equal(uint64(20), seconds) 146 } 147 148 // TestReindexAndDeleteIndices Tests that indices are reindexed and deleted as expected 149 // GIVEN a cluster with indices to reindex 150 // WHEN I call reindexAndDeleteIndices 151 // THEN those indices are reindexed and deleted 152 func TestReindexAndDeleteIndices(t *testing.T) { 153 systemIndices := []string{"verrazzano-namespace-verrazzano-system"} 154 dummyOK := func(req *http.Request) (*http.Response, error) { 155 return &http.Response{ 156 StatusCode: http.StatusOK, 157 Body: io.NopCloser(strings.NewReader("")), 158 }, nil 159 } 160 var tests = []struct { 161 name string 162 indices []string 163 httpFunc func(req *http.Request) (*http.Response, error) 164 isSystemIndex bool 165 isError bool 166 }{ 167 { 168 "should reindex system indices", 169 systemIndices, 170 dummyOK, 171 true, 172 false, 173 }, 174 { 175 "should reindex application indices", 176 []string{"verrazzano-namespace-bobs-books", "verrazzano-namespace-todo-app"}, 177 dummyOK, 178 false, 179 false, 180 }, 181 { 182 "should fail when reindex fails", 183 systemIndices, 184 func(req *http.Request) (*http.Response, error) { 185 return nil, errors.New("BOOM") 186 }, 187 true, 188 true, 189 }, 190 { 191 "should fail when delete not found", 192 systemIndices, 193 func(req *http.Request) (*http.Response, error) { 194 if req.Method == "POST" { 195 return dummyOK(req) 196 } 197 return &http.Response{ 198 StatusCode: http.StatusNotFound, 199 Body: io.NopCloser(strings.NewReader("")), 200 }, nil 201 }, 202 true, 203 true, 204 }, 205 { 206 "should fail when delete fails", 207 systemIndices, 208 func(req *http.Request) (*http.Response, error) { 209 if req.Method == "POST" { 210 return dummyOK(req) 211 } 212 return nil, errors.New("BOOM") 213 }, 214 true, 215 true, 216 }, 217 { 218 "should fail when reindex 5xx", 219 systemIndices, 220 func(req *http.Request) (*http.Response, error) { 221 return &http.Response{ 222 StatusCode: http.StatusInternalServerError, 223 Body: io.NopCloser(strings.NewReader("")), 224 }, nil 225 }, 226 true, 227 true, 228 }, 229 } 230 vmi := createISMVMI("1d", true) 231 vmi.Spec.Elasticsearch.Policies = []vmcontrollerv1.IndexManagementPolicy{ 232 *createTestPolicy("1d", "1d", "verrazzano-*", "1d", 1), 233 } 234 for _, tt := range tests { 235 t.Run(tt.name, func(t *testing.T) { 236 o := NewOSClient(statefulSetLister) 237 o.DoHTTP = tt.httpFunc 238 err := o.reindexAndDeleteIndices(vzlog.DefaultLogger(), vmi, openSearchEP, tt.indices, tt.isSystemIndex) 239 if tt.isError { 240 assert.Error(t, err) 241 } else { 242 assert.NoError(t, err) 243 } 244 }) 245 } 246 } 247 248 // TestReindexToDataStream Tests reindexing an index to a data stream 249 // GIVENa cluster with an index to reindex 250 // WHEN I call reindexToDataStream 251 // THEN the index is reindex to a data stream 252 func TestReindexToDataStream(t *testing.T) { 253 o := NewOSClient(statefulSetLister) 254 o.DoHTTP = func(request *http.Request) (*http.Response, error) { 255 return &http.Response{ 256 StatusCode: http.StatusOK, 257 Body: io.NopCloser(strings.NewReader("")), 258 }, nil 259 } 260 err := o.reindexToDataStream(vzlog.DefaultLogger(), openSearchEP, "src", "dest", "1s") 261 assert.NoError(t, err) 262 }