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 }