github.com/verrazzano/verrazzano@v1.7.0/pkg/bom/bom_test.go (about) 1 // Copyright (c) 2021, 2023, 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 bom 5 6 import ( 7 "fmt" 8 "github.com/stretchr/testify/assert" 9 "testing" 10 ) 11 12 const ( 13 ingressControllerComponent = "ingress-controller" 14 ingressControllerImageName = "nginx-ingress-controller" 15 ) 16 17 // testSubComponent contains the override Key values for a subcomponent. 18 type testSubComponent struct { 19 // kvs is the map of helm Key to expected helm Value. These values are used in helm overrides 20 // for the subcomponent chart 21 kvs map[string]string 22 } 23 24 // testSubcomponetHelmKeyValues are the Key:values pairs that will be passed to helm as overrides. 25 // The map Key is the subcomponent name. 26 // This list of subcomponents is in the verrazzano-bom.json file and it must stay in sync with that file 27 // Keep this map in the same order as that JSON for review purposes. 28 var testSubcomponetHelmKeyValues = map[string]*testSubComponent{ 29 "verrazzano-platform-operator": { 30 kvs: map[string]string{ 31 "image": "ghcr.io/verrazzano/VERRAZZANO_PLATFORM_OPERATOR_IMAGE:VERRAZZANO_PLATFORM_OPERATOR_TAG", 32 }, 33 }, 34 "cert-manager": { 35 kvs: map[string]string{ 36 "image.repository": "ghcr.io/verrazzano/cert-manager-controller", 37 "image.tag": "0.13.1-20201016205232-4c8f3fe38", 38 "extraArgs[0]=--acme-http01-solver-image": "ghcr.io/verrazzano/cert-manager-acmesolver:0.13.1-20201016205234-4c8f3fe38", 39 "webhook.image.repository": "ghcr.io/verrazzano/cert-manager-webhook", 40 "webhook.image.tag": "1.2.0-20210602163405-aac6bdf62", 41 "cainjector.image.repository": "ghcr.io/verrazzano/cert-manager-cainjector", 42 "cainjector.image.tag": "1.2.0-20210602163405-aac6bdf62", 43 }, 44 }, 45 ingressControllerComponent: { 46 kvs: map[string]string{ 47 "controller.image.repository": "ghcr.io/verrazzano/nginx-ingress-controller", 48 "controller.image.tag": "0.46.0-20210510134749-abc2d2088", 49 "defaultBackend.image.repository": "ghcr.io/verrazzano/nginx-ingress-default-backend", 50 "defaultBackend.image.tag": "0.46.0-20210510134749-abc2d2088", 51 }, 52 }, 53 "external-dns": { 54 kvs: map[string]string{ 55 "image.repository": "verrazzano/external-dns", 56 "image.registry": "ghcr.io", 57 "image.tag": "v0.7.1-20201016205338-516bc8b2", 58 }, 59 }, 60 "istiocoredns": { 61 kvs: map[string]string{ 62 "istiocoredns.coreDNSImage": "ghcr.io/verrazzano/coredns", 63 "istiocoredns.coreDNSTag": "1.6.2", 64 "istiocoredns.coreDNSPluginImage": "ghcr.io/verrazzano/istio-coredns-plugin:0.2-20201016204812-23723dcb", 65 }, 66 }, 67 "istiod": { 68 kvs: map[string]string{ 69 "pilot.image": "ghcr.io/verrazzano/pilot:1.7.3", 70 "global.proxy.image": "proxyv2", 71 "global.tag": "1.7.3", 72 }, 73 }, 74 "istio-ingress": { 75 kvs: map[string]string{ 76 "global.proxy.image": "proxyv2", 77 "global.tag": "1.7.3", 78 }, 79 }, 80 "istio-egress": { 81 kvs: map[string]string{ 82 "global.proxy.image": "proxyv2", 83 "global.tag": "1.7.3", 84 }, 85 }, 86 "rancher": { 87 kvs: map[string]string{ 88 "rancherImage": "ghcr.io/verrazzano/rancher", 89 "rancherImageTag": "v2.5.7-20210407205410-1c7b39d0c", 90 }, 91 }, 92 // NOTE additional-rancher images are not used by the local rancher helm chart used by verrazzano 93 // so ignore those entries 94 95 "verrazzano": { 96 kvs: map[string]string{ 97 "monitoringOperator.imageName": "ghcr.io/verrazzano/verrazzano-monitoring-operator", 98 "monitoringOperator.imageVersion": "0.15.0-20210521020822-9b87485", 99 "monitoringOperator.istioProxyImage": "ghcr.io/verrazzano/proxyv2:1.7.3", 100 "monitoringOperator.grafanaImage": "ghcr.io/verrazzano/grafana:v6.4.4", 101 "monitoringOperator.prometheusImage": "ghcr.io/verrazzano/prometheus:v2.13.1", 102 "monitoringOperator.osImage": "ghcr.io/verrazzano/opensearch:2.3.0-20230123213036-bd387046f04", 103 "monitoringOperator.osdImage": "ghcr.io/verrazzano/opensearch-dashboards:2.3.0-20230124171546-f9e6353395", 104 "monitoringOperator.oidcProxyImage": "ghcr.io/verrazzano/nginx-ingress-controller:0.46.0-20210510134749-abc2d2088", 105 "api.imageName": "ghcr.io/verrazzano/nginx-ingress-controller", 106 "api.imageVersion": "0.46.0-20210510134749-abc2d2088", 107 }, 108 }, 109 "monitoring-init-images": { 110 kvs: map[string]string{ 111 "monitoringOperator.osInitImage": "ghcr.io/oracle/oraclelinux:7.8", 112 }, 113 }, 114 "oam-kubernetes-runtime": { 115 kvs: map[string]string{ 116 "image.repository": "ghcr.io/verrazzano/oam-kubernetes-runtime", 117 "image.tag": "v0.3.0-20210222205541-9e8d4fb", 118 }, 119 }, 120 "verrazzano-application-operator": { 121 kvs: map[string]string{ 122 "image": "ghcr.io/verrazzano/VERRAZZANO_APPLICATION_OPERATOR_IMAGE:VERRAZZANO_APPLICATION_OPERATOR_TAG", 123 "fluentdImage": "ghcr.io/verrazzano/fluentd-kubernetes-daemonset:v1.12.3-20210517195222-f345ec2", 124 }, 125 }, 126 "weblogic-operator": { 127 kvs: map[string]string{ 128 "image": "ghcr.io/oracle/weblogic-kubernetes-operator:3.2.2", 129 "weblogicMonitoringExporterImage": "ghcr.io/oracle/weblogic-monitoring-exporter:2.0.7", 130 }, 131 }, 132 "coherence-operator": { 133 kvs: map[string]string{ 134 "image": "ghcr.io/oracle/coherence-operator:3.1.3", 135 }, 136 }, 137 "mysql": { 138 kvs: map[string]string{ 139 "image": "ghcr.io/verrazzano/mysql", 140 "imageTag": "8.0.20", 141 }, 142 }, 143 "oraclelinux": { 144 kvs: map[string]string{ 145 "busybox.image": "ghcr.io/oracle/oraclelinux", 146 "busybox.tag": "7-slim", 147 }, 148 }, 149 "keycloak": { 150 kvs: map[string]string{ 151 "keycloak.image.repository": "ghcr.io/verrazzano/keycloak", 152 "keycloak.image.tag": "10.0.1-20201016212759-30d98b0", 153 }, 154 }, 155 "keycloak-oracle-theme": { 156 kvs: map[string]string{ 157 "image": "ghcr.io/verrazzano/keycloak-oracle-theme:0.15.0-20210510085250-01638c7", 158 }, 159 }, 160 "fluentd": { 161 kvs: map[string]string{ 162 "logging.fluentdImage": "ghcr.io/verrazzano/fluentd-kubernetes-daemonset:v1.14.5-20230810212038-8777b84", 163 }, 164 }, 165 "verrazzano-console": { 166 kvs: map[string]string{ 167 "imageName": "ghcr.io/verrazzano/console", 168 "imageTag": "v2.0.0-20230912070053-2d1883d", 169 }, 170 }, 171 } 172 173 // This is the real BOM file path needed for unit tests 174 const realBomFilePath = "testdata/verrazzano-bom.json" 175 const testBomFilePath = "testdata/test_bom.json" 176 const testBomSubcomponentOverridesPath = "testdata/test_bom_sc_overrides.json" 177 const testBomImageOverridesPath = "testdata/test_bom_image_overrides.json" 178 179 // TestFakeBom tests loading a fake bom json into a struct 180 // GIVEN a json file 181 // WHEN I call loadBom 182 // THEN the correct Verrazzano bom is returned 183 func TestFakeBom(t *testing.T) { 184 assert := assert.New(t) 185 bom, err := NewBom(testBomFilePath) 186 assert.NoError(err, "error calling NewBom") 187 assert.Equal("ghcr.io", bom.bomDoc.Registry, "Wrong registry name") 188 assert.Len(bom.bomDoc.Components, 16, "incorrect number of Bom components") 189 190 validateImages(assert, &bom, true) 191 } 192 193 // TestRealBom tests loading the real bom json into a struct 194 // GIVEN a json file 195 // WHEN I call loadBom 196 // THEN the correct Verrazzano bom is returned 197 func TestRealBom(t *testing.T) { 198 assert := assert.New(t) 199 bom, err := NewBom(realBomFilePath) 200 assert.NoError(err, "error calling NewBom") 201 assert.Equal("ghcr.io", bom.bomDoc.Registry, "Wrong registry name") 202 assert.Len(bom.bomDoc.Components, 16, "incorrect number of Bom components") 203 204 // Ignore the values in the real bom file since some will change every build 205 validateImages(assert, &bom, false) 206 } 207 208 // validateImages validates the images in the subcomponents. 209 // Optional check the image Value. 210 func validateImages(assert *assert.Assertions, bom *Bom, checkImageVal bool) { 211 // Validate each component 212 for _, comp := range bom.bomDoc.Components { 213 for _, sub := range comp.SubComponents { 214 // Get the expected Key:Value pair overrides for this subcomponent 215 expectedSub := testSubcomponetHelmKeyValues[sub.Name] 216 if expectedSub == nil { 217 fmt.Println("Skipping subcomponent " + sub.Name) 218 continue 219 } 220 221 // Get the actual Key Value override list for this subcomponent 222 foundKvs, err := bom.BuildImageOverrides(sub.Name) 223 assert.NoError(err, "error calling BuildImageOverrides") 224 assert.Equal(len(expectedSub.kvs), len(foundKvs), "Incorrect override list len for "+sub.Name) 225 226 // Loop through the found kv pairs and make sure the actual kvs match the expected 227 for _, kv := range foundKvs { 228 expectedVal, ok := expectedSub.kvs[kv.Key] 229 assert.True(ok, "Found unexpected Key in override list for "+sub.Name) 230 if checkImageVal { 231 assert.Equal(expectedVal, kv.Value, "Found unexpected Value in override list for "+sub.Name) 232 } 233 } 234 } 235 } 236 } 237 238 // TestBomSubcomponentOverrides the ability to override registry and repo settings at the subcomponent level 239 // GIVEN a json file where a subcomponent overrides the registry and repository location of its images 240 // WHEN I load it and check those settings 241 // THEN the correct overrides are present without affecting the global registry setting 242 func TestBomSubcomponentOverrides(t *testing.T) { 243 assert := assert.New(t) 244 bom, err := NewBom(testBomSubcomponentOverridesPath) 245 assert.Equal("ghcr.io", bom.GetRegistry(), "Global registry not correct") 246 assert.NoError(err) 247 248 nginxSubcomponent, err := bom.GetSubcomponent(ingressControllerComponent) 249 assert.NotNil(t, nginxSubcomponent) 250 assert.NoError(err) 251 252 assert.Equal("ghcr.io", bom.GetRegistry(), "Global registry not correct") 253 assert.Equal("myreg.io", bom.ResolveRegistry(nginxSubcomponent, BomImage{}), "NGINX subcomponent registry not correct") 254 assert.Equal("myrepoprefix/testnginx", bom.ResolveRepo(nginxSubcomponent, BomImage{}), "NGINX subcomponent repo not correct") 255 256 vpoSubcomponent, err := bom.GetSubcomponent("verrazzano-platform-operator") 257 assert.NotNil(t, vpoSubcomponent) 258 assert.NoError(err) 259 260 assert.Equal("ghcr.io", bom.ResolveRegistry(vpoSubcomponent, BomImage{}), "VPO subcomponent registry not correct") 261 assert.Equal("verrazzano", bom.ResolveRepo(vpoSubcomponent, BomImage{}), "VPO subcomponent repo not correct") 262 } 263 264 // TestBomImageOverrides tests the ability to override the registry settings for a subcomponent 265 // GIVEN a call to ResolveRegistry and ResolveRepo for a valid subcomponent 266 // WHEN the image has overrides for the registry and repository 267 // THEN the correct registry and repository overrides are returned 268 func TestBomImageOverrides(t *testing.T) { 269 bom, err := NewBom(testBomImageOverridesPath) 270 assert.NoError(t, err) 271 assert.Equal(t, "ghcr.io", bom.GetRegistry()) 272 sc, err := bom.GetSubcomponent("verrazzano-platform-operator") 273 assert.NoError(t, err) 274 img := sc.Images[0] 275 assert.Equal(t, "testRegistry", bom.ResolveRegistry(sc, img)) 276 assert.Equal(t, "testRepository", bom.ResolveRepo(sc, img)) 277 } 278 279 // TestBomFindImage tests the FindImage method 280 // GIVEN a call to FindImage for a valid subcomponent 281 // WHEN I ask for an image for that subcomponent 282 // THEN the correct BomImage object is returned if found, or an error if not found 283 func TestBomFindImage(t *testing.T) { 284 bom, err := NewBom(testBomFilePath) 285 assert.NoError(t, err) 286 287 _, err = bom.FindImage(ingressControllerComponent, ingressControllerImageName) 288 assert.NoError(t, err) 289 290 _, err = bom.FindImage(ingressControllerComponent, "foo") 291 assert.Error(t, err) 292 } 293 294 // TestBomComponentVersion tests the ability to fetch component version 295 func TestBomComponentVersion(t *testing.T) { 296 bom, err := NewBom(realBomFilePath) 297 assert.NoError(t, err) 298 c, err := bom.GetComponent("verrazzano") 299 assert.NoError(t, err) 300 assert.NotNil(t, c) 301 assert.NotNil(t, c.Version) 302 } 303 304 // TestBomGetComponentVersion tests the GetComponentVersion method 305 // GIVEN a call to GetComponentVersion for a valid component 306 // WHEN I ask for the version of that component 307 // THEN the correct version is returned if found, or an error if not found 308 func TestBomGetComponentVersion(t *testing.T) { 309 bom, err := NewBom(testBomFilePath) 310 assert.NoError(t, err) 311 312 ver, err := bom.GetComponentVersion("cert-manager") 313 assert.NoError(t, err) 314 assert.Equal(t, ver, "v1.7.1") 315 316 ver, err = bom.GetComponentVersion("foo") 317 assert.Error(t, err) 318 assert.Equal(t, ver, "") 319 } 320 321 // TestGetSubcomponentImages tests the GetSubcomponentImages method 322 // GIVEN a call to GetSubcomponentImages for a valid subcomponent 323 // WHEN I ask for the images of that component 324 // THEN the correct images are returned if found, or an error if not found 325 func TestGetSubcomponentImages(t *testing.T) { 326 bom, err := NewBom(testBomFilePath) 327 assert.NoError(t, err) 328 subComponentImageforNil := []BomImage([]BomImage(nil)) 329 subComponentImage := []BomImage([]BomImage{{ImageName: "external-dns", ImageTag: "v0.7.1-20201016205338-516bc8b2", Registry: "", Repository: "", HelmRegistryKey: "image.registry", HelmRepoKey: "", HelmImageKey: "", HelmTagKey: "image.tag", HelmFullImageKey: "image.repository", HelmRegistryAndRepoKey: ""}}) 330 scImages, err := bom.GetSubcomponentImages("external-dns") 331 assert.NoError(t, err) 332 assert.Equal(t, scImages, subComponentImage) 333 334 scImages, err = bom.GetSubcomponentImages("foo") 335 assert.Error(t, err) 336 assert.Equal(t, scImages, subComponentImageforNil) 337 } 338 339 // TestBomGetSubcomponentImageCount tests the GetSubcomponentImageCount method 340 // GIVEN a call to GetSubcomponentImageCount for a valid subcomponent 341 // WHEN I ask for the number of images of that component 342 // THEN the correct number is returned if found, or zero if not found 343 func TestGetSubcomponentImageCount(t *testing.T) { 344 bom, err := NewBom(testBomFilePath) 345 assert.NoError(t, err) 346 347 imageNum := bom.GetSubcomponentImageCount("foo") 348 assert.Equal(t, imageNum, 0) 349 350 imageNum = bom.GetSubcomponentImageCount(ingressControllerComponent) 351 assert.Equal(t, imageNum, 2) 352 353 }