1// Copyright 2019 Istio Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package metrics 16 17import ( 18 "fmt" 19 "testing" 20 21 "istio.io/istio/pkg/test/framework" 22 "istio.io/istio/pkg/test/framework/components/bookinfo" 23 "istio.io/istio/pkg/test/framework/components/galley" 24 "istio.io/istio/pkg/test/framework/components/ingress" 25 "istio.io/istio/pkg/test/framework/components/istio" 26 "istio.io/istio/pkg/test/framework/components/mixer" 27 "istio.io/istio/pkg/test/framework/components/namespace" 28 "istio.io/istio/pkg/test/framework/components/prometheus" 29 "istio.io/istio/pkg/test/framework/label" 30 "istio.io/istio/pkg/test/framework/resource" 31 "istio.io/istio/pkg/test/framework/resource/environment" 32 "istio.io/istio/pkg/test/util/tmpl" 33 util "istio.io/istio/tests/integration/mixer" 34) 35 36var ( 37 ist istio.Instance 38 bookinfoNs namespace.Instance 39 g galley.Instance 40 ing ingress.Instance 41 prom prometheus.Instance 42) 43 44// This file contains Mixer tests that are ported from Mixer E2E tests 45 46// Port of TestMetric 47func TestIngessToPrometheus_ServiceMetric(t *testing.T) { 48 framework. 49 NewTest(t). 50 // TODO(https://github.com/istio/istio/issues/14819) 51 Label(label.Flaky). 52 RequiresEnvironment(environment.Kube). 53 Run(func(ctx framework.TestContext) { 54 label := "source_workload" 55 labelValue := "istio-ingressgateway" 56 testMetric(t, ctx, label, labelValue) 57 }) 58} 59 60// Port of TestMetric 61func TestIngessToPrometheus_IngressMetric(t *testing.T) { 62 framework. 63 NewTest(t). 64 RequiresEnvironment(environment.Kube). 65 Run(func(ctx framework.TestContext) { 66 ctx.NewSubTest("SetupAndPrometheus"). 67 Run(func(ctx framework.TestContext) { 68 label := "destination_service" 69 labelValue := "productpage.{{.TestNamespace}}.svc.cluster.local" 70 testMetric(t, ctx, label, labelValue) 71 }) 72 73 ctx.NewSubTest("IstioctlPrometheusConnection"). 74 Run(func(ctx framework.TestContext) { 75 workload := "productpage-v1" 76 testIstioctl(t, ctx, workload) 77 }) 78 }) 79} 80 81func testMetric(t *testing.T, ctx framework.TestContext, label string, labelValue string) { // nolint:interfacer 82 t.Helper() 83 g.ApplyConfigOrFail( 84 t, 85 bookinfoNs, 86 bookinfo.GetDestinationRuleConfigFileOrFail(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 87 bookinfo.NetworkingVirtualServiceAllV1.LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 88 ) 89 defer g.DeleteConfigOrFail(t, 90 bookinfoNs, 91 bookinfo.GetDestinationRuleConfigFileOrFail(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 92 bookinfo.NetworkingVirtualServiceAllV1.LoadWithNamespaceOrFail(t, bookinfoNs.Name())) 93 94 util.AllowRuleSync(t) 95 96 // Warm up 97 addr := ing.HTTPAddress() 98 url := fmt.Sprintf("http://%s/productpage", addr.String()) 99 res := util.SendTraffic(ing, t, "Sending traffic", url, "", 10) 100 if res.RetCodes[200] < 1 { 101 t.Fatalf("unable to retrieve 200 from product page: %v", res.RetCodes) 102 } 103 104 label = tmpl.EvaluateOrFail(t, label, map[string]string{"TestNamespace": bookinfoNs.Name()}) 105 labelValue = tmpl.EvaluateOrFail(t, labelValue, map[string]string{"TestNamespace": bookinfoNs.Name()}) 106 107 // Wait for some data to arrive. 108 initial, err := prom.WaitForQuiesce(`istio_requests_total{%s=%q,response_code="200"}`, label, labelValue) 109 if err != nil { 110 t.Fatal(err) 111 } 112 t.Logf("Baseline established: initial = %v", initial) 113 114 res = util.SendTraffic(ing, t, "Sending traffic", url, "", 10) 115 if res.RetCodes[200] < 1 { 116 t.Fatalf("unable to retrieve 200 from product page: %v", res.RetCodes) 117 } 118 119 final, err := prom.WaitForQuiesce(`istio_requests_total{%s=%q,response_code="200"}`, label, labelValue) 120 if err != nil { 121 t.Fatal(err) 122 } 123 t.Logf("Quiesced to: final = %v", final) 124 125 metricName := "istio_requests_total" 126 i, err := prom.Sum(initial, nil) 127 if err != nil { 128 t.Logf("prometheus values for %s:\n%s", metricName, util.PromDump(prom, metricName)) 129 t.Fatal(err) 130 } 131 132 f, err := prom.Sum(final, nil) 133 if err != nil { 134 t.Logf("prometheus values for %s:\n%s", metricName, util.PromDump(prom, metricName)) 135 t.Fatal(err) 136 } 137 138 // We should see 10 requests but giving an error of 1, to make test less flaky. 139 if (f - i) < float64(9) { 140 t.Errorf("Bad metric value: got %f, want at least 9", f-i) 141 } 142} 143 144// Port of TestTcpMetric 145func TestTcpMetric(t *testing.T) { 146 framework. 147 NewTest(t). 148 // TODO(https://github.com/istio/istio/issues/18105) 149 Label(label.Flaky). 150 RequiresEnvironment(environment.Kube). 151 Run(func(ctx framework.TestContext) { 152 _ = bookinfo.DeployOrFail(t, ctx, bookinfo.Config{Namespace: bookinfoNs, Cfg: bookinfo.BookinfoRatingsv2}) 153 _ = bookinfo.DeployOrFail(t, ctx, bookinfo.Config{Namespace: bookinfoNs, Cfg: bookinfo.BookinfoDB}) 154 155 g.ApplyConfigOrFail( 156 t, 157 bookinfoNs, 158 bookinfo.GetDestinationRuleConfigFileOrFail(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 159 bookinfo.NetworkingTCPDbRule.LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 160 ) 161 defer g.DeleteConfigOrFail( 162 t, 163 bookinfoNs, 164 bookinfo.GetDestinationRuleConfigFileOrFail(t, ctx).LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 165 bookinfo.NetworkingTCPDbRule.LoadWithNamespaceOrFail(t, bookinfoNs.Name()), 166 ) 167 168 util.AllowRuleSync(t) 169 170 addr := ing.HTTPAddress() 171 url := fmt.Sprintf("http://%s/productpage", addr.String()) 172 res := util.SendTraffic(ing, t, "Sending traffic", url, "", 10) 173 if res.RetCodes[200] < 1 { 174 t.Fatalf("unable to retrieve 200 from product page: %v", res.RetCodes) 175 } 176 177 query := fmt.Sprintf("sum(istio_tcp_sent_bytes_total{destination_app=\"%s\"})", "mongodb") 178 util.ValidateMetric(t, prom, query, "istio_tcp_sent_bytes_total", 1) 179 180 query = fmt.Sprintf("sum(istio_tcp_received_bytes_total{destination_app=\"%s\"})", "mongodb") 181 util.ValidateMetric(t, prom, query, "istio_tcp_received_bytes_total", 1) 182 183 query = fmt.Sprintf("sum(istio_tcp_connections_opened_total{destination_app=\"%s\"})", "mongodb") 184 util.ValidateMetric(t, prom, query, "istio_tcp_connections_opened_total", 1) 185 186 query = fmt.Sprintf("sum(istio_tcp_connections_closed_total{destination_app=\"%s\"})", "mongodb") 187 util.ValidateMetric(t, prom, query, "istio_tcp_connections_closed_total", 1) 188 }) 189} 190 191func TestMain(m *testing.M) { 192 framework. 193 NewSuite("mixer_telemetry_metrics", m). 194 RequireEnvironment(environment.Kube). 195 RequireSingleCluster(). 196 Label(label.CustomSetup). 197 SetupOnEnv(environment.Kube, istio.Setup(&ist, func(cfg *istio.Config) { 198 cfg.ControlPlaneValues = ` 199values: 200 prometheus: 201 enabled: true 202 global: 203 disablePolicyChecks: false 204 telemetry: 205 v1: 206 enabled: true 207 v2: 208 enabled: false 209components: 210 policy: 211 enabled: true 212 telemetry: 213 enabled: true` 214 })). 215 Setup(testsetup). 216 Run() 217} 218 219func testsetup(ctx resource.Context) (err error) { 220 bookinfoNs, err = namespace.New(ctx, namespace.Config{ 221 Prefix: "istio-bookinfo", 222 Inject: true, 223 }) 224 if err != nil { 225 return 226 } 227 if _, err := bookinfo.Deploy(ctx, bookinfo.Config{Namespace: bookinfoNs, Cfg: bookinfo.BookInfo}); err != nil { 228 return err 229 } 230 g, err = galley.New(ctx, galley.Config{}) 231 if err != nil { 232 return err 233 } 234 if _, err = mixer.New(ctx, mixer.Config{Galley: g}); err != nil { 235 return err 236 } 237 ing, err = ingress.New(ctx, ingress.Config{Istio: ist}) 238 if err != nil { 239 return err 240 } 241 prom, err = prometheus.New(ctx, prometheus.Config{}) 242 if err != nil { 243 return err 244 } 245 yamlText, err := bookinfo.NetworkingBookinfoGateway.LoadGatewayFileWithNamespace(bookinfoNs.Name()) 246 if err != nil { 247 return err 248 } 249 err = g.ApplyConfig(bookinfoNs, yamlText) 250 if err != nil { 251 return err 252 } 253 254 return nil 255} 256