From c8eb953db1cf538fb5dfd36d47d86300aa918ce3 Mon Sep 17 00:00:00 2001 From: Jesse Suen Date: Fri, 12 Feb 2021 18:10:13 -0800 Subject: [PATCH] feat: support canarying using Istio DestinationRule subsets (#985) Signed-off-by: Jesse Suen --- .github/workflows/e2e.yaml | 4 +- cmd/rollouts-controller/main.go | 26 +- controller/controller.go | 21 +- .../istio-service-metrics.png | Bin 0 -> 272003 bytes .../istio-workload-metrics.png | Bin 0 -> 213514 bytes docs/features/traffic-management/istio.md | 340 +- docs/getting-started/setup/index.md | 2 +- docs/roadmap.md | 78 +- go.mod | 2 + go.sum | 3 + manifests/crds/rollout-crd.yaml | 13 + manifests/install.yaml | 15 + manifests/namespace-install.yaml | 15 + manifests/role/argo-rollouts-clusterrole.yaml | 4 +- metricproviders/datadog/datadog.go | 20 +- metricproviders/newrelic/newrelic.go | 21 +- metricproviders/wavefront/wavefront.go | 21 +- .../rollouts/v1alpha1/openapi_generated.go | 64 +- pkg/apis/rollouts/v1alpha1/types.go | 14 +- .../v1alpha1/zz_generated.deepcopy.go | 21 + pkg/apis/rollouts/validation/validation.go | 12 +- rollout/controller.go | 171 +- rollout/controller_test.go | 30 +- rollout/mocks/TrafficRoutingReconciler.go | 14 + rollout/trafficrouting.go | 22 +- rollout/trafficrouting/alb/alb.go | 5 + rollout/trafficrouting/istio/controller.go | 290 ++ .../trafficrouting/istio/controller_test.go | 200 + rollout/trafficrouting/istio/istio.go | 277 +- rollout/trafficrouting/istio/istio_test.go | 328 +- rollout/trafficrouting/istio/istio_types.go | 50 + rollout/trafficrouting/nginx/nginx.go | 5 + rollout/trafficrouting/smi/smi.go | 19 +- rollout/trafficrouting/smi/smi_test.go | 34 +- rollout/trafficrouting_test.go | 32 +- service/service.go | 40 +- service/service_test.go | 8 + test/e2e/crds/README.md | 3 + test/e2e/crds/istio.yaml | 3448 +++++++++++++++++ test/e2e/istio/istio-host-split.yaml | 81 + test/e2e/istio/istio-subset-split.yaml | 85 + test/e2e/istio/load-test-job.yaml | 21 + test/e2e/istio_test.go | 144 + test/fixtures/common.go | 56 + test/fixtures/e2e_suite.go | 19 +- test/fixtures/when.go | 28 + utils/controller/controller.go | 14 +- utils/controller/controller_test.go | 12 +- utils/defaults/defaults.go | 24 + utils/istio/istio.go | 50 +- utils/istio/istio_test.go | 69 +- 51 files changed, 5772 insertions(+), 503 deletions(-) create mode 100644 docs/features/traffic-management/istio-service-metrics.png create mode 100644 docs/features/traffic-management/istio-workload-metrics.png create mode 100644 rollout/trafficrouting/istio/controller.go create mode 100644 rollout/trafficrouting/istio/controller_test.go create mode 100644 rollout/trafficrouting/istio/istio_types.go create mode 100644 test/e2e/crds/README.md create mode 100644 test/e2e/crds/istio.yaml create mode 100644 test/e2e/istio/istio-host-split.yaml create mode 100644 test/e2e/istio/istio-subset-split.yaml create mode 100644 test/e2e/istio/load-test-job.yaml create mode 100644 test/e2e/istio_test.go diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 6b381c4281..1f7e093535 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -31,7 +31,9 @@ jobs: - name: Download cache run: go mod download - name: Install CRDs - run: kubectl apply -k manifests/crds + run: | + kubectl apply -k manifests/crds + kubectl apply -f test/e2e/crds - name: Start controller run: make start-e2e & - name: Run e2e tests diff --git a/cmd/rollouts-controller/main.go b/cmd/rollouts-controller/main.go index f50ac53ce2..d666c73fc8 100644 --- a/cmd/rollouts-controller/main.go +++ b/cmd/rollouts-controller/main.go @@ -27,7 +27,10 @@ import ( clientset "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned" "github.com/argoproj/argo-rollouts/pkg/signals" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/alb" + "github.com/argoproj/argo-rollouts/rollout/trafficrouting/smi" controllerutil "github.com/argoproj/argo-rollouts/utils/controller" + "github.com/argoproj/argo-rollouts/utils/defaults" + "github.com/argoproj/argo-rollouts/utils/istio" istioutil "github.com/argoproj/argo-rollouts/utils/istio" kubeclientmetrics "github.com/argoproj/argo-rollouts/utils/kubeclientmetrics" "github.com/argoproj/argo-rollouts/utils/tolerantinformer" @@ -35,9 +38,7 @@ import ( const ( // CLIName is the name of the CLI - cliName = "argo-rollouts" - defaultIstioVersion = "v1alpha3" - defaultTrafficSplitVersion = "v1alpha1" + cliName = "argo-rollouts" ) func newCommand() *cobra.Command { @@ -75,6 +76,8 @@ func newCommand() *cobra.Command { stopCh := signals.SetupSignalHandler() alb.SetDefaultVerifyWeight(albVerifyWeight) + istio.SetIstioAPIVersion(istioVersion) + smi.SetSMIAPIVersion(trafficSplitVersion) config, err := clientConfig.ClientConfig() checkError(err) @@ -111,7 +114,6 @@ func newCommand() *cobra.Command { kubeinformers.WithTweakListOptions(func(options *metav1.ListOptions) { options.LabelSelector = jobprovider.AnalysisRunUIDLabelKey })) - istioGVR := istioutil.GetIstioGVR(istioVersion) // We need three dynamic informer factories: // 1. The first is the dynamic informer for rollouts, analysisruns, analysistemplates, experiments dynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, resyncDuration, namespace, instanceIDTweakListFunc) @@ -120,9 +122,8 @@ func newCommand() *cobra.Command { // is to support the mode when the rollout controller is started and only operating against // a single namespace (i.e. rollouts-controller --namespace foo). clusterDynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, resyncDuration, metav1.NamespaceAll, instanceIDTweakListFunc) - // 3. We finally need an istio dynamic informer factory which uses different resync - // period and does not use a tweakListFunc. - istioDynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, 0, namespace, nil) + // 3. We finally need an istio dynamic informer factory which does not use a tweakListFunc. + istioDynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynamicClient, resyncDuration, namespace, nil) cm := controller.NewManager( namespace, kubeClient, @@ -138,13 +139,12 @@ func newCommand() *cobra.Command { tolerantinformer.NewTolerantAnalysisRunInformer(dynamicInformerFactory), tolerantinformer.NewTolerantAnalysisTemplateInformer(dynamicInformerFactory), tolerantinformer.NewTolerantClusterAnalysisTemplateInformer(clusterDynamicInformerFactory), - istioDynamicInformerFactory.ForResource(istioGVR).Informer(), + istioDynamicInformerFactory.ForResource(istioutil.GetIstioVirtualServiceGVR()).Informer(), + istioDynamicInformerFactory.ForResource(istioutil.GetIstioDestinationRuleGVR()).Informer(), resyncDuration, instanceID, metricsPort, k8sRequestProvider, - istioVersion, - trafficSplitVersion, nginxIngressClasses, albIngressClasses) // notice that there is no need to run Start methods in a separate goroutine. (i.e. go kubeInformerFactory.Start(stopCh) @@ -157,7 +157,7 @@ func newCommand() *cobra.Command { jobInformerFactory.Start(stopCh) // Check if Istio installed on cluster before starting dynamicInformerFactory - if istioutil.DoesIstioExist(dynamicClient, namespace, istioVersion) { + if istioutil.DoesIstioExist(dynamicClient, namespace) { istioDynamicInformerFactory.Start(stopCh) } @@ -183,8 +183,8 @@ func newCommand() *cobra.Command { command.Flags().IntVar(&analysisThreads, "analysis-threads", controller.DefaultAnalysisThreads, "Set the number of worker threads for the Experiment controller") command.Flags().IntVar(&serviceThreads, "service-threads", controller.DefaultServiceThreads, "Set the number of worker threads for the Service controller") command.Flags().IntVar(&ingressThreads, "ingress-threads", controller.DefaultIngressThreads, "Set the number of worker threads for the Ingress controller") - command.Flags().StringVar(&istioVersion, "istio-api-version", defaultIstioVersion, "Set the default Istio apiVersion that controller should look when manipulating VirtualServices.") - command.Flags().StringVar(&trafficSplitVersion, "traffic-split-api-version", defaultTrafficSplitVersion, "Set the default TrafficSplit apiVersion that controller uses when creating TrafficSplits.") + command.Flags().StringVar(&istioVersion, "istio-api-version", defaults.DefaultIstioVersion, "Set the default Istio apiVersion that controller should look when manipulating VirtualServices.") + command.Flags().StringVar(&trafficSplitVersion, "traffic-split-api-version", defaults.DefaultSMITrafficSplitVersion, "Set the default TrafficSplit apiVersion that controller uses when creating TrafficSplits.") command.Flags().StringArrayVar(&albIngressClasses, "alb-ingress-classes", defaultALBIngressClass, "Defines all the ingress class annotations that the alb ingress controller operates on. Defaults to alb") command.Flags().StringArrayVar(&nginxIngressClasses, "nginx-ingress-classes", defaultNGINXIngressClass, "Defines all the ingress class annotations that the nginx ingress controller operates on. Defaults to nginx") command.Flags().BoolVar(&albVerifyWeight, "alb-verify-weight", false, "Verify ALB target group weights before progressing through steps (requires AWS privileges)") diff --git a/controller/controller.go b/controller/controller.go index f29604f03e..65e507cae6 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -33,7 +33,6 @@ import ( informers "github.com/argoproj/argo-rollouts/pkg/client/informers/externalversions/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout" "github.com/argoproj/argo-rollouts/service" - istioutil "github.com/argoproj/argo-rollouts/utils/istio" ) const controllerAgentName = "rollouts-controller" @@ -79,7 +78,6 @@ type Manager struct { ingressSynced cache.InformerSynced jobSynced cache.InformerSynced replicasSetSynced cache.InformerSynced - istioVirtualServiceSynced cache.InformerSynced rolloutWorkqueue workqueue.RateLimitingInterface serviceWorkqueue workqueue.RateLimitingInterface @@ -87,9 +85,6 @@ type Manager struct { experimentWorkqueue workqueue.RateLimitingInterface analysisRunWorkqueue workqueue.RateLimitingInterface - defaultIstioVersion string - defaultTrafficSplitVersion string - dynamicClientSet dynamic.Interface namespace string @@ -112,12 +107,11 @@ func NewManager( analysisTemplateInformer informers.AnalysisTemplateInformer, clusterAnalysisTemplateInformer informers.ClusterAnalysisTemplateInformer, istioVirtualServiceInformer cache.SharedIndexInformer, + istioDestinationRuleInformer cache.SharedIndexInformer, resyncPeriod time.Duration, instanceID string, metricsPort int, k8sRequestProvider *metrics.K8sRequestsCountProvider, - defaultIstioVersion string, - defaultTrafficSplitVersion string, nginxIngressClasses []string, albIngressClasses []string, ) *Manager { @@ -158,6 +152,7 @@ func NewManager( AnalysisTemplateInformer: analysisTemplateInformer, ClusterAnalysisTemplateInformer: clusterAnalysisTemplateInformer, IstioVirtualServiceInformer: istioVirtualServiceInformer, + IstioDestinationRuleInformer: istioDestinationRuleInformer, ReplicaSetInformer: replicaSetInformer, ServicesInformer: servicesInformer, IngressInformer: ingressesInformer, @@ -168,8 +163,6 @@ func NewManager( IngressWorkQueue: ingressWorkqueue, MetricsServer: metricsServer, Recorder: recorder, - DefaultIstioVersion: defaultIstioVersion, - DefaultTrafficSplitVersion: defaultTrafficSplitVersion, }) experimentController := experiments.NewController(experiments.ControllerConfig{ @@ -234,7 +227,6 @@ func NewManager( analysisTemplateSynced: analysisTemplateInformer.Informer().HasSynced, clusterAnalysisTemplateSynced: clusterAnalysisTemplateInformer.Informer().HasSynced, replicasSetSynced: replicaSetInformer.Informer().HasSynced, - istioVirtualServiceSynced: istioVirtualServiceInformer.HasSynced, rolloutWorkqueue: rolloutWorkqueue, experimentWorkqueue: experimentWorkqueue, analysisRunWorkqueue: analysisRunWorkqueue, @@ -245,8 +237,6 @@ func NewManager( ingressController: ingressController, experimentController: experimentController, analysisController: analysisController, - defaultIstioVersion: defaultIstioVersion, - defaultTrafficSplitVersion: defaultTrafficSplitVersion, dynamicClientSet: dynamicclientset, namespace: namespace, } @@ -276,13 +266,6 @@ func (c *Manager) Run(rolloutThreadiness, serviceThreadiness, ingressThreadiness return fmt.Errorf("failed to wait for cluster-scoped caches to sync") } } - // Check if Istio exists - if istioutil.DoesIstioExist(c.dynamicClientSet, c.namespace, c.defaultIstioVersion) { - // Wait for Istio cache to sync before starting workers - if ok := cache.WaitForCacheSync(stopCh, c.istioVirtualServiceSynced); !ok { - return fmt.Errorf("failed to wait for istio virtualService cache to sync") - } - } // Start the informer factories to begin populating the informer caches log.Info("Starting Controllers") diff --git a/docs/features/traffic-management/istio-service-metrics.png b/docs/features/traffic-management/istio-service-metrics.png new file mode 100644 index 0000000000000000000000000000000000000000..3d753c80e014b257b94868ba47689e1f13f5813d GIT binary patch literal 272003 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�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 z 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 literal 0 HcmV?d00001 diff --git a/docs/features/traffic-management/istio-workload-metrics.png b/docs/features/traffic-management/istio-workload-metrics.png new file mode 100644 index 0000000000000000000000000000000000000000..623b0668c78ca8b0903ecf8c0586a4ba20440d2a GIT binary patch literal 213514 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

YhtR0@QpLZTNI#l$G`5X)6 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

}~rUtgH7o~0WWheZAoV}r(;0AXx$L= z-3qT*`w}`T(`xa3`t_6Mn3z(0hiN(LBYj4$Nmc8mJLkfOnHsmEyWJK;O!;OS4)0y_ zea;Cems0`P&(t~B8FyWhRuZg%_{kKMc`jWyL?G}*p^;Ar-dSIEunLAODuWm$_U=X( zG!9piw#vK(a=bz_T6aT2m#pv>AyUhwVOv7}d#qaSn=9hj=C13J+)!GdTHl&8-dq)9 zQ3L1?9!AhI9l4LgQAKXQuI-jbG;F7CJ0mAHdx$1oIhs>HoPDm63zJ-1mJo=I^``vg zPqLG@_DT6oZD^mJk8zkiR|w|$flC0PCO_7b!~1P+6`=r-Rf+DK0U`=N`^WYo?9H}^ zD#3m%$^61!#AELpwI9<-S@PP$;W9^a78zS_2@SJEv@27P_S-W4Wa)Cl>s;Gb zeVr7ay;=2weC%~ud!(0^JD0P!;+6?YHf_{_#FDa+B%}ZCLZv5JNix-y%i@?Ra>}B zCTaO~?p%6ZN&c?D$6#`QT~k^*C~|CfNE0Paas)T0q9=yf-co15iL(RvDx_MZU8+b` z8(?Zeff9reX~9Fe3=nIP9+B)(hg^n3n?5t0NDC}&O?2%4|uZA_!oXsSm7${^Mlu8t?&PmGVrDct7i+^?;KXexFJ_TE*OHv4(! zM1AFQpu_HHuX@XbJc*~$#YO58C9v~Rf8bRIX zf8Vwnf)!R~J?Oq~1R@MabPLv`;TP$O_CXPw;UA1*^}+ z;bbKj($M+AgLbQ%tFT*6bR*W~05`12jTKQmtgyGV9S@{lL^2u}G4Z+d0(CXT{(+4GC4vERQ8;5SHJx4>eN=$Y}K#g1?_%J@+PJvbjDYOVtj zV>aXl{JE4E#9AjIo@MLUmh*GcRymswY>2V$>D`@}nj1k?NX6~wxp5y@>Gudj*~q{V zF8hEf!VJ^^;iTBJq)Sk75z49=v6=$v6KNC9z&8Bm7ISB^EQUKE+U`#adtU}Kmi2)! zU$UAJxnQxt{rP}BtRdu?I=v`556PUwOH;EIa=E_$mDcOQ&g?mWJU3VmFhsWQ)fhw? z)y?Be;KPNE$||E~L=TWU?An92`|#FV`a-aXVC0(j@L|%OEdo!-J9kfQlweopee5gO zCXoT)vmktmvN<~pp(t6^g2D%PN`gEEF&w?lY({LmQZJ@A*|iq{mR!|OzPtl8rbUQt zv2atkAFGon4+}VM+?{FMHaD4+hE)T_OV1hbtLSp};>`t)J?j~W1ZeUF3ct#WZy<8( zN4D>R2Hzla`cKZUCBWqILr-QA6JcL*xo9TL*r9ik%L4NI)jwIHz|eLo96-v@uMdtdiomfdq^&dht_ z%$W%W-ucfe!e4@^!99~;%?{>5avx~NF4thgIhsrfui#$@XBBGe8K@ZcF0 ze_RAlM^6D4T3etShWRrw-&HqrS(7<7_Edg_q6mW=tqZ|KMwQI@pfMooV*c=Gjr!Ux z!OL^7*C-%cf8@&N$=2fw!Ss2iw8lqfeAd_Gb2<9$KWf>4awqV_kCsDqK*iC*d;08lcM`ZSkH z7NrqWDy=?ShEO3(K&Wmk*|uC>fD*T^s`T-u?_~3_MdHOnq-|jkUcMHgX2-&ZNx6Z9 zZbn9VAhBnwyD_sr`J(;DOh6v+&d1{8uNt-XIKtza*6%ma47UY`AY;wy_1ZSttCaG$yTAOQ; zvy9Zae%oJ^SF1q64JE#?+A-A{4$H2duhz2(@_uM_lp-ntc2P(-Ie`+1@^Z=RLf|X1 zNxhU8v43-qKAX?6N4j`SA<^Z*2Pdt0`oTfIEjK@Ap6mCRCK}JeNH>23*Sv>kM8#j)z467u}<^XP3Hy&X{q>3y>+3KV+()X*k z>~e308IEdcYz#J1=7*UdyO$X3AFTm?YHWf38@mSQP2HuJ>AlGG=4t&uua^9xpqXzhZf-0K0&dZ=C!NPqU^T=Ay zi!HsIZW6K4sglco0i+?xJlA%~Q86P={ zMBD~mi*|i?^%5v9kH6fn<#S8w;1CjxhyRJhPQyM)kbo!T8N^|AsbWnIlmpl|=;0aA z-f#~x{QO>NqC9`P=N<|xu>Ur>Z2$@-2MO9`y_)X<+kMBuKZC5Is?%<4#Zw2J%6LuJ zu%WW|IRb@X!aUokJ&&sQYS+>%wnomml5&A^cwsP5Ta0nix9fYkU))+#2bPd>b+>hz z>Rh7V+Vm$`z)CB>im?tF@Ow;XDHMjqwuRt}Vwc&<;+W5$E}TU`A6PqcoMNrUHe(JH z2|8^+kQZb^H?G0obQyH@)5d}}!z;9#OTJ~N`&t;&$A2HY)|0!4tl6T!(5ISlE(8B8 z4F;oyX$f5%tGt<^6I2?yxiJ6WcMUf5#c|zwD=0B~^^wudVZmyr{GB_h`;uQe!$%?R zru8r-=r`z$K317Nu2`CX!b}_AUOcFN;8A*gJG4C@tC5+vp+ks^BnnOOwz)+25s*~2 zp@H)wnSgZ8u@z;NT$d0OD5TOHZ6wGI7Y**0fgkJEnn$LF_*uRDB)(rvFK*yBRsRX~ z2h1e%8O5Br&Xsz zuE$rsd48*Xa_Le%OpBdZNt~6;9h&Bsg%h29*nWZ^j^Fua4cX%8*!lCbya`O+?`XC~ ztBd76iEnbUM^VxO%IF5(QotPV$WURk3yQPtu)E$Rijj!FqjFqx>O($b?(sS_Joy}% z?l<_o_^>wX=3Ck$VAN>)p_AucYN2Ts)kPly&S`kLpkaodFA_I!4f!cWj9s(Z_`}oI z^Dtq;yf=^a{qiTlP6I6V?r5ap4|kGVM_ck8Wx{I_+-w(;`&-z$fFkX%p#-(Zm)f=c z@lJfZA-Q?(9RWXWaEF-tL>f;Wqos%_8r#dtD;x@#UoQR_4w3Wv3QRCU9cUV(2t?73 zzdA`i@;-ewe*%<~B+w6rso;C*PbyqHERb}T)$g4yc(%&o<}$zIP9&Q_N%lSEBaN8B z)RBlheJtdXG=U|-akAvS-|r~#e5$}#5}09Sm$GD*%N|(2>t;>PISwK0iNa?B%n0ik z7H-`{&OF=p+iDb+38W67Kct=_oPqF*^HLc^49aQ|1KJ- z6)MVS_ehw-8A$3oTr-$AO^s^38b^F285KFzY54RTP-oK*+;N5<(nim!4zRcf*eEsH z1dX8P=tx$?#C8TfDxHPcs#i1>-H;Y*bnq|bP3)^CJA=}&Xw|#nP14S^JE<1pl)C~b zBnD8-5x5rPl;@9;C&-9w#Y{+ik3SK5%_^B+#7qPxZ{wf7s}^Cw=0vxErG2GSfvzyx zUsIkmeEab+NiY1i2@Tx~uu)+U8}Le@Sglq4*G0RP9=u6%a`}sO=rz`-wgdw9|s`eOx7gFw8c2gEdg>ZSKokKi-A!4j`JDw8Rt-|xht;T&o$toPkckr zTybIJ)5i}u1p9DicKm)(V_RO9GBYDJfYf8NhRv@hLa7H}Pid!_v<2zc-5(!vwqv#4 zKm#rYv1vQl$-gqOK1dv(>eJBZP(YA5m$hs?8+pI@WCiwO)WzD7d$Y_!52}_0J|Sv- z?^guc^i{JwStq!Wf8Jzz&~cT#-m*BjiQc(tkD7+`fNIke8Eem`ero!wMf(OKMU2O) zy?=Sa4S{LW3dw1zYJ6UU23gPX9P%rrAW$heRm&8SrD50;v zk2lmendeSs;I9o6!|<86=4H6pF`bUJrW8{J6=Fo9{4dM>79PAze<9;P-RQ`(&Bbi- zajx4OhY;$C=QpJGHB2ApWQ$tz=4X>;8w#A27RPT})n0ItW&tgUHtv|^j$5pyYL-BT zY+fnrc32kFR~$5`x3rc`y7zb+DaNvB%QZu&MuRlWf2qRo#^3(PoI?JFG7~tr_qYR}mWvNeB=E_$iE>Kc=$+pHBjr9m z7Y7A{BN>q4;?!Qyq%^Th4i+wLZQ-E}J8TzIo3lQCn*D{0F7xN{Lsj^QqL811JQfkz zIiy9ny>HyLW{=gT>`vWIk7Y+}Mh1rm1tAJ8-*mRNGBYZQ{X00%AI({=M7k#NxBz3E zDl&Tt&fQZjPpdWRikk&FS6EXy4sK+HT)}oq;45FQ`L<6RNMe|oq;|$*xtx24v2XfZ{4G|K6di(vHx7U7;+9wT-S9+Iuh79ji~gW zzc~#lU2Ek5r)<Z_4Bps z3u>^*Iv>&GumH&9xI6vW0c*zh__OMY@3539@vg7Avp!C#QAhLPV6>3x(ZJ4-&uPkv zg42+@E6)a@L{B?&;-)L5fKczq2>VRug->bE8v*Z&#q>UXm1C!0CkD|04`F?K8qg5= zNRaS>dTP>FtD>au5Ism|B}TF`wy|Nq zm7`jyprSRw2Gl9(V9&jBz6x8buBU8%iagT!&^!^^DmZ-Y>Hpg`X#y2`u0Mth&uc?8 zEVykeUvClYfod_|GN?8am9+SH7fWfO5)86T(?8Des{H78qIj0B{f`Urc}uxsyf%b& z$jQQXjSq+YvPs8nxN)_-F1xm3|7I^Whbl0AwxEPQ$3H|+yggA(U&*Mj)Sv_M>!&1Y zl7A-K_wV(FgZ(Ay_RepXy!g+Bd^dk3cvDT=XXMALrhCcsqY&6x9)1jDwe{Z>x_;A^ zsTIhok_<|dY5e5>amKNoFCC~ECLC>=D%i)%#8(w}#@5cE_pd-(Sm+ePFXl?t1Oy(4-fS~Wo z8@sJ0{i2H*q#g;VU`#I_^9SHXu=Q20CNh-rI- z7P(3dHkpvk#xHB`wry8O*NiSpqWbeLBjQ)*=8j{`f;?Tr>IUsc6RI~%m^*?en20<3 z3J}UxlS26l>#}A(0pG6kh@EO}!ZJslQ;|Aw)$unQMySzG}Awmn2S^{+K%>-0|gd!ahmQ-8s-?{*|}g{5=hra=-k{dqZK#r=tn%7H_ov zb;*Kj!_~22-<9;|;1RO-PAHf9fc!{huB}w@j{UHOM#n+yBOqcSjYoQ)5e*;t?5idk z*&$hs2z(o=(QvTkerLy#q@^{YK7oa&?TWASEZv5{g~0ditHJv8mF$(s8U3X6p6hw8 zqie)U5*o(pc(YZAdyYwX7o&RS)aMBa1;LNVxL${BdnbJ2_RhE?MglB4OBFeZtnuW* zItI2I?fU9kLL+FyAGjbNWWDnaF(b8HH*57T2_4t+56=qOA*Pi(R(urFU*;qQSbZGM ze#N`P798y5X~G`nOoPsrU8z2+BqE7Xl^7k$2)tABQ#wkON-J48AO z4402?C|Yv|UI7E8@7ZmSo(fhhy-RJFuof~XzSd{oRd#317<1Sh1=<@WilPWCAa<59 zu%~LE`!>Lv*msd>a!fK=?-)=<{)iu64)pQ4(8<_CAR3_w26=(Sczbs>@aqcU-etHIpHnoIK&20k4j z_lT6J<5r-L3gX^Ah4GW{Xa{0}w+ifeQ9yel_f&0k+mL_3|lx#3{uTe$c_AZ5ttyF*B;&wOclp=NyNN(790 z^Lfwe>{q)xgl*~Vsr@G=ldBA9t=xw0u)cKxZe^VWz{V!30% zsMGy?;^2wWX3h%#Os|%wyeA&?_|V-eZ|_M`=wZ$w2cFAj$H7LHfEaesKJG?!bW6{% zJ>~Q#f!sF=KM2u&VN_)TO%FZ$(10Fy%Hm)6dX6vb8bBwXH9jh$s7454c_7mHe;gmRQdfTr<+yp2(6Tj zIFAkDvGWyQu4wbZ3FvvuNpDGe-#L+7#^avarGohhw=sQ}!<}g8M>_%k^H3~To}D#x z3S8$h`!fM=?wQ(B@bA~Ko2i&S_;16Kf!#nWr4Y0;v|duU;du(-W^|s>>iEfXygcB8 z^YAztgu3Kj*`6P!HoD^}eDkXqoZ|MRq)kWZ1us`6GWcSzeO{K_g`~|>g= TIeul zO2FCevs`W$N3u6|eBIb+I8*$?8>bNK03{*#ozK@s^N?Ncz;;Y(4bi9&aP-cwAD^t; zC||%YC!2|aNL@c@ea%%AU+Z}h@{XV1!Cax!fZR;FZE~CI4tEE0%dYfF#z1OemwHK& z_CH(Z)ZWx?=Q6wJj*Zg$L->tZqunh--1^?)ZVPWLyp6u6$-b;?ZxHxh>CbLgQt!^P z|H+@lZ@mxi1nRPmO6XGt(s!(K*`4i6wfUB4gj6Z`?BIh%5tU5w^)ze7-c+`5kOH*!>#ThgDb}y^1Qc_<4k@Dp;;Dx3~d-o=ID{RdA!1%-}_#d>oKs{Z1*;`pUMeyh}*?GCyk|NY5)^ z6Y?x0c**b3V@;{H{5)XJdlSNLhwGccpjR`SZnoT$;ZgHcSx0f3BrGHNdhg0;?^J@J zppnRhcxmGobH{Jlik9P7g`rw8)5sIkvAyhteq4@W>c^+h4;vrt8kTUXEU3Sgamiq#4oZih5bn(IU0(4YHd=o^(cb=L8 zL4wNAPM?I!Q|MhEmP)2TmNK?@`7cVDDLY8Pd+v1>uI)dZE|I9i^<5kQzi-?7l|3gO zBy&_JxtBXzC)z?f6P_7kuPMMK8e%9!(j-6D6KUq5D| ztH;K3FV^K{`ihzjRgiqL>yvI5ZI#rWnlY3Ox0fw)?awxWIyaki?~Pi0kp!;e&uf*9 z=2O1z#OH!DI($|?)9VE)5-a!X6$HnC|ZN8H>f;Tn= za|OL=BX9T?g=ES~Z7WE4beH^3ZCmk}g)$D_W4t2v`Yt>JHrhZ|0!f^jEt@iK+UR~c zUMaCH7flX5X`HM%$eiHBnesjIG91m~7Vw|(&jOAyJzv}t+rlCfg?hz3wP2yg>*K?LD&vB=XgLzU}`!4bkxLmV~BgTA>Cdz%a_yNmC&oL zuw);%!|6QpVl@|at($eGS*%^%al@_Q+&*c-yU45)4=(L3^dpe2zW~zpuW=sidxe1A zYo~Co*v{&$HgGqNQr(F@0f2daaaDqDg(CQ+9XaGWYKqxm2dBN*|E>MgF*BOD!PIQGTPq!C)Qf<~7 zZ@i6zwDxP(N7EYJuU*HBMF;n(rvQVz=#^kF(gYcO$7)-q1N}dvkcCu|qrRBkEMz>Pl)GGocwigH1F)7=7_e@+F%+<9sNGO@pdKHE4=vTuV(x+M zN?6J(H)+!^B^>K>Oa&LD=)EZK<=WJ&-(l^S z+v7S(Np$F9A3(~wLZUkx1s+i>Bj9sE21Z*G`-dd^zO$1XV2^IhZi$g}H|1r~E8Qji zMFVZagx-&aUzRRj&!w@g(Kde9z3AHhK-EF<)Y;zGE5LNSGkTtQm|^6NeyeF0^xG)# zrgbXsOuObBO+jFKK{4D$yOd|$d%un7)PgqioPCID%2~;Gu|1F#@@YT$1G3qO?@1!i zVN_~^NiV{IXQ{(m4&ux7W+BX!Dw%@b74tH=;h$Nw|*3rcC*_ z7eJ^|$k1^(n^MpoxQl|U=T0Bw1`9Kx zS#F<}IWrY>%nP0W@I8_hT>H6oQbCoZ*h_EKm}w71HX*QU`oy5q!m-z!5Z}xxY0zx^ zVa|&ec-f$mC9|C2{qiCutSa7DW#g;Jl~ct#%by*eKkLW()$tw^+DEsaa2>f^wT7Rp zE+v5F(~jmiL9?%6O@w1;?_8OHJ68sX$c)iOF^M77pW-nNBJln4J&)$uW;~Z5boI#% zWYk0?rw<#|Gzv1??UHhly4mV)@TMw(9>qWWS`v*>-lP;-GVn@Bq5 ze)CYa=Qtgz&uo%9W8#%y3x5f3qK}F)$5kM^Updj5lGPI-yDxMl!~9@}2Wal>)jWX@ zkTM6~rtbpVmG|>w6u^wb$UD0wPa@D>4MncO{Ch!RbhizNhy#tF@Z+Yc%Gih)3ohV zbM2^tR`x&3afYBLljr3>$|td>TK5FM)DvmfF_NfEi_irLKSHBnV2BGY5HjP(+uXB^ zZlk_2soKYO#~amaiTMCD+Ri`C@obFqQ?QNnzA8fBg20!XVcij@uE)g-G$+o3b*F#+ zumI>geCwh-45&JaC5=Js4n&NFHPj}36foZnHffj&H8QriI@w`%>ZYY$k8o!dV1YL| zS$jtEI>=D=^c7M&A<8%YE2rWw{BD`bOe*ju#4%#9vi(&;AUrEZFo}9b>+6-05j8lz-MVnyi+zF@ zLPFrDO7=g!uIEJ2BG-Ut{6|dyZK%Jm9}~XVFmU?77^L538GD|w{{G{VGN-SLb0g*L z3GV5eNC1)e3)no|lop8mV*?FVYwKRNXerEI+Gb&H2F^# zSuN`1#d%#eE$Qg#byms~UfxEitN*|v)Jnra#^suSnv~^oGBEI}o*-mGazGegHAySQ zp7FZwF?d;5>=6L38;ef(PZn-66Oh~&u&08aBChfV-r1$0%ph^Ysxy$WlXINs09ONES6aaRybE|G5-ly=hio_03DE zldFjU@mOprY=-hm|hg9P;H;z`X@*J*N8{TU%Y^@_HK6OSaRL&MyN`tzD!K>-yYPYM)Vyr-D@KDk-|%i@6$~I&DNP7w zy$BgK=cJkiaw{^;V*X4CfMMc40eNV*F*YRvb>c0U!2Wo< zJko8Z+6tHu4RgBg{u7?S~$5y6CO zonXfq^qiT`_^~b;WU}||0F(B2rh;c^5#pU+KmhUzaPz1yN z9QB2m|BM?zybHSJqpvB%X(k&|?t`&klM=RCkSt-u2_K;WoNO>0%%2?hwUVt8b^DTG zANggt;o-GgQagA~ZxZW>o%-4R@4we_VqaC*TGAWvyAjTy8UCJK@*sxS* zwg^i>y0c~dvQ7J^_qo{=n?;?m_*yS&)*b;*AyD4K-{LSS079wS01O5)YasDQto_L7 ziTU3z3!7u!9-Y~VYmWOpexvn@-^#G;|B+!}nn6pv9YTsI{yJ^|#gy%m;YzQ&YN+90 zKny8N5(r-y%JBnrGC#V^Uf=sUxj()M+p8z{$2$B2C->r(E{4D8lFG(w$UlDlebQ2Z zmJYb?&ftDv3p?7^LI5dm0Ig}%Z()u^iX^kBp`Y4o%fQF0vJHfb6o)7(qW>#pw~NPc z+^Iz#S^i&RK!i!bw1#YH9;6TD+IX$E{6z|Y`~q>yG4USKo@uRRe;_XN4is%fTY)? zfQ5`4WxT4%=2iAZFxiVk>}Ih0c&o`&Ft*6Ctf#e$N8`S9Yakl!t9T7y8AeFg^74m! zQXzbJXYJ!glJNhAuvr*{8P7xk?knoqpEZv$d%xJyqDSQ4aAk|b4s;8q#19cn8p32w zhq0<#tqUa{*`#~GMRq|H`Mav_kIN7qzXQv-poFmd^#2p^@;2V)dUxIvm$BmxFh%Ni>BxQZwM;}DpCgY0cd`d9LaXg1 zY)`#%Fx4&qByIT+!6<$9f$e(O@1!HD7GN&S(J~pze+L>vbq6IJ4+`=A6MEqDFH``6 z8EZVJ1gzQ<+_*pN9+H4z^Spa_BgR&&4kC6tv1C+hNNzQ+2+R5x5j2=}K!K4B1;}m& z$bQD_^_>bP>i=JSR{nFMVTt|!htG(xt0vCBO%mqo07F^SuVl}hBYI=ENjMrH^X@Dg zH9(8{np>kFOsau+8*?-}iQ_%~PjZFX{v4-BJn!Gjh}|wz|KWde4{&hnq@#rM%G-_- z2W&xxWjuCpp!YDi6a;wc49p&L%Vh%Vk5R;)IL?AT_`vNgSENL9O5F+FAN3)+Q=e^I z754u&0sO`f1>h{dcT9Jy!ka`gApWuIY{9}$+9G%eLp-~;dJj-b7-Fm2?XS4^CB^8DmEYp>{tObj6Hd|?n%n5$bz1!m59CH1&~I}iCV=NsNQvv*SC=Dc^W>VULKSEV{euqR5F*YW z)w-pU_Qjn|Co?Vi+ja4QX~=K&?bl)~>u+ym0>(Wh_%v%B>1UrrILzMwf@(IIAz}eL ziWeC$F9t25c~YlkE(Cr82XL2S91I9bt3;7zME(<0*uTEJQxQClVpzQZ@T-52>Gk_t zuU_ZAf><)a^&PVn^!z{%5Jwq^3+4oAcL6TZI62IZ6lQ`YuC-a#_3+wuK}7yp5p#{5WYBeAx!j#h><(9Q6K*Z-wDuObvM=fP~o1FC6m6GOz^+gAh!- zR!ZhZjmKm6}Dz+qT!(6!Zst{96{C4?%M_j@iy_CZoPb9YinYU z{zuVUVXr%h9q&w6|Ch{LiUTBICO(q$EEp}~%$W@9juA0<@Z(JQ&WPO{0YNl@)q_n$ zn+U*<1*pQ-gt=-9Bz3(bw%9~==r3a5 z3IW8T-)Ix4phs}lkpA%jdimj`&?B~tIB7Z-3Taj%pGN|=Gce5b*2upCjQlxrcTRZY z?#Eu?Z>GC+E>dmbl!MXt53Y~;PJ{$?tY8}U=QIH_jWJ=~uU_jp-sil$x{3p{gY&G- zp^lSE=>LzQd4M>H`8v#UkPJ>nm7`!6J;IS4b~L@VfbLEpcI&EeYJ5ldI$ZsbcOJ`e zt|v?^;S~!uGLGjxa^H~OZ3@#N?Y>3$2i^w8csFq+AmGV)O9qQ6U~|3)JRJuoz+*H>slfEZv_Q5>U(%aG(#?>Cx zM)zi5#TehA@$+~8<}d!0!$6pXi+#w12NDsaw}}YApy5f9&H;Ak%WFu=NELd-nJ^g= zOt|G?2#kc>y&zplRqd$u$y%6Y`bE@pn9ujG!u{|xCM>F8h%>p-Wb`Il^* zJF4m60K!&F0@l0QQWFk?z9DC08uUDICmZ79dNo z-(xgdFWIfPO7n{aTP(!q&iV*bp}kH6FrI3>T{D-Nwd3nFQXs1kQyxrCdj;U2fvm~z z2RL7AL;+PSO!FS(=#=OYUGJU|{AarYIM5MWh2I%6$l-*U-`fjm%)8qhSIl3|u?pe~ zIga(1;IqfR61yyu&DFV4hs2_iQAm$Wtq zsX)WF>rrPMvVfGu!WrN^^`i#tL=6-Oz9i=)7dh?Z9^1>#uznmk zF#91FenG9-SV=nO={WO9&g%#p*-51%{1OZjZfVVyF zR&0rQAIf+nVO|;{;{AY+E%dD@OF=7^{_bkgS0P-J<0!Z!H6N)Y*CzDeb!$Z_q`=nJ z;I*l>SQ@y1=}>t;ZEMu&yhOkse`D&2)`rhL$bf`3?XE;NSqZaXGjr|UW6QWKOtE+o zOwP{E#_hw)pORfI4=s0vFBeSZS}43x0dbZ1W}FLH?VUR3H8gOQJj1(B#am&g+jE5i zNB&;|BUR!H8NN)EdB0M)Kg**Bk`D?K6>1dXYTrM3tmE+nUQ$KT%pq43fSo>4LtCk4 zpR;krDc9ZExrE9h8dNofc;wauCAo_HPlmhwKF+?FuC7Y#yYe7xw=ex+udCRW1?M?Q zvBT5xg6{2PiyDwSs*J$u>J_{A>v=m1(kmAGijV%&ZyX;?ysEt*NhO1T+(WD?5llLn z+J(*i&%{*;*zWNGFmbCGu&TlBXMb@%R#+mmnUSvDrBB;8+0w^P!M^l38Quj%(O8y^B7CWA5Jy@%x-cuC;(-qTuZ_mA-GUvF=wGUY z;Q&N#r*RbJPLs1pkd`G*6U8T~(6?Ro-7)J2?r|i-8^i-JR31 z%X%sG%9Fqv|qyso!a$UZ@#z|IQ1&g0cpJ<4si@lg#!$4}X5@AU~H^KMwR_DrN~m9UqKsH)G9(y?z?F|z0s z!kbIW7Q8oiJ@=0<=(6Bla!@xaBn93XKqsdvxR>kNK={QITvT#1T9ox`19^5s7>}!Q zjVlVwc(zdpBE|x$)Kq}!qKI*%CTDCL;Dqm`kXflKMm0(C58jUC2Wf4TAN?cR zJ^R9YY$(kO_C&J-7L}6C0K)@Lc-yM2QARtZ^yof7(cY@sRA4pGQC_ElkhR}Iv)w9x z^Lm|L!6+25JBt5&|FDvMn9Ef*gF~r6=+Gg)Y1?n}8n{SPUGm&<<=G7hka%yd)?hid z&$hj7q^zh)lWf5Gifbt^IMGbZu(IR4X2EF%mv86^q4Q-Zo5QbaWl%w6;)|(m_p(#4 z=fJGS7P#)^ebxPcwa0z%3Pd~sEW&(%Hnywa-&=RWFoW1HPQlAf#NsKB>tqHGXy?>P`5q~x& zjO5%=%v{|%nT!r0mwv6D4R3lzSAk&8JA^n8hChz1)+X4l|Gq%ng04c$(skS4*Y0`Y z8u$C1iJh)D{pz0L1J?Os#LqH{w2sRsueoHb{4TVuG_G^bM`v4cMMLHXwIn}s@`a-T z;UZg#aC%TVUXWm0DeS z@f@TCDC_G}0Tw8R7FCWL?xh}BhMAwfvhCN$-On3>PT#+XC~Fq^^(af$G>&m39^Tb& z{()h(w=jop6zzW0{e#TV6LCUEQk$HG0&!m0p0XI;=tH?`DDGi?i8KXbX}RVnctdU6 z23e~*T$^%?4~fM`=V3wE0FF(WKC zCbh-6Ju}`WDWdKsTFb7~6$Wy_J3}GLQ<{&*ko)dk-1?oop z8X+tj{yj{)$2^Ds?UY(s0;nEDks?U1l!6ibhS{jwIwh>f{daGosxrR}M7{647VGHE z6!!o(YfaTTIy1;sIsqWhteQwf!d_C*%o(ML!Qiin=6y*#|2$Y}|AUnCGp zO_9UZ7XE*tm#4Q*23BD8<)u%v#dha-z797lMKts%4Fr$1FKwj z=xpaJ^jiDA)1pd1<`aQu3<8gK&CVUp#5YoHSu%2(fRc{>A?~PH1)=NSilevhP}GT! zj#eQv2JZD{1pkV~t&|HV!Qylze8K;GFX3>?81SdyI^vg1PM7slR;9gO=qb2HDTmJs zMzo(7w0+nrr^v71s?q&OTY+#A6q1qjmZsl!JF2-Qr-s~_LIppP-xK9$3Uy(1h*ed# z@9Cq1S+0I|ohxj|mNgKT5dF_t8|Y24a_jM9$(go#o*HF5n*wtco)_Ce!dw`=h+k8# zdK!5UsVWab(#SE6fBRsj^ZyC~p@nm%QX_AaEN@u&RuM0Jg1$LdTex+s zAf&~IYYN8QWQAwT_$RAYw&T??GY;bA@zJZ|qAEAS{txJ^L8`Z+y^Z-7e--OGNomz@ zG)8VlL((EhW$h`7Zz}b1!ou5Q_B4eXC&;Z%Xj1sc5S=9h=O>ArQ>GqM)KFlMhs`4C zkEPIQZ^VT+i@!M|a7lbsZ)W!CgnzmsT~7{DVvwh9tEF`{fMbper-r&w%IsW>XUd{fBdsC{Fw*QwCssJn$#B5);_f^*i7d;=h5cWi`AuiEI3- zeN(aOXHNYR9RDn|;O-AjSXLn%1(d3ZY;Iw>_}100hIKpAh_sm`^^~N~s4l3^In}b( zEk_enZ@xc|u7{9+SZrWf>N(`vH9~E48#1o9&Butox=fv9$i!@K|MC(3f<%+#5#Y!3 zBG$c`jdPkCr~H(*Gugb9Yvc)P1m?v_2XFg*`;gm!AB!Fv;QF^?Y+{HUs1F1!hB`CUVVdCq3kf}T zj=F(Va44*(9OkRhz#+7|CB{8uiUX|)Np)E_p0icsd?&!}gfvyUwuL^cpQWb%fiB>g zvjj4+xL7@ZQLLfbK2_r3n`RKj%7yo=IrC5*@9I&}kwf?4yo>U3wO{vzrheg4gH{G; zyH+B!$I9$NZIvm2%NCUKl~RF4J+rnd$M5DvCVEe8BblKA%G;^HtoFUQ`ntz{xrw4_gT&Jug?F$#E} z#)8tcJ)O=uic2cEd?)5D^c}WX=5F4;ljZL{O0^aia|-G{JsvpP;3J$(t>Q>mR&5<7N1|s^~p5Q42}ojwa_hV8$|~#(3UH6WfnE6 z?%HJOX62pp=9+t?*R4oAUwOQx?q}J$` z2>7Tnp2X?2oE^g_3FLs!xB3JS;;~B8!ODoDR3-Kt?gU|ZF-S-kMs_gmJ)RW&;fZFC zd`6y3vK@L8-He*_OvU0_iM3=Zgkoheu12F$&}sg?w`{6-xL@*wJpZ)XX)}&Kxj)Y; zOZ*AYP^5nTFKN9wGJgs|1QhP0awT#crEn$JC4<$9ZHuOgo_J>qnBCHFf zUgOXnX};GY8f%`iwtB?~rspgzr1yH+QVoU-)0XwzRiW`D zG2gy@3xQBX|TYZZ6^7qRLeW03$pT#V$?fmd)yimb_ z2YOtazmKhx(iSb`p&)_M!DiLb3nV)cwVd|T*m4FbzHBfYRUiof30!R|*tG+x)xDbz z#wg)2H%aLO`5tL#V08Xrd~oE#z#+>tq9|iDcUjC#7XC^kS1}@wn1(u3P)a>XuxB_b zmVlGqDyUZLri${(5n}hpd4n_%BVU&GA;UomMhun<7}QWyT9S~KC8TlVPd+6r)(zaj zn{o#vy}-5p%^P|Xh=7gA5zat(%M+1bKWG^{$Ok=%~l zt07aN9_ASb zCf?V(dL=%`e%`;Z-;qqv6B(Z`liY06DFz5}AV}h##c+g|jv}N-Ao3mnHSWiyiG$N1 zG(&+++VIiOqc|TElYC85h-usX5tT?Q;V{oAcj@8j z$jex@9x<`n>A$qok?_8T;70&`S@f|Ag0+}TJ6XkwOHOUYGQUYG*lUZ9;QR&NhlY)d89GZA?Cbu4&NhF8uG0oEMbY4*@es2!DROMWI5a5O%iwu0q0l z!1o|O+4OjmwL%+OyFQ^HKt{wXh7+*`7cF>_vfu|yv7YN7ax2nx>g)Op+1{8Vuxpdb z^gZF37X&h(KujbUY{AC$_ihd9L^Yv#%B)ouLwil=&H_9$Y4#*A4n z>_?2#zxPI_VR3fOyX-cVP!)K{CUP-qEwj3w5POz`=niJF&FA~S*Xn&Tm8$g>%Dmx+Hux#o1y5TVIHYf}t=PZerm zsvuQp$bh#BD~U{}KS&Xzqo3(3V-~_`-%Lc3ys>SJ=gQBw`pT@Z?js~U9K~OhFx4-oCMgr8J5py zCpvgJ4FZi(?8b)wxGJ|IG+(z!Q-k35}~iFw)JaCY>vwwIt&d~Q*>wQp1&X+ zLtHrmnOnIMo?owekf_ByDA`kyt}$UHS%mlP9r>tLmUCX!{!-0#sfFp)#~J+gaN2xL z{m=Utp6rLA&*i#Sqz4KUOrBOd=gyEQ4v)PuR8&ih@fa-p)|R8Z<|rH9Gue=+cP^#x zXl{l&lFq8A_Icv0Vn@;woI#b zb+C3p-=_ZUP8dB?^3};=4@ZHxnMt=U^GL_9oY2#)MIBpi&q{QE-I1Gzg5p6ON8RGzl78cmM-w7Y2uexCk)Pn?7O?#d$V3~t;<9z(b{ETeAbPysdw8HKP;vr|4Sd!nT=*Cf|!n*w;OfOgW}*G|#w&FEm6 z1EwAss6v+Xnj~sdW3FoduR#HRI7S5y?T!_8p@QYziu-O}AH-QC^YAxL+p z(%mK9AT3CDcf&)+ccbsSxBHCqjq}ej_~HFrvDTb(&9$x}GndP6e)em(J6OgF`JWOz zjvHA?c?(3VZ!dO+LdY@>t7o+PGLsp!IGpy0EvDlKV%|iF&?_HbkhZJY>iTs$UBLhG z18kH1ygOxxU2$V7@^pz+d}e93;~WeJ(QX@V$B4OQf0DFe)3?xwcwg!U&L64KJp0PUZxFtXi*0aR=>}D2-pMYq=U@zZQsw z8En(?^aZ)WoaAV}NGl8mRv32Z_`5@k*j~}F8;W%+2zAb_04D;ndLxpT-}@1y zV&dGj_Tor?d-hlML;#0zKg1{TY11@Ud89?5TiLy$O)O{$6V_rLBj(}}p#GX`${jiO z@k0rl)S{QzcRryr*B%3R8~Yu(pVmYkB@$GvcL!*OkB2)#(*)F2$+lnk91wugw&v!+ z0_bsGkbJrYEpYlTl0WeYNR01s`zE{xOe-Pa`F>1*(J~5JI)izRramJ61h@qL2e41C zlYTiQHxxQZ4yJq^jlURc|B-BZqCY>RTAP!fFCr3wNmJ2sm&y=Q(28Y)PW9&PA%VN} zIWY2LXy>aBLfPH-iEaQUVE#=k5x_&Qc_c&cj;IbyC^~;O&@sECDM(bcc&->-yxUqw z6;AndN8G#b`LKPaad(V>QG(>G4Q92=IJg*3zh3#HnuA1uZ8|Fm*}5Kx0E=_hN;V2= zpphZ@hPJLxL;&W=O#)gRF3+dSgdgh#$rGQ#_{09%S`5G%4F*)h!oP<*681yk8xB;# z4%#xt0{A?_EQt-K zOAQxj@)xQ15Y2OpmhZ6aict}RRutCAo!N(NV6G*#yH0f{K$l)1YqmAcN zDm8~qslV%S=77=k-_jybMcxFMa^9Q%5ajyUP_#ZVt2z0B2Gss3_AwZf_aS0giVENw zJas|@@a=h8{79j*Mp}O8C`Ht93pY_(@&^OqDvX@Mx!(-v0LtY;aaiT$Wo{Kw`n+ye zba#akvk&?p>HnKy<)e=QsWxP*kW9I18K8aN2m z_jltSP_@XwIZ)v;xC(9g1U!3cbh-j5ZgwD_!e~@1)q29CFrxGHV1mJNXkWve_vz*| zCu(y&j82$7UoW{A+(WqY!!GsAc%vjM5*=OC;zUtf6i^|H21*UzTzE65y=TA;4i(2?O0ta~jaE6m$6v{X;m>8;& zC0=3R|BoXLN*uWFV!p_L(+oHf;;$8p1AK!3U;zgYL!%+Gw9K(y-# zgeHOtAOuJiG7pR(z6tc<^;m{sTI)Trlc!EQv(EB&8{@crN0`1uS}jsIuA6VQ6jlZ^ zN}8I)7dvA~Gul2xdUEP*_T=Y1;d>KB3S??E`BIVCuC~+ASAOHHJ{nANgD+iqA&y)1bu?9)ZIR_6$RLhRYFV5p#s*+3g=luI6HtojrOZjLpP@egoy(shA`qz9uGT=`JT+Rr9TLnpBc=&r;FMMdPp&033 z93N;V9Fc?%uRFZ=9XCM*esPKu_pY=xA|My0%_PY2<5Rz`A=&zX6;#%zGui?pPvs^{BR-?Z5*y6Kin(Gq+gI#*N`_~Aj?b# zq)0->0{qg#N?Cxc_{giPn+qAcV@X<}ZNCWS=2(9PM-%AH1n2naH~j!OE>di9{XAK& zMx5xvkcZ8*UbTqj86H%QuEviofb680k*nKAbJV>Rrw(TLoU!YA| zU_8K8q^#e)4}s@S9Rir%^Z+MpR-UAQwfJ1`d@SQNcX%%e{4X?!7}aErxaz+W22HRp zGaWzuv_CC};D{@rIxs#Vj(1|?0~Z96mQc`_4;CL@gnpa)VCVheticoQPNv35mF3o8 zg8ihNsHBopom87k?B&7C%+CyZz3ln77X)dS;$#`*1#s*mJxC~(a|y05)`!e}!fdEM z!szHff(uO`-#81TNqB#5pi_x#ag__SdDhHbfV|-vWX{E;hq^KHoB(Mo2*NE5%<$ z_F@+PwuS8T*tYA^xDj~@#`rvJxU%y<+LSS^d^|RG+b=4J&`S3CKedD(YG5Qm+Efrr^|4NPi*!n`yi7Xl z#sDU74ZGDELm5|g|s!A1C*Uqsmt=b{oB*LcJZ%so6ElHlU7GCQs)|@&N zrCy{?7J7sNj#yKU*A|466W|8Wu$>R^L?1441b}wWKg<2H--v$>KS_8b&~t(TXo?hq zlD+VifYwSrJc4?MO8fCn?W2oLr)My&q2X(6GcxZ`4Vw2R>)s=JMU~r#v%-H~xaIb0j zprW0&TU2vL0uBlK|Gd0p(8wotsmNAd-%6jal+<_+=0r~PB`6Y;zMkhjzB9rM3a9!I zm;a7dc#0*D>d9zQFmt|QBEdwTawLONzOW?%<$6ie~(Ybyl! zRaMZnX3c&KVnF4t#Zvn4Z4CjMo+^tb$=zQ+I$H3B20QM}Fa0DR3cMBjpr!I9cIgGs zUxRY4=lB6Y@2pAY4h>kRqxkwGGvZB4zuMEr+Dt$4Jc*SZDXH{Z@+HlA-&+}JZE;Xg zn2~(-WK>Wt)5fWh%1(KymmCrNw~=TQ+plFBCl@5QL0pkrR_b+YT%-mHJJOP(=s$eS zbFf~ugZn|{cTRyG6e3e3D?akm(9mZCHF8UQ9QD4qj55JiYRTlTF!Q+$F|w7=seLS@ zGzl3s?{dP@EVIo_J-t)ZTEI>XW+zd*{;|efdWyYl zDOiCmQAIYFE0SVOwY`<3;(Hy2`_y7Xp7E%KeDmhLV%9fps7-Lcbl~fthC)1I`TzR7 zTCP8|v987A3qnCAP&Sxk%7=hDW#7PksXqg5?3ep4@>lZ$U@VgOfI$m^Wkr;L$4x%P zJ7T#QiFl$fSMKC5UkW~w^D*^yz&zbpaFDIOc$mt(Ovpfjt-g1e5Te)Ea%!cOV5;V8 zlKR$KByi7ziGSuxx4N|DT8XP^qs~E5{1wb!{;3cD$4dEDvl{=W5D?H)p(6F+#e4w< z0IsX|Vj{s0{QZGVf0??X6~JMdY-mV)a0r|Z26NX_4sy%O`<5daWsW4R79+MMgX6f9 zNeequWr^onKbd(k1Qq+Hq44HS(xKp7S~l@brMh<;U);;YXG2YXqrm2 z{Vzs_AII}5<@!%H%DpxG5ae%a#YnZy`ii|2%2WCYXNzeE*w z;cu?j3c03f?P3Y%$F;{p1qnP-k4Y-LLiIV8gL&5en5EFdsS`D|N#k7%MDPx9vi&Vx zRS(lgd9Fb@d9rRzC68W_rCxf5^Uac<;eR*+Zf?d$m~r0!MiQXl!t;kO*gxay1?-Ul zeBp7}tZEA=Do&r5vlG4eSK@xVI|~1Dci0E1f^16xeno^C*QH#2oY9=; zevBn;9qAAMgBe&L`=d}s+`kvd5bqyCb&~pPWB6r(E-DbXhrM42)iWj|7;wT^e>c|1 z0nXKb3$8yfz({-=C16-?b4u?w5sK7Lv(CtkopXAcRZ}bM@+n*70|-)WrL1&{#F0U> z{OU)}{$`#>zf{DJs&6Uwp{4}zo1us;2z$V!owZ!tfmZ+jTu47Dz%-%VVpI#TWW~s^V})iF=bYsZ=)72P^)SAX*V@AQh^L zFK%*3!07MI0+ge!QOV?}+QNmv&ioJ{Mtt1^hHp)=a0N@lx#Pk8`gqzWV za7q3TU=-w(@j5`RPtx)H1kgXEVn_q1+*IJ36_N72p@MFsXd3 ziD6t1ia3t1np9v<^PBkgO%d#W1#}>}n|cF_M6#D26^`SQcDdrr`Q|9d&0*`I=2IBf zDll7xC>cg9}4_&hXtq+Q^$i3s=b*vHtj(s+QRIxgZ`B$)~qk zx%)$a0zMp6?dE!k1D5r2BI8FPQf1%d)BlaN@T2Wswts>dk9~KweGnKpR&(q1ywqSn z-gxFl$9vKxxdk-un2MULV`{}z;0ibwqB$0sle z3T0ptaouMUOsd^QQHl5thKg^plq*dN=G(1l83s8s@KECTYDig*G(Q8dX?y>U*nrs= z=w;T9jl2~DCIfJ>J(`(mshcB(tI$tde|Baxntw+EPo>x{GdU0!#Y=g;%&h%lFV5F^ zmbtTP%qzOMXLs1lz8I}MAOjlfh=Gz2``#~SNrH}@(mYMGJ^-2+a=hHkZ)bl&4MS$X z2U@Q@(27Xd^24xmv=EKy@Q2qnyG9`~7M(*i?&-q7-u=SEimi86Aqc zA=J%bTMQ`hb&}}P5LpgX({&uA-_5W80l|FE2vD4K;{Be6H-!gANlRC@ei6Wc=F?x;BP}0j( z9hI2a>9RbHnPd6MVlnSzPL*1+8dcG#Ozu4ViVmm+?>jSoYK3$Abl@gow|BgwBLXnO zQ1B2R*~=G+y>xsC`~_c1No8Axpye<7yL0!0t__z8el0D?ZSR--(&H}zdfvr8o+bj zgJ8TLqSL$`4L%M!9;?oi+{$RsPU?Sw8>QUo z_<)QWfq`7ksVHpQH%LaSs|IDt2ioJ3t9P(hZhS@*FZ#@C`pHV z!jkS~*2(#&{8kSwu1l$u`z4q11Bcx;(ZQ4*ZC!9JU?@*wgSO99!b!NQ6Zk$Z|e?880r8Yo#cg2I8Jj@TT1Q7D2?P9c$1+Lq8UOm(M8w!JSouhGPL6xh7=sps#lVO2Or)7mqd$F5psS2W5edc#mZ6iW@i zGUZiT@D|;ga^o?Pe|i z_0&?VrCfO$<0K>`oX>W{4L;y)4~&0~ig{`6s4kwaNJ5IjAm7?Dnke^zOgaDQNaXtq z)Oy)fb3O<=HgN25OeFdan>a8qFn_ofGJo*%wRC;)_97S*KDxzgv=jmsPCr;{Jj$>J zj!#XaUkMsA?G$RRgFgITxuV}I_x*oYP8m{*G%)R${DAi>!NE?O0axf&$~gI-z=(s5 zGo}XSv|py}g}#@3$N#aSP)GuAhOg3<7PP_y$|=9aLg72 z*)Y1D+Ev$kYF#*o{w|Ev%Kkj=`pNs-9E5@Q@?ewm5h+pu7kZtIiZ-YE z6?$b7#@H5G1{q*AAo(P>xUWRDwT;#PqX5sxaD^NacoumRWpiMmq8*pOu_gj)lNiu5 z*xl4H6yGACpFdp4YyaeDDZLX`Mz$g><4wko`yw;)4R-?NWd~`3eiO&Pi<6~*qwB&> zzV-+~{&7Q8{`TzSwR8M_5c3BpL!dL>RH`+lq%{Hsw5+6loO2waao8KuIGzp8#>TdiEaZ4UcK4 z$*!a?4^Vfi#?0H>SI_I$cr{-&QEeBJ(iD8>@@q3*TCLSA9whAKP5{^-7wi<_QhW*AF zz@Y$7=2vfRaugJllqm}LxEFvT>i;(2FRI`L4ilOS>aYVEU091eJ^U5v?#k^rCAQRt zUD1cyiFD44T00~9vpS8IM z9jbpPp`WpU8lFV#!873!Mq{{WwUGzdeTs{VH$%g|VA5?JD7pU1Yz2BIM3RTloH$ygWdgDy?sq1ZVKe5l+k z=idM$Y{f@6zjs0Pt#`#&i2&^GYT{=VHCbghzlP-Uno6?VWiqRl_p`p=CZ1Dy=@?Z^ zcG43O-qT4KH6FoI5T7wnQcP5vAyV*ou|a&K{X0Dq$yVMj%U7SU%Qw5nD7H9$UT999 zpBN)HTq@kPl_Xw8j+kNz?w4?8{{-W4MD0}KlN7p#Rxd;y-WUk~az^H0Khl8ncK=m> z20%6POCUBJ6Q%Z3X+bM^={xW~MaYKG^A1w_`t;a&ez;YO1-Qo8jecMlm;BI6(#Ef8 z52r<~+?PlUVld&ovs_mB@Nm&tJ;m~vXR|^>tOLDWYOtRh!uS{yR7Spo%GZJT;KjMq zj7qQm1*#Rn`(Zg)#_j){5?3p0;la*ARNGMz{c1s;!`h3!53vX?&c|677a@q37D%>~7< zCiAFpd1OqMYmwZVV@Y@=myu(2k^1@IN0Wf>n_EcBL^w*dg3^+7@biK+Dcs69f83=+ ziA|x&7!Qc;l7g?3y`<`DG}Cpw*NOj$AisG_J>asZ6TkAz1qR4Zn>*iji@ZBe&D{)abEh<^Jl=43R1&4UY7e9S`~cV#mwY5kY6% z{5a>;u#_vkz|v>j33st|#d#bb2#a=?I3B|7VNJP{=@1Fj6J%OvWk~`d0vWIGPqzB( zHVpSBjO2z$QW0M4Nw|NJIAsL#`7?Binv9 zy&X^fQ1T4Ja!61HSGW>eeLljOXS~cw6Zbx6^#64tId+J&fUfR8j!=QK(89=n9HCRN zrnmO}WgDA$J71X%Xk;}wc|JaxQCKOov;8*HM&y(yNPAo->dk199dTNk9`a<|R)wQG zn}Oq*2mp3&cPgn?l6=4sMz!Tf5w|&&^fd{vnG6;ce5C>U8@o2W9y&c3?QarDhk0o} z12z9dy9^8?cc@yc8TAiepHj_A@4HO4QWlPx^oF{VQNxdzZFPzkH!SBW_f=9(8~Ei7 zoO{G%o=tyGyr2g2y1R^_h$BluBh{bVTk_EM+#|u@b`KvajdI^^y+00-mzQ6cm_g9m zo?fs?>Ms}z{&Byc7c@wcqZX{8W<#k()gHG~UUbb?#JP$bzIVfKU>$=Z4EUC>pJhlRzUz?L{f3*) zU`x#|NoH`orrOCr!77{%rkMkT&CQF60(4hA@5|0fm7l{)zcQO}JtaHJ<9dR!hI}4J zSocqK;LKLaGcug_jFN^R@jOk}@4fL<~LG!%qN-l zc|WmHEIIHt{eLEV8NT=H;(3!h^&|-JoRoOpXPX9>Dz2@_T5prVQVckp zK;I-^Z(SvsGE%i5r^1`4Ac?a?$mH5kQDE|aHOaDm4*}4N8_SF!u>&Tp?4SSJx&2?F ztoV=Y0#r>-+CX2zalFd7%b7-TDIxKkzpL^6)w1 z?xdSU$K3F2bI7Q3hIiq}9l{_eon1B2l1HpbX*gCR5?g-(!I!TI3fp6RZNh7)Y+@?i zT+}UzV1fV2Uxnnz@4vj zqHvg|6Eme0aSETvO z5Z2`xl_-;(Z$!av_TQ##G?oBaR6K1$9)zovIehD$SgKva(ODAWRt^sUAu5$vyN_gk z+|R$CT+&1q#p=T=4i1HYsM5Wq7XOGD(Kjpkv8rENU-!6^F7}RpjEG^er^YIHgghH zq2G?@W|FuW6%9{#)5Q|mF}f90JNWB8LM5@EH|*PWqZrggOM$WagE*~ZP_y%mK&wFf zX)m-XOy9@Wpgm{HiQJGv<+{-5QpCiORQ5Lj9Yf*@i$G__?2p7%P}yh?x;~tP5WQN6 z^ME~=0J$u-Kl7bZ);sJtcfP@pv6-l4UvBd%Deu3pvFql@T5NU!UK2C25UTpQzm2^; zD!MsO+L??^Fh~X_Dwr^w$y>A}Os0z$gOJlk>Y32F~yh7}xuBS79NupsbzA_OZ+ z=M&(%rb*n@lY)<~;_Od-)IHLCRdxL&GI`cB;7y4~>cpFYBx_C>KaXlUacfYphV+_{ z4?Or40{)->0$I3Y(G7Y;RDNHmx~Ut_(qBJ)9BsgBfVbVHb#( z`SXj4{C&MrP%905^govqo*VkYd&$FxRxN8((V21t^QjX>cXWL`6^xGbI{%nhw5F=c zZpeSxI}+UZow@9NN?+V46ge{hj8h%2IW0SaoDTXJ)RFd zp73YokPP|cFjB=4EWYHTMF6g9s1KZu;$TZ@1}j09E9fD^lAZF@2s)VvJr2p4*=8Di zd3m|()l9iY6o6p(Yq%2%7`4D^OvVHnPljMJ2j-uqarycAn}nsBSY3DsXV9VhHlgHr zfc@P|7AnQR8{k*Au`b(nsgFHmnH?mQ6mPjICTKIgCH zl7UG`2blVia(kJZmI8-1mjvts22=KCLtYH4jyIc;lRO*^7d7@+CQm2GLIu9h*@Cn` zrh5)!C7v3BwV}oKM>4-@>APbx`;Ef1L(KjHl!ZAWtrAT59mQio6(+Sj*5JP+$!JA}2Jwc2ax1o^sK{}mT zd)_zbxJKn_ar<$)!^E08rIq=)YlVN_jw=~&>;aBSjy$&+BL_2V9^1szmA0==R$3EiY$W_VkB?0+G(_Vm zuHU4m^T1B`Se~xv@sDM$?XI;4xMel2S5s}M;^1OD~A^C{M@Qe`+LHJG57nqnTw3`WqF4JM~tS6*q6rgd+e|WAzsU{~u zuUsZ9Eu^>`dB`wE-_8#^a2L-H9xKo>x{Ugm7$p#Gfs@sA@QZtPqn(l>f4E%GpP>eU zH0-r>=j>AR_3C&Y72uwut{oASMx~JlUutq&55gNPxo29kdFy;Q3!P9IX7W(w#c4d8 zoJVV5V9+g~Y>g@)dES!?)8~G*A5o$*qLIVo!jp{~-va^NN8BOH_;TH%_*5z~O@9_b zA08gXeRORjuk<<~1*g`E&%KjSvbP(FAn~&Zycv*~o2*3|Xw&7aHGAv*i6Y1=qOFoj z6PkhbiYWAP4YwDOS^w~1fJswgj|%h|id>oxKDYvj9EmPSDd2kmY| zxWC6D8{njWe($(`BPaEhYuQpp=OJ(PhQj-%-Z6!kdoDRy)l#(vF>Siyll)^AQQtTF zI!uunFWgJy<<_Rpus?SHB#zfx{{+PIu>fks*NEZcCcaR_5gooql4o62#P%ZGJ#7er z?=fQ#!_Oq@$VU1&Ia%4#)1y!frqOE!Q-nHH!4eLVI^mXpnn)EmW1kP-Ls0@-)uW9; z36*vvxIrjUT`<3NXEMWkQ+Ei9=@yE&mnU?J8z%`Y*7MW>8KtsWV4iQ^3zciKPmzk# z=Zl;Th=~!!fE5?}~o!;XfrwEj=_zG)ZcCLL< zvTwdA^;4YdaF#yV>^4orjSAeU-IyspEh$P=bW?xqFksoD#yhXQsk2n#iyy6 ztpKhdjZTHWk#>J|yaao!C3T@%<%toB!t{XqrJ}t^K+?RvfP&{&ZPB@AzM2fv%A|$E z4w3y)Owd0Gn=h4A*TfYnb~J4Wi>-8qWul5N9@t`dtA?1Ti{r#PwUa{hrErf8X#W_NUGF2Zy%^9w%(s zk#u5oLkRHd9Adp2Zg(NWwa+-j-+qM9tk7=lORckr8DNN;Pi$?)!R7G` z?iP&7Rv8g}R~sf&ekHp|`u3Q{6%2YA6rfFE4*Sm2CYYkvdtO zH@P02D92=tohlV59SIi9)rwdpL-z+!K;!leS4t~|@R9;L zoiv*OO1@?uBt;(HRddeoO<~T08y4M=T_Y@3{lDh9z0&s^2T1 zxbGR5vVc8B21fDql|m>9u_t0gm9QW!cFkx!P9#VK#w&`W5xJ`2L*9d(EL_MdqCfk; zyCL)f>VJ|(k1gTQXf$+3B@}ls{MykP@2l&|RH~ z+UeDqa2ZECy3+KdfTyV0v-Z;I=@a)rv3Bcymfl9b`>iH;y=xoq)!}0K=*F1MeCchr z9urTu7KNyN!2EZkQOeA4u zNgW*t2B(WhXl#8!>-*t;u2_iXle$~r1|(Do0fN6`q;@Y5$bwu~NAvnc=JEuDe34Ao zK}?I@M}gP%v_CLF@YfBry-Q)&3dq=q;UT;quyA9~J&Xk9aW@Gl0--q8tuQ5~F6l{0 zR~Z#&WVL^hO4HkZYmgOE2u_?DfcCLmdFxTXc0v@!G94}aIDs5+_QTlY>d-$YCntI( z+3jLyYnc6oAk|6#OOW_diDh$D8HP`F$eY7>C@JM#*~fH#27$N3tFrA34|LUi6wM)( zjv@H`nV-j#An(G41_2k>xH3I91u1`2$SmK#eljK&m~~MM`eGGB8QkWDKCa@zRNTw%E+(UE1JofProjRO4jWo)#J4}xF36kkyY zJk8JC%>pSeA}}HRMrcgZ~`TOJ5SrTW184B>vE_N2-20?AN0 zbN4gYypa`1!x2gZ%zmQ>N0~n?dE!wt_?4>fE9gGzR|!)2;$SrH(}7-b<6X0i85;fu zY2hnk)MV%zA^^(>1XxD&#j)}59y60PV=h01%(ns^mlmoiar*R~BZ|ZHj~cfk$dzLL z3=sIFpP?n8`Z!$n!QrAl`J*wk^|9#ph+%U+HMoC#O_i8qI!@U2m@OQphCb}H-x7(# z`7O<4U4$nO+!D|XCNtu`1FQ!e9pFDg_*O{hT$aei(}hO1(GPh~vwELN(9mxP`{Pp_ z&Oodr@8;F&^r2a50s}YMT)%=%TP42BvtK_kNM_`*^N+@UtTMz>{#5>Bb`nmR#W|Rb z{{2}Noo+@Us)0KLEjCeSGRbY+QTz)e-3#tJY%hL)9}DuE6%#td^b2T^QMke{blJ=N zC*fY>k$~|5@%!y-3cXkngdExtl<ALirh-ci? zBUXr@=lKdHnd`ppU$7(U^;6QyD-N6o%8>fqsR{cZM__p%(;C=b-NGXOl$vgeG+Be? zU_6_@cd@CPxP4ziN17QH5-AciJwnWiCw=`js-kT=GYk_kT)eKkpVg)w@54i*XoU^H z!hg#jn|k3qZ-nqk5b--zB|Ir73*yDT?POZHn(Tbxs)*FvnS>y98V8;ps#C6mms^IN zGsx8U{+viUSI`9@{e0>VyH&35V2#vqrh^3|IW?+m_NI|x{Q=AS)wrpX6m+MmAJ}oB zLIKP7vQQK%e-8u&9I{X89no3ciVaUEe0td>H}&h1&;_c`ic zGmlx{Z~}9kiqqn;@}|XeUnC)93<*FI!XH6gJ;tB0o(l;d#>t)Rbcur7UDBe|$QadW zqSI)^ZPe77GHXIpq1EZJ{VLRu(Bvkua`6OSYUIygVj}lTLv?X8VF)d3JFi}-S-!oi zO;e+%wIwL39~EkxOi8CpIs6Td5PmDtDz9Qn7{hD9hk_cxzz>xpI&bX=T;QE_8DV!Q zkG%+6YjVyC-o4O%G5SQtOfr!F3%usX&x7g%!m$u2l~-KA4WJ8491TgsDn>UWYQF0_ zUO7!uoGUGMIG^vYCnQx!#6k)cZy!9v-B>Tu82OpRPv(=^Nzu~Fv{1gOs3doXSl-24 z98zCV-=4G+yt!N523fct)gDYj08DgJQfBnFSbO8oK8itr4`(F(^dv^%GThfMCgSt2 zQoQ~#;TgnD=B~SE`?zwaW54=&T1GJ1L1{Di2@diL9AhI@A5`D>@%gyNvr!h-!{?Ns z4m%5J>mbTpIIt-nnjrbiH)r#0`1bUEYeSzcY|l=6k-1$F!}E6gbB@yy{TZZzS%LIE z?bR07xKe2>S_!#47uRf5iFAT7gwF~Ed)nk%THy=K06$z{UGe}13n6BC07AtC*K3z+ z|6~AXu1d&TR(f8$M6GZV?#?k)S+>@4I347iyxPk+;X;;3y0Yr%)={gJv)zOW3A#SXvW>}Z zQrq`%;0m9coz?A~myXqral3Ehd9-^RG;;EgM}vSt_J7Vcign;*r_-_ry>~mDI8un) zF8et}WfxRrjoa??a6{nk;l67mZgm%90Bj#SCqrkl!n7rnVfIH(PR_C`1AYCUjnWPQ z-cVB#1z5m009Wxw>Q8XxsmY}x{Dus0NebcELvsFaL$g=GrL(ZKcs6UjRXDTs4$X+h zBh}+p5@-PlAY{v)>fbruUds=p`#P?*(9(g^y3ElIJERXWlI#y>`R}VP%(G z8WWeUqPpYW7mSHG8cKzd2?FnTJqHJTFo)>_UP}tiY`rlVsm)Ql$VdO#-Y!eQ$cWfr zz1+2U3u}9SW%cCD5f*{>Rkc@F?v{3RDVa?lHJKD zjv%SLuy%enZ?;qkfo-)6A0SAI1w-oVXP<5EF>!faVV`jkq(ouQ)nwUrf(x(zGWC4J=z*et(nwE2xrwvCRRFfKErP*sMBD0*cu4?!ivS z;K5-aYFL`|b^V9n#%kE{of#OjOEd&AGw}FSsBti936JVYJm6=v5d&ue;RNnEqJwo9 zo6{cNquvGyTxdwy#<#@6di;1WBt?kIOCmlks@3fg6Zc3R^AXE^dE%ArTGDK1KeO8+ zc{;~ggDQ)9-I4DHTrJ@X*Yy+yG6ua`=iS#uUCvimv)`>)Z`2M~*Xu^9sq@O&sMx^` z6doSrvK7r*tLSgY}s(1VK8X{OuU zx@hK4hws%+NFPd{`w>S5<{jxWvD$AS2^Tr2H1Uo)GH(wI4}wwXm4ShDZ6x6f`&ZHNbA#$qh=Q2f?#q$033FCg zqhIfgJ%?Rq4O$NZ!VjTn!hdwUkD|WqE-Eely0}F^9wD}J<3%Z zDLq9a6#7M{OOt@X{fpiF7s^&=T66Zc6Tx_8>>}PHXn~oKkQMVXu=r&WP#mLEhciup)f2cxYwJGqf`ev@_$l~|vS1^euqTKlyQBt^? z(T{Mch(2hM>`#z{SA9H4@8snOqq+V$5$9ZV=7B(HpXBFLp-07j0PBy!?zV#9NgNNU~M(C?k|znqmzR=FH}uCbQ&a_78ot zm0#UaDEwZ;!RXOHGOrlNeaBDRxIh4b#X>MK>l6D)sbQabfe^`8vI&;A%l*X;dYr%- zR=a1J94M@{JPmV6j6&Zpa^Q{C#0Og3Fdt$t@eGJWpoE{j#e_Se321kOW%tK8ide9X z+l-VG{tQkzLl<`5{uHpq~fG^6V#Y2^Lr#XpI|j@TKwf^TsM>&aDzLFVF( zfnX%xF9rXWoK@ zdfnvT3k!MnJdg~XjTJG;3%|=>sO-(vqvn!ntTuX=7&qv7eo3)CtmEGdhbw`Sby+Ln z`>3({jC<2L_Aoe|M~+<#f}bFSyCpb2b6ZOVDo7N8|KK$WnfN>Y7Yc~~LILB+Z)qZN zd4h2k>hS}h`+7b|j@tc`-b0wF9zJ1k+LJ$VTRfa>A+98L<(k##jtFRl;;`Ci_OCv* zURK|rqtWUFa=BgXZJmL)ofZ6{6QrqhiMwlifyOiop+?YVSkt9F^GdJXZ@nE*zul;; znC1-yhNU+IxG7T=9;r#sG&93JH^zpHD{4n8y+0ihdh~EY5{N3E*p>PN;nx4;exY=# zJjB-yP|>=>*zSrdW?-81i4B!ux>pD1y|T5=THsrS)QbyboyRAM?^s>Sj!= zd0S|g-?l7?hJ7L2^}F$usjdE$P2pcPF(uJiK5lC$7TgizeRQ@v?SNz9n1&6WdR-os z{@#7{v-Bq?hliSI=6&ATFHb>m&)glK!x~PnM;(T-V(V+bogg4+)j?JP!=QVHGegqv zfm&TDMv@5UhY4VbaWmk+!A)YVBbDv|M3&mE9)SD(lR$!f-@PuN{sgsHnGl#;i$qg& zKcQV4EfDfWpqSW%7a8-z+nS71rMXB~2RK{@_paKM@9vNJa`__fFoMsG+L36ma1s1C zhlf-#w*9CnAkhv=SE}D*HCVD1xgV)djc>TX%}P)QU|57V_&oH852sTd8+EF3D$;@w z;K2fvg;iX*pSNWw2E2R%KeB=GWtOZ>;1Gr`NN%b%r$nhp$8p>=5;-H^dJ;wiis z^Bvs_Y~N30ZpPA!XVT*fYLNP)^aleN+_!v6RWTO3lL1?=a;EjyRxeMvl2JN!qnn5# z?ZwM?vS5I4CxnlKK<}b0a1rBpsh5>SiUj}#5-fA`A5dVa{tQZIFd(XqyayTAOm;hk zCIw5V((;pDfv-J3NQ&(xG7p>zzi1wjL1hutXsd+?mRzSAEhBfL+Z1-rj{CDx>~N;h zH(XQK%-1^_@kE`YFMZH>c;?$(u$5#@qP_y4QGJ&ybEDVH7cY7pCk%}{Hx+m zkqhC{fy9Qu9{L}J4gNI-m_6sbTVd3(7Dwu49l$IHECs{p^1sZ-TN0-*e(xx`bTLA) zh@j&c(P;wn!Qr5^_!X@yRbPz&;i{utu@X>5ZJ5s>`dMfH8`k|h3b#ewxK}#cdj64@ z!h9r{8@PP|7S5xx<;;gL%6tzckT>6b7~w$#Ui?|(`KtdE@OpXl_tAl6rbzb912^zr za!Ml+RzI_|JKdjnO_vFYA>BW^jC;Ux;w#t}p6%o)3{;ow1!@4{+SS?8VuI`V9*)W9GsKOk#_by125+hRh-t=7 z|3r96Kl^$vohj!amVz34|M~~wH6}D#!}@NYV78HhBq4O4{7{_4{o}_MI1&6WoOn%$ zFUUuY9BiD>+U%^mwzxSbM^ML%*f zI=+|y)wabwq}g^8Rsr4s^A99*<*kr#f@Sl(RLi({JBPPnwwEVyZ>==c>HDyD^mO~A zuey7wRNi0ZnXU;WbJ)FeWs}H@((<@Am>Xo4NF(u}0GtIa_-II7^2I_1k-VTFCuf%) z9{uA&xG}LcqHo7}X#X6XR!@D?bRl0Ta`BFA|EfAEpppN0ii(>0UB*H^z4$Qkj0#1X zCVf4d?)w{0vBPK>BMN2Zgzfe9(B9#Nlz8bPX|BbExh5LUwPcF8!T4!*LM}}xyuEZL zGW(r@l7xb$we|zWH7<6fD%-S{;Zn0W+s&Uk#pZviD=!!4x7bejCb>F<4-rTK)X+Z* zLwlhBWxWWq>|hF!0pkCo>MY}`?v}SN2uO&OlyrAXr*tdbT>{eGA>G~GozmUi-5@Cq zo6hIAz3+3*|9Qt7h0orzW?gg5cV?Atwpmyb1qc4&#%#nLaLQ0YXF57=v&Zs9_$)ZT zh{>_DGC`|RGF$-P@7$J2KA~q|@4q&+q{?ZUJFFPOb(=Qz_N@K6m2-pXg;)ROL+5ZX zRc(jux#Dkj?eUKjw*HbBes00U*25}qE@bb|yNC#g%hH8YNAN)(v3oK$w?Tn-XNNLr z>rOuYN$#ce8kHWbAMY%X1ug8lSf4&wK3BusG8Ddulapd8@as3c^?G5{O?ede%#ilcqvRKy;19P zt@|Md#Y(l*lOzJY>b>9Fzo(kS2wJ@u=mMlZbYT%}mL^tiE;(i8EkM3VV@@PPBx+_F zj7#|h2i*lFR%#Pv@HVW{(+?(1eJLs8O0PX&)n)Y6hAN#oAjU)1bp?kQ9*`PZGwTrFABeU*$W&i>zoW0XF=#C zY6L04wU6UTW`e)m<)I9&-ReZdyU48(I>NAJT0)nfV}irIDiI5n4WQ1{>%~mEnylrZ zTG&4}?_BEQ7&~RYkhPe|uk=Y`3gk|;3og#Qha*7o_zp3C!fzgfxYqr|qMrAIi35`o z3TOZ6E{Ta@eW~dW2HI)UB)!xQTK(X45YrFRye4RZUiyywoLvP2@bTYPkV^Gn10R3? z|9#tpg5H7I$7@!|mrX69JD#$VvS<3X2xOUVM$71!ZDVO{*aH!`pUd@8C0DA~p3PM` zu#3~Lsbe)q9d{P_7u($!GM)w;*{jZ3HsYy+>*-Rvc)j?Pn1(=eN9;`ctE5Bj3Qz`` zc@Br8E}CsNZ?~j>DK+XsC_ZKLwBMH`8B%^y>T$3s5 z%~-wg+gqv8`cH`R8Z|miXQ?>_htW_@e1)6c-YT^8r4&ArbF;%S`c6zhfZxC8lngBN}JfPpw__1`kXmY>rs5-2l%2?$tP0yNJ>;g1O2 zFb!O0_s=DYl~k6i0@O&EOR>*4`;dHvWlP9|-JZ)!OQv%{!NFhl*~VgxSYnlX?1jLB zP<;1aFDTyYP0=G&3{WJ5P42j~GKwV7 z85UheRbnZ+LJerWf`z4K2Q*NB7bwTmP58_Bj3nr;>|NIwjZtl$Y=^2lcrtzeZ6W*~ z<~^3TN~LzGzoPQ7Sn1*S+8YB3<7H@g)D9#{A$}P^3Q;9)DhI_ zJHd@^wV5dHhQZOYG|KjQN~R7d4i$2d}wSfFmcen={1(zAX_(OKfa6z)&)sDnvE ze!-}IO&44B!bHA3W{xZ@iT}zj+$sN0Acf~=ATN;tDv=J2unQ|H?mn%_m+2+hY`zAO z%kkp#a@|{l`~U0$V7clrnb2LO)TvweP38GQDOd7qeZX$*P@v4j>py(M%)eZbX>0Lk z6vhA`mcp`yjbcK*ivh9OG5o5D-$XNy!Xtd~Yt+Un+FFk#;RDh)^k`lrOb_Fu!_E@8g=#ZOE_G7~iYr~CCMOJy;A(zX3 zq~40CT(%#O3VbD^80qLRWx6TjDp4ZOUwvXL!e)Nn3ARrCaon`g?PIguF}N(-Wp&xp zX2@hXwjJ?U_;st_^rEgluA7eP8Su2_i{$X6kpC8?6#qA93h2~xr5f-h@E>C-A}0$q zFt4Q^NpYC7iFMLcQ5)wE{GrjL5k#7@daZ_`aQSTqXG=umF`=w*>JLx+7RsKec|NpJ z(1|UcY+rK+l{+SyQWjuS)88ds7o-l9rlBql0qip_0L;9?=wmsLthplu@`q2Cbwnb zMM*#6-4nN3%(~U(ARWTRce2EXt z*^Nm_QtVP)Qa94ovZ7?}4K(nIWP^3Rqb}C^R;HcV^nB6mY_3|Z8@KPiEV*p4vm$o> zWSof%_XsMj>V>+<$diL+ag{!cxXtH=!)Rjvm5xSb8|LeLEgcO!a0f@`P6S+=VmrWmLGU`Y_10bsMIqxro0EUs4va@f^C#0bn>$%;M@(Te%Ze{>>G79O zcf0C(yv3x-MdcDRZNUA zEL7?ct+HUGtv>bn!|}S{^3(Cq(cDKxL<8Q)IcY*oi@b^uFBqpBQTdm3!EMbJtfSRk zv5r^Gd9DwJW%Ot)fC0S){2id!Y_b8$#R%kGfc}l5hfAWy3JncK)1K66v4v~@`QU|O z-0v#l1~gkwH`>CpvP^;%S7ptyVM=-mlF6?L>)@%WdYW$nwIh`v2%D}y=&*bj= zs@u8vLfX!=X2+2A1Oxrk?|94A=C>PD+t-JYMitQ=G)nRe=@jP@!$8B*`k`zK?gPU} zkG-c>D~JBJ{(bqpp1HvY&rCV0pu3sTq)aohuK4EyxbEd4#QM>rBvufgacby^YpvZ~ z8XivgA_cAe?o4P9LbH!w&_X8YAOx1w=U=xA(!E3wFuR&5fQC^V2^Pyu&%r;};1rGL z@%fi7gYT~ni)QY zX5lLNwVQNwLHR-qBS3{i#*V{B18=_bo`2-g1fy0$K)?1MmYh%vl@WN(5blr1ftxfA zKMc?zoRzM>b4WfL$?cfgNKJ?hC%i)FcqyRH&npK-M0739P{i&iF=w`L zGjo!Mp!JGh-0Iyf!YH;!$9y0@&jwd`Q z{W3G=7unq?mP`Dba9m6ISW9TlZ}U9}UCENf8pn36%LLvsFD=qFdX{>p5*7WOK7s_y z{eeU`XGR=#k8w@L#qH7Hf{B!p+SumreZU1U2mdhh0?nklWexOH98YA!IWDzbZ8l`L zT_P$*BhTKFN+nx3H{Fzpr8KgcJU+n&J6_29!@Is}AWRbT`eT?D-VHDEn-e)pOd$ZG z+wAzByqPakwxzOVbI^7Q(|z-mZMY?ASahn}pV6Wl3!^|`6=4a4*>&)TSM|&&aoV?< zHkpM)cMErMX{ETiz+tbuG9shxx?AdHxeCA8{!XT}Y*A)16mzlVmGFhfTKua$xpKyI zkT)d+-c(XanEGdO62jUcxi@UmJmgP9*ZdgNH=vFdzsR#B=P>^YcTX)?t)a6&gpjsi zaj53%BWj8J&yaw4IPhU4xI!5`snKb+!@FFXxqaTVn^v14-x|#BxZ?A5A5S8)!*F;w zTBy9*6F!t~{u>T?cHjz>mX%;je{0KtyqnWRwvFP-+n)%(pP0}u&^(Y~p5~6q$1AbS zST8)i#yFOm*tz-k`cLGM3cXZ9_Iu(eP4Ms4%qzw-fK?S_EHG>MQO-Q5agE6{p(!eE z8-^sp^CRiDTDt1h1Yh>_PD4rYqPEGm8pdO}7C9sw3Q3D4<@#Hzmo3aA9d=kEbSkk> zw^$n1s#-;(p=a)w4ChmIjll^|57s?5hA7%nLs6kfb;`xock7G$LN`e!&c96YPqkgM z4ABgwz*5%mjhtf*;HCl%3%UQR4GCzJMKgVbkkRnU@x6Zhc+YG&NElSCxP?5IOpN&i z{oK0b$#K4qAH5ovx&t^kA`s?!CKM;8$6$Ag$=O@~XB6nbabM|uz^JNEQp*6J8>YcD z6HUF_^rT+cx6)V@D`8Pl(_}fogVJfG(_zHntO-T9xH}!yJ0{DlSYS5jHZyZf^V$P< z#May1HM&2;$Yyc|R-MC+5d(PId$i3Qrc;$LkA%DrM1i|fiEqmAYI{5JqI%;Nt=S;nLKL732asb|OK7N<#(FRwR z$9{!trugZFYhz>sS33U;zQ;qZ{M;vNTU+_UQhMzUSF)fH<#)7X7fJB&>3H)zQ$nPQhlIkwWp*eZGwLF*YX@uT*BZ?rNJ7}p=G#y;={91W^?AMWQaK9 zF^TpJ!9Lksfwy5r+ZVKPquBl(Ev4TVCR@6e4IwC1ht}%~6cyFWPB4NQ?M%(>#n9a0 z-w{@TEmGgpp({|>tqmVO3;U_{$EFo~NPXRvU`)u!a2&=j1?z$-Kq~&D3k0C-Vb3v7 z5WOq{_R5!u18Zw#D{d^@HE~;;?K?yFzbs=@J&msnVAdTz5id!-Oa}+%hv_lo#&PUG z88m2%_7v(MkqUeH)hXqOkA}E0FqdH(oZcZK)aCKGsR=XIPZDs}n1&iF9^XkdY;BWo zJ%nqNkX|>b?@D4Vvj5?>UT^gX4OOYoA2{W|xEoTa(*h1&4O9{_tsGCkRLDq=-|Sbf z;KWUba^0h0p2%H&J({L>%zMGopdhbTT$?YN0*-Glj=u`dz8m||EIaV`*z5a{L{5cq8iZKccz$Nu+UO z!+!H?F>xFKpaQ;v3RnQB>hm#ssS&QOA;3>;ZT)=2VsU3&Z}kjE&6hN|JAea_?Wxe6 z5_G95mmaRA{XUB^wN}l$jLlTxS6(-mo12^E>&3@L4>!lH=az=$KlWl!?Qei6^nf^+ z%_H^MK?dx~*QTS&s)-o97L#`+F|>|sz_=Cn{9*%vudSjWKDjmMh;dloWA3wN_ILv& ztL~?6i<++MAWE#{{M;5NHE_8FHK z26U6-5~%i#!VtE2xSs<6&tIgOo&syd{gO|49M@EyLvo#ovrF|K{a%O(FK^m~bvClN zC3LP;9P=c9hU{osgX!9g->(R*!D{8}Se{a98SCzO^8`I#w&52$3c|t@?j(hjMkJ@e z-@Z|0x=9SXt){K0(t~8ypeHo&Dm%t=q1zG;jCdj>ElfahBc6!yLx0=F|wmJWpTwZIE6Tf?4ZifWB)y9}pPZl`5` z3KX+zz;fQ_vjhO31W$udWUO@c^z^y|#*2!?Ss$4<5(gF~W}uLs|Ltndy2xXu;E%AC zsRh@SLgs~}q-kdf5M_@au`{6DeBl-*M~Xf^jKOilK0e=E=T$>WykA|@>*1L@zx@tC z$IML(ibN+ssi3;-l3=PwIz)vfC95q7+dsTO73i1gv58C&kd9Axad^)iilo++EHiJey6p;W2XSvPX-1Fcf7O$#<7V0OHBc;^j#}#@XQnN&^R{mY?dC*CT+4WPpgrw_7O%k)`d^ zx8Ux@rAZ zoff2H+UoseibYH3il8&~9$Kz4-|>nxjGy?M0X%~5L|u$4tr{a{OTCqhnL~-#-}8$G zKEIT_1Viy7(11e;`@?FjF@OrK|GUlJI)zHb2C;j`TAK&X+XrXU-O#nqrt9!pZLaWY zG>HuT3E>hNPxx%EJk-h+@c4UoncHH1u!wA*&Z>QX>gYbf>MSlU=?|VyfhU`qxu5XX zqJ_Nl0Gj;p^Bgo%$7q`om+^3(BqUOo%VFlWpi4e6VNv*uNC>#>02ricrFRmH#&y0m=P(BI#$O!M*R&U^H*b_lvtmXZs`WHw-#$^TX^atNBL9Gh=rsLUM;IsQPN% zql8mu>8dgj>SyXmF&!Nt{LAsi+s?LNJn%2{+(; zH=IN3zWb_cWKn8K{<7v3#8(&NU!l17%5BzTAFU6*&gFqMTYZqZ5h&n3;YZRaMU(_h z%$?&97s={48BUvpbQLBnhi`5fgbRsj5p3sHNeFDHGx3jB`ixKBrfhw{%QcV~Y&Jd$ zFed@Om(G|so+~fzwB9@G7}vHhnqkVN8YmF?i4Bk-)OOu$2jOoqT^uw$ljZz=Z-t6n zUY1zohsc`?0Ei#S2`?hQY$;ENHZ2b9qc{wM>-R zx4NQny}H2QaUV2guXh|+%7#?Rr<&RHN9slL9E^8d+)&*LCkDbnNINu#aYc$}+=}Oi zp}GT=TUf977lq2(nI~RHaXBjtUw{;%md%~W6X@NdTCEi6k0nx< zPb63~WvfLm6Gckp)W8Ts7RI#c9*!N}r%&(`d~cDlv5ll{sD+@yNIIeNyKM=%akvzX z@+8%`4gC>8T*hNBk7DkOXTonfFc*XoRKc!jo^-IP$d1dBf}dA#XyGFgCqrv|ciVxasHGj-*j zll%&poE}acP?&nyZgCU)-VpJ%67W^09mc-Z9iy0G*JV-YbMSv6Z+mkiliVKKCf6X8 zYPR0Z6I5?=&@>#p*9g-!u=`aj+A*vq$K?c5owH~|f_qfyjy#qt4F3GQi6CtzDhO>m z+8Zc^9OU&gnm{o-X_2$#8?bAx*9NKY(b#pyQuwd~Ut==)kuLFq4_UopdcC%nmBO%& z>1c+hKZe2K_k6(bM7b$^ij1EG#-~-yopH8tu-PkhLIaUbb6rN}50OWhrlt-io3Xol zdOF+kp(|F1!va^htE`YdoUVit(5UoOj;R;5`4#lvR>V|M^-zMl>+opk07ee{@P2uD z9)`95kz|$)^Y^VxUqJE-qKdenZ{Hg-RNm|soXOkm=!Q)E~I9#Em=#QZLgXL!g6b_)c2!N^2wla0dDw}Ky>Qwg!m6H#cMyp3K+ z&#q4u3mIvJ-}zL&FVww5Xes7ZnPka}o-BG{kUpQ6AQ5@AJ$w17T4nF=m=o+IvSjsw z9ot_m;$*R)=guNsX!*mk=V2sMXY+ScPDaALahj1&>9sl@pYt2)m#kOKJIztI1K769 ze^}@!k|<<6h|)-_*w!JLaZlUbRBndq9e2OiSI@0WCF}9z*yoN7Wx9{sKWn(h4&(=#o`*d&u zKED2_ZRd|y1J^W({#C%nOlJP^3_hQW+%1sHpc4k)4zeVZ7L*e(6!m8xs& zQ}_;#w*ud8BnP9AAs(fUs+|X!m&Tp&Rv<3Wxk!eWQ7TXttZgg!*W2Oa%f+B$A_0XT z6UkaCE%0>xcWDMt>iksYkxI}2EDOsw0>U{ z#aF&PDoMA6Ru7nW!eSydiPVMf9dsDJTKZ5@A#l2ee8nLnZ7{gl;iLpNWUZI{2l67hcR*p7W<`uWx*U$yCL#_(s!W%LTz$FmehhM$hK zpLY?3GqwByk^EV5(ny^c2-(3HAThhx_sNdoJX(m>R@JxbPH1F4S_mrW-qa>^w?xk8x!JexP^J0WQ zn!ha9q41XLrzM`Y^`zE&No=4bt3eskR&oSRas`-VsF)-!}f`QD1CxonNBCD zj0=P$BbS^2;kX^g$)Zf3UfFQJbK&)MYQ(L|(x&;ak$pNXH`um}Pe$smLuN5MCK7#^9NqM$0W{H8(aH~~HRyKl4e0=oU$gFK9 zz#0*#ZzWt$t4$s_pDktuSR{@fPM_aleU|ommotsuU!wei^7G-4LB5!agiKRmm*P5Y zXbJ`B7i_Pf>PV$*PQ-Y5zO)sslFHOD4HE+MjZi08uToKgrhDJD5SmJAXa~qm^bB=# zn2vtjMV-E_f~bJ@qTfmdzR>_Eya6UyWQDbySG01bKXt-0EPc>R*-F{2nG zIlB|{oK#R?A!bV551M%yB8#H}L|Dyw@y|MSRdfkMUKA4=t+=h%GeO43K8 znN3M5%`G4Sdxg>RPNOMgkhcnd0FGvHqzq~4{ zW9NlR(d$tX5iy`+%X3C5J0D)Xy@Vm?t$=&LkBprjWZ?DcAE{h{Q?fuB?VU;eBEgia znqFBNFQ8d03R^b>*Kj`KTxEb`nckcbLCuDD614*zh zve{E=9a<0avzQF|HW=+E!Y$d~K?wn#LxKU|3@T=@BO;JOmgNdT#M-Gulb{OtsqgFlhPvQrXrAR` z|0*a^UP`&*Cykp6sl$)Or+0S|PZQcq`I6)XcBvo}8Ig?DX|{%^YJ^huAJZ&(zjVVw z>zxa4O^$qmvN|u(Fy%9zOSQdt>tCwBWq50Radh}Mtc~zSnf2ul2 zl0Xg#36Q}m6!(y-@4oVHi&E%vVvkF2%nmCmfUlZ+ofcCfU3S128P<0F zJ^4&=?HuM6gwWagC;CGL(%@vB5ErAqD-Djb@JFC3y?FjgNVGfOGT(j$x!r z#3E?L=Es`p4*hZ1WyfoPiP|s|zqyTdTL&VhQ>MiFxSTmT3eY;0Xe_FN2G&UsL?3ezSKoqU`z$uvI z*e44U1^jOeDaeS7vwS0qsOZ^_cj&=tz3rz7gH^7u{HplBRMQYVso5j3l8jqbU(5QygVN~yMuioiKsjU6CeXW(wFi)$)s9{wts^smad9+xbI29^$ zqRuW>YAmBTcRfyuH6tVlr<3BX4!klv_{%jHHT**OvGS<1UHJDayFNjt(Rx2*6!MF5 zDbHG-HaON|fHjrZsD&AS6$l?%Ri17b14rd*qs)lL;C@0ANN&50kK1T0pwmGkDQH-E z#_xd(SpI;g&K|pZK#Vya<2H9V*e(BQTdQ>ZE9+!oOJTFc8bZ5W|B)dEpuxIApJH$({wXs#YbW8gh zvD01t!6F52KhJa1ujtLul2duxGbTz{@q<=SaF6+`CZ>*u0;EXDN3?Fml1t^9TT2bL z3YE2KPCVpqa4(i??Xe$3rG%vaKv9zBUwkckX|#bIQpHtcc&DE|p}!5(p7vvBVF?JB zo8fKTm#zFi)6t9%d9JKgLRu;Z8T{W;almP%@gY02O2Q)_ZN1S3@ zb)(++=Y0;M=rg>WJbr$-o&!}?91?oz*uTCAJzWeCY|54Oet3CYngKcO_2xn{8;z5G zbh+9j+8a%cEc}`oqJ%OnnMm&syfjK=wcc7~bkZw4pu6$%4A5a9*GfYpH0C&UifA)n z+WEhiZq`<%%+{O~R|2O_RuYfpN7?kd6-pR~!+Eg{h@WI5wtCZl=eZ)Dpyq+z(B2C# zrUq&7Kud$w^=hXStNbrjn|diPpZO8gv6_OgV(BGYEEb!RJUUCKjg0i9v&!R0YrX0K zfA?xVol*ILYA;#cy;TwUr9*p5gT8Lg!33FQ^s9fF&7yrsU?a!6IOU_JN!82}(wu-eDU*w;6Wf;&Z;k+N0GZUV@p}bW9je_17G& zO`NUXjZEL{*s4RKInfAiF^i|s|K|0Kd^@4j>aCLb#kFn~wCn#GHsoqoDvV^1do>J# z;tN0zeY$2VCk58-0Bwr6Ph_Y*v$6tSKO2Icj0DWxk=+(Z1xxFnC9#c#|u}lGy9WA zzRu@dTXO{GIxWO{@o@-4L8I+=GH$Xw%mQ0 z(asDa!Av8HkoBM69r{ax>cR5)Og`5=lgD={bs~u=Wdg>4H^v!bywp$Y5}tbN;(gmL-9`>@bA(JYchEn_Rv=bny?O=lf7y z`?JE1!I^R?iqCiX^@dvbt_9|mFV3&pnkbbegE~3bm&*NK=hEq%n1$n?_L*di632xJ zm*A|ou+U~oKFCZZ)y3j4yWi6M&ham+-1E5G#`-s8E)B5WM%ADo|G z>DT9B()eNefiSlYHYmu(1}#zb5Y~8GJ?7w0!yXk^^Fx){#g0(-3!O5QE3 zxFLHMFMMlkbN>S=T6G&IA4pyDbMXv{o<{?>O4NCulKfnLZg-X}8Tz6!Zw_oK&vF0|7&lxmlRV5YFJyQ3B&;CAph%Kg8&>sdps!m?YFvuk|7QpGQ z?Ls1=)1JmmL!k`zCZ*b&o9y=cVKBBrD-l5((W~69zgdwnF-s|+T3n7WK;(O5_EE3e z>-7#Sb~`bR8KXxVjV@^Sm%9eq7wLY?JYy#3$Z34foPNhv9d#lT_?a7GZJy65oZc?M zmF*A5=r5;hZs!NnN+`%+@{J3StpAb@DWr^+Aq0&SbWPireF&=K+Q0Z)y}p)GdfiXg zX?(TziC?v`-pD-9h>{xi3N3W))uPjQE{!G5Ea^ypteGt2qn~=E z;HJsak10_nn>@X>%&BTE8pEmy-AQkvGyT>aCSN9Pdg9+CpvyW0p1j-w>oV~z--DH0 z9Qell{l543^4+WyHwL7-*&Salv}pl2F2;pw6TiDRqSa-Uv9~3%%hP%*S?so5G_c{L zdEj)AfGw(c5N4kKA^H95f-`(sSu`-*wTLcp#f<8vx*{Pw;BJw8{^m(%zklT}mdjt2o?%R=`( zP&;(%Vo`)XcQ;YRgRafI(R8|`}W>RuUxec8<3M!DsT`LO#i`Q%wJ^;vwol;4*D><9c+xIDP>b^=0nhi-Tq#`oPKPOlOiCF4?Ma|hhv)b8oaCsNEg>u(p604>&#rFncz=Zb++Ow# zSeM(=H8GQf0VFq!0uKV<)0lW#Y%@Uuh*ok7@6nAwOge0LUxvRrQt2ZmVTEgzbk>MBDqg#aknA@p!9wbnV`Bn&l3 zfEi`;b#Ia1)4}{n+ri|ugSv|0nMQ-E?u+Iio^a*|V9+h_u*N>x6>K$t+eO#Nc^QAV zddA2KI5DXHL{SzgUh=Q3gpMM0Gy$vsMTJKX3^cT86r-U@fi4=%3k^TboF#r18586^QCP zPFby8%*-~8awj8PwsHleD_~+NMZ%-_25-ye!NDL;d|$TI!iG(zMbXTApZlvn3cpNO zWJ{@JP?ps&mP|VZo?#W#(Zd?$%+iHRsDS+}KyCt8wLB1~;h}E3HM3oqF#Qp@Azl-n zjtW%s2@R19W^?x5Bb9vPzGa*o zWb$SRp4_;%c9LWLNA&5`_N#Q6L|?D~JYnYx;)R!3$xof)QwyyS<|$P)RTBpTy>G?#rNXtPxo8g`n2#L zsmrdLe!rgad0Y}mXL2YXxlNXu=*(IysydrA>WxX30qa(jDuKNp=NEYX?xPiZC}?P* z7O4wNXWGGA1gs$YN)NGcp?vB&!o6Ju7Si1@oCT)Fj{4ho@rz+rSGZhNmB=wMEBhT1 z0g>2|w!2=l2u9%H-@C7wzAa9cM~?odGk-~|i+5?m0b;&PGX$#J(Qi?9uHI^9p7xi~ zqlGgwS|7RdOvqyZOFj(Fii8;qM3wRcg$aYf&1+%nAU_syq~pKj1AH8yQ!Cwd0tS^D|HO0|l5 z1^|@pdD476x!_hMhu@R8j3(95sW~2bbB!{>%stj$PKtXNj(qIS!$vS~ML?oErD-@) zaO^u4Z_dtW`((KELLR7lycxZn)bhRfht6GO{5?wn)-JEie3B@{3$|9hEuG_QlMYEd zeXsyENvEPd+$SOmRuO~w4{Ca^T4;-VG<5H&_m(Zmaam|FWQ=mZg4UD()TJ0Y<@4*C z@7~}2|AJqv#TnV%NCf;} zUb_O?slhrq~y>w~q1>xEJ zNoZa2&(*hjZ!D#AWkmz4 zciG{n+Iowa$S+@#vEJ-jomQ%hfCo1KYiNw$Naq~tS|#7CpsSRHX{e`ECf&IG&1RL`53u2RZJ385|$gD za*=i}#2_DKkZNm&mowc@Pkx)(R(yPJld9p%$dM7HT`pxt+Zh@lh<+Hr)taY5U$1u^ zYq&hm8-hs3JnURdv1*UEL3>*oT2cic&iitX#rZqvm-nHSV-$SoSn6v`>&ra1abOLB zPZILC+g~>f{p-yo4ioB^5_n`6d7;-H{vGZVO_>u>zstN@2WpVpAe9mQ1fRXhU7?Gy zf%me$x%gN^_bVd4by-u)qLb6BhIn=zA@Djzy!zN3{*s{L6M!FP>>!E|ChvP9+Ux_2uv=ak`B zzTRiF5cR1qY^XSIYNt3}ypQF1=vAoMza8ck2GNBYLFGtfDSnqOO>38V%qVI*Rc_0f zj+O`RwU@Y7rP@5}+vV>id=6AXoh3fVNZ*G$jnIJaTbDTNT|WkGLJF&Syi4Av+^gn- z)S@$G_p6Sh2wWPIdj8VszLUjvnNu8Fu}Oy#<+cg=2bXGbb&YNHe;Uidjre5hh}rDJnFy>!-HN4=`b zMj;o21dxG$R3> zMlSw%b8>Z3$)H9Y$$N7qOmLWpqvPgK&G$B$s}l`NVZlwpZ8vYZa`NW?%MKZxYj(Tj{Y8Ne4RE|%|2JOp1wgSHl9f1C323Peu+II}tE;$b&wbR%OwSUW zRUNjq^SG5V*L=34&T?I>8xvh`AB{#|14a_YQr+2AzN^K%gtGlqOJ!L$?V!rUnrw2r zeW54lc&(sKd3FCbv-r-oI-WO7>pOeY zcSOjckPpHJukEfvW6XPS;bgcjzc4->QNuZWI-(nSHO}5CcO${jz-D)-HzVwQo6^{1 z^qmqCR+TafQj=wmF6!#a)hMB)pUR`6Lv&Vka5yq$>u6bmwl} zhV03(&ImgrhBy`fk9AtWnO;CTaWqoFW_GS>FMIL$lb?urRGH4R9mZmK!0RNH&h^Sy zdkfXC`0aRC1c9tgyV-MH+rl}Zj^Pv(u}BEq z4{x3OR0ZBZK;=khJ#+3$gksR`9vB=-l_ZFcPfX01CnY7327WkA)LNF7Ia=_fG4FWn zuSvdh^KOckMw3Q7-fP*^;+joKLMHyn*PV)*GH$h%=icDV>N5A{ z-7dS17Zr9OHCw8h(a}Mfx|Dn~4{^kfS~!+srKDcwKny- zA4K6etTCTY8eZq#BB}UF0Z-2D0wTM{vWHx)?x8eG`x*7S?x;egK?I+qdV?9&*snZS z))V$yE&4>qj-AkyHEHM(zWXas*5P)O?9f@A*?iQDMkX}{?uK~kb9O+{yDx{!!NK%H z!@~(Ww@>67R;#4u?OHgOn>s_y)e!=u&>^8$MM(|thYXKqp*??M@|3kmFYaz0+I>$l zB~A-x-dEOMW%LU60!c=s6`=_D_6d>YeD>(RMgx!INIe_ih|iUrZhUZP{sS;OheF&fo0d3(_)#bl?d zr>76_N}}TIv3`5zQmwJ%OaaB6C3Rg{2E!WDfvj4KV|sgKIGe`Ob}T;Y^RD2AwR*82 zO;uOPKIsen(0hXy!^McdADXRCukspc@wE~$bW=>VVUnIB)5%x$8U7zaN?jo^{entJ z!y<2dh7pQ7dd+7-T@cRw`ey@r$@j%;FmM$VurN*@C2aZKL|;#Nll+U2tNvz$q61lK zAK-uQjq|qBr7fVAH9`@1<3ou`$hddnr{&9 zRQU5St8A{qYb@s?A8a$H7Nle!As%dpF=uva7x>DbL^#lVB;k>1jKm*_mKG}#rpw`wBfqdz}7ewyf; z4bz*+NGXvaoawHWc=g=ugs{+$f-Kf*NqE7)+2~B-$^z}C8=h}+*ImZ8?iZVUJFH8h zNShS)YM0S1i*WnIW{d?|C!r+-ZaLUH_{JDAr7`*h<*%1)?KCd@t(C73hsg?~+0Qp_ zd3;d)#AFi=C{?Ngj|k29xZIj$A(1ZgT7SlVsVF+4n55h|&F8oeJ-a7-{PEoT8~&Rn zBlxnL+SY_Z20k)fDA+LQ+<_)oLT_&kKoqU`bYk(Nz^XC;iOy9)vJ4zz!z;xs3246I z5v3)h8$6Gsg~~u%3Q3l#&8EUtd`@w*)3s&S61O7Tvj2GZ&YEZ%P%3< z9O|Vlu@a%I`T6Y0Rh`Ae0PCVf;Wu?lybZAu6y{v%1(Fb>vr zm~oz!Xr>^Y))Ar$?T5!3dw9zfwrhoHr54g${Xqo=RiDS5CetgJztG03CE%E@D+JPm z7$BZ7-05+!z!#zcZ*q&*=$5O-j@G8-*2H|JfmZGsPTF%yCR~RE+2iskIC95fx#`&= zN#u&9j2#fiSvcDhd!k{Sw;L?frYJPd zyyy_MSlM$HL^ni(@Kp(9| z)Ic9F+DDiL(#!OFFGRLC5YZt~H#lO6I1qu^@Ntu&#LGvswAo8 zG`5ShSIogD6|FcB<=a#njiHm-sUxM-Bj6LTCaA6$3*v)(1={S`jUXBM35q;ALdY|| zU1a%q3p%KtBg!fLuz!oShE~hA_KGLJ#z6J1#u~O7CgyF(6fn7hGIfc_Er*JHp8t3j zo>ekZX2~RzmhPgrwl|;L?y*a-TX4YneAP3(FGojBH+eu;>DKz)r>a+W^OzS&qCKov z*hVW>*TkxO+BL1kkuj60qnCXkwPU-Ed=A4V zCdc=G^ODeC(Z|m4ew@m*_A*J70ey-iUCmP$Bd)N+ZJTB@k*6w_kiowz{@4j4hEB_k z5BAM>Gv>}23_Spd_D*cmM0yhw{H&jV7;cPV=uglBjHth#9YtBzI}_=~C@(E}F}r5l z)WxYeH;UCS;$Kx(dqDk=z@R?I+4E!8S!wa^-|{Oa!`~3MdkPe|9?gi@)G_quYVjpj z*i4F3JfAlnE?Y8h*fG}31F9{&^oMHcF>z&**;%M%ewdnjZGE_MjL;(ptmHEpv1EBm zq!jo>fR39KUXZDRl_~=x2!3L8_h|k&r&~OOLqxw-_c01j&gywaZJ}`sYwOXYoZ60< zH9Tzr!YK?z=Y!x}$gUj;X}Qh(4AU-xQ2zvoc!kDT^zwp8_|oWo0FBgc0*<41jXUCN zk?-c4R5^~wU6$Sm4_uLD!NFpI8MDjQbH81=O0HLT>{jVfUyo;0IT~eP`uW?(eHUS2 z;gUVS&W)MUg%Z9QaRU}=SO8xUPooh6FU1L9f`uDtHM#^5Blvddkr#i z&ndrN1~zyG^E#2NxXrr{l*t^}UWd%W$>PKgz@nvrUgZYWm@)4&sZ6l35+@{awQ`6o zIdG2D>EQ>9u}FEX22=?SRZ4<_+!^+89{H*qI%EnFNIxmH zI0SR!G|pb9`7(rRekTlh965+cz8G-|ARsM61s*bX-GAA}fsz~pXoLth5BCH=-AjLP z9+QUyNIe7Dtr=AT;()}JfBA%QC9H>{hN0L+hUHd~Oo@1`x(P@+G$KPj*M+DG#Q(L) z3U9nOBxEj2SyLuSgmLdJ6vg=GZdLi#N_b7Hw(1>K?`o4uG8y;7{Lk~JEYZnJgFG6= z3XHx$OaTdyCK1Aeksz5*E`zrD&X8ES#Hg<>({qzvJ-W+5l$8Y#A|SxlJqrtM$)5kR zn2LbXPAv^*HL*E4%-j2z^;|;P3Nsh~JyGhNesV3G)H0x1~_gA13 zr5`Ki7JdM+@4g3{d5j`ie02u1m=T;|{9%xc$#PeEZ830Tc2ZXs&qY~dcF+Cz=;j#k z)}M>3kFE1TNI5JE|3mGpVMB}Zau(xv2(%y7@-=fKW8-x?h!`Mitg!A^rR*y-GCR<4 zpP5$HY)c6W;@w3MVPKi))eG@w=%x;crSNDq2*Ss50&iZRVS3x_nN? zb~zskF^mBsaXFBg-Uotamlt_$aorns4+=3(WYgiXRZp|6f`FX{hKB@1SX?F#j0nky zvt(Do@WqK=BLiAos0aQE%VEK-xt*_FVO;U;!Ver#}ZEBvgmSQ<+E^DTW^ z%KjbUv8ml4b`1%#j>euGCBQ4pZmSRE--s$f>pCFIo*nGX+Z(ubvj>nN4i=QgJ^k!V z|I_WwWkP0vQh8}OOW{xfD(6uU4Eq83T30ljjnNpAoEF2Ml2cz0HB2nKDmO6~N^jF3 z(!psK#}4f&3wtYU==*T<){oe7R7ltx`o1T528K1NLVaaf+IvkdajKY+ZBPZ&@*J_QH1 zmI_*AoC<%4jOZElq#?ZfT3Srh-W<;T6XVY)ljtw1I3W3xgY1km8`xPfw?>L&3`^Gp zml6lRv~fpg^VxX3ad9fBh^Kvr%iTa;fdQ!z1aY2<>(k-iRvADxk_HSPej`r?u!Gv* z#<3t~3Net>Ej{^ySn!(w7h8Tvys$`IdLz+$`rFFkhi{GKSA@87E1jz;&iOTDGtPg1 z2{~JxcQhdzC+Eh18g{d2Vb+#)5F8uxVROhgjNq>?1<*O9JwUTLX)36QiG|D?pNEDA zsWue)JL8aqtonI*WDqD-fhnmbTONQgyxDIIrJXR^46Mr`Pgqz^s0#*#m&VssBiES_ zflcZJsybLe(JK0BGELP9?`<=RrxMRjeHL!K@X*ig&3XQb(I{+mZg>X#QEZ&12hf3p zAt1XMB-2(YH{=V0Xf=(?A-$3}zy|2^t^~mTs)6etfK89#fkyxgv4y!$z-$G?_3%8$ zX@!kC2AGKLZ;q)2@F2B29N9=@Xjic1Yg2hgU;#Km6jiUz^Pjt<2_?^1m>|lMp1JG? z{S`)NWmu5RJ?krubSk*u&qu+gBmYuA9pQZl^JnL$#KHUAxwY>?#^X9KH|i*n%c+m^92AoAcMRbxT=QO{v0_Sw^?;Mh=E(i7a`%* z>jU$vB$9!4U>D1ii^n9i+&hKX3OGY@V0&*}`N~HnjoHf& zLPwy|#+KzC0oVpI0#3uG=hK1DFqaj*HP)Kwd|b zB@S8mUr`eU{a=w9O=hBTaF!aEg5gJa-&mThJir`~7 z9IosB^T>FFCyC70h0KF&i+78z+J&L7|zM*-z_%m~qpe5*2;8R*-fH z{aJj{)Q}3PJ4WAq#NbCC(=HP4E^w+;KxH+yy6HMr_f^Rf8rRkQ&y1@XnsJfwF!48CM znq73!X9&PP>4C@N7*Zfs1?3*7bfi_n(r0proB_sTJ0JnCe4Yo$5CKH&%i*S}8Krk| zKwm82dFeeBiFZ7P!KX+e0wN0H4p+}PAlp*NatK~oh}uc^n(>-!-BHbTTvj!xxq}~c zvCh0Ga(gF6_58JoFS`R6J(ZTbswdVl5fOC6*C^>MH48VKSVxI)kU;N65%wSLfEuD+ zHgIB@Xal&r;FQ#v10s_dwY)v#rAU1BO1qMqp*Q6>1lgmiJFoE~W5-1jcL4tP0XyMy zl*^*|LSFcZ5>l!6TkyArvxT1E1MHIrg4PqiG93=SzNIaVMOi^o@MBCcg+gFbsa*Wvys#N}jw^t)KH|!XAcv`R0sPP2_)7U1v?{-qI^03qXc0dT0 zqOLrk#&Cn=AtN!8LW0$d`Vv@*0T~@JhSoHKVXxZf#-1>IZ|dnb)9g`}2g25BBv+CSb0=_xjbmxK- z`SMq$jCS14_yu$8@e--mV_zqgS*)Z1^MKX-X{ocn4H$=JErA=6zXs5E@reCSu8gEV()U^mH38jz-OcTPRFv6HYGVcxw&qhh`5 zwDeWYdU5{Ji~K#is2~dAF}LdYkEp#E!|YsAI6wER^y(mrgsDbG9o z0&tplFTgv4j5UEvM0cGkjvCm)aIw}C&~SPMu~vFxi|ev)Z#m3tC2Fr=RD(wjQ8N6e_G&I)Er8|V&q=iqcTwx{xI!mcz*G~?;+?EXY= zKgz6KVjsq+>^_9-L_FIrt4Y%fwWKez(CB8oU-<2C3Zc9`y;)`|z7AnT?Y_u}o`Ny^ zh@1cZbroTt{V4ls_9bv29UJ*K=+JtdP`37&|A!DuHf)Lf@Wev0fIG<7(`!r2)R!{L zFTV&>rAOl^8YwR4Ui(6>V163bLV%!9L%F567+9Y`ZPdX*v$FoVa^8sfj$ddWSM7eF z2CsEr9pCFH2ZA6f5yO$huS&_|ODnf4+RCqa@l!eK%yZf;)qiv~w(5ChyRonldf~uB zOVo7FI`_v$K&ZqO2kPz?V#&?Cn8V}wiJG31jHOp!wB;z=3W>=PPAAQ}OE^JIx}o=t zurQ&#DVA8q*APIW~2Sz_FNCQ5fQFvhslCzSsW% zPE&ZQWEeY0cLJLX-**92d9>m2Vyt^kc5b^;*i@Hmn~C#v+PEZ@^kM7=J-AlO)n0Zok~nO5>&ZvH%$)#* zZYCxs8B(r9E)gfI7&bS3j!wO#)YZ1`_6S2Qr-+V@3-=M}od#b5tJnLAP2#xA6)v(? zRtmqicR%~Eu(n!uuFJi-Xws=kEgH|M(|KRc#jVwHV%(shTHboa3t4NZuFWj8h2lKF zb22@C(ibG$v-UyywU*Jo;Xy8!L`*TAjC1I2hkJ&gd##=CJ#vvYWGMClKvaa+wH8%; z+@K~^oBLW=m{837KqB*66P*092g@lVCyODYD<-#m{K`wCtA1G*gOOb?YtmWUfWJU3CUohHrJ>n_7fB_N@kOo$rXMh3%PPVXpm)K`x6a zi_5q{3|0EP=3jH|?v4;m2tG13Yb!92Xw@=uXDsCKlnV$5s6JpV`G!lSF+&w11to4! z_Lg_$=U&V>JSxi6G(6Ju4%n?ANz@&>;drm8d{18j#88ko05x>?THhTKTSgE8&D<|W<2K+ zfx{(}Pp*J?UjbzO@Z{A2M)3M#9-7o{Oa+li8zry^io~yIiiGYvO=#AjdhJ?|CET$w zJXO-TreGlhoZAbCzn0H!k7hJqM!6DvkfvCofYlG<;SZi~SFIaLGTC!M|AwRb{xqZA z*Cy)O6D12y#d!XHBejKL37Y}LMwX_KhbA?Wdv~ItLPYn6Q|HmOA6tHN#T8SfD?j1AS*P*uA-_H z)>Wc>=C$;URgbpGavzOleSck`FU`w<#VMo8i&d z8;tkjZvY&;9A2-DM0ACpYY~8_e!8Kv(RQPii}}k^#>h?QAKaDSB&fHx^ChgKub;IM z=u03uwVzYJg^1xxHL_QsS70nXK9R0<{t`4GL~p;KZAON8aIKdf>{Ai!v)L1|j}ct_ z{FlcAcj^eKkxu{~KL$bmlxC<5rJxnPT2dSfE-tR!TD|9j{gD7XAz^xXf;e6vO#3!}(NXzGgSKpl1(pPpT=~(dFru5V!`LmNS>r*m_HQM0dx)Aa0P04!U`cJ{4h6959&# z2jDp?qZ*CZU89weBZ~!(O^*Gm7)h=s@aj4g zwFeR}iNkqTQ7&Is!^o&&M=$QCV=0x}m@O~Li=d52X5dSO*Fh&Gg@9F7EowEe--l<@jKfFw>k$ceTe zGFTLI*fUf%yyv@k_#suRyLr$RvKfCh{Gf$vBvhO1qs8k`_Ce@x2kG`w$$zWc6!K7h ziOO_QQQMN6WkoS{-IHFc5qj3uT_OiVH4QS0KD-Wx0~~sfK2smnWI9%X?`OOAEYqoG zMpDVK{KAhxJ%Y@rv3aDmgYiAz;iS0j>OPTu^2v7c=s-OD*)EKunM`Vt3!^%awoVlY ztG@(n>aUWaC=S-<<)`q8hl9auDHD#g#s%Pz=k??gAO_3P;NUw2zya?R9EKEu%Zl$G`aAe>=Y)@*yBM9LkxNm&y5~@F0XeU<=Qb(cuv4P>I+zNezql4J zFK?Pt_sT?3JovIKS1}jIuE70muc6ZWE7YR(DzBKVG7OVlPR3u(_yu3xIc9R>hXZfK~frGFT@t|$03?4{o&&GNWJ zh@3tJa=`OKDbyS5R5+9m9OBR?3#sS_cSpZS9+2%C#Fwh^@7ctY2Q*uLV<YeF(oNf&Mfwr`c5L#MK-nR#qQSXS^Rq6`3cw$#% ziMXp|!0}$(Fo^Q){5XI%Fn|^~{}0FtbSygk&szc*|L^vkqfc6S4SjKwsp{I&xz;@s zK}4W0_{2(DC`3ZzM2{QKQocWLi59{f*l)I`+8F|!Ebk06zy|2qWb z-X>FnBlOCr2=695S8maPZ`;z$OI!`lYc#Dcpy%kEyx+~l>OkH+>Q7D3Lr}vyh#S<5 zu0^M@8CrPEpAPyRAK0w*^=3LVC%gkRDUDtQ$OU4lym+n9a>L1mO|`yd$nGpt{W<8^ zdi+TD4d_-B#lEc9))sjc2*poND1UqK-w`aoNVfl@q%?i{4DB1kwWaI^*dt#USjHN# z=k4oX0O!Vm%E+$)=lP`xPPNwEqGhIsn8327wOf|GkhBU>3Vfjp3Tgc7q(@ zhxy46303o^XW@dL*ay&W07OY8km-9O5VvVgy($(WC4{DMAUgzYw^%*@b^qbFpFBnI z5{IgN6NitjSeQS@G&a%?|2(<{<^glO6I|URh-V6G+-AR}yu?VJcKhZ+rcZw{#4^hU zr2SEanuTx!5vQLtsuq==FVFQ9996(+mm3#{pqoRQ7qWTS6sZ8Q=TnbkU}n4*2G$94yo;QNQCj8$%=D zq+qmFkme6w{;hWE-eM(=aFK?_amy(^>90~pc#b0URw$q4J~A_l9LW?^2cu;)gZf54r64OCwjQb& zMXYRLJyf81{PSTU_y()tqs{L0onj0hS=_sa^LYwF3%$FVa`)tU39o<;e2K{wkHCE> z^CYGHMnkRfq7}10l)unkf?(l6X73~DMLd@3Eiq;=JRx_Su}iOYpj_kGWBcI+Ae0ov zqzoV@fl|onxAlMPzLT7otb`klTk~mO*Mn;m+d%w{jPz>I1Kf;VuY(vplgOxB2lmMV zZOoI~g&CbneJA6?h=;!_7qQ%o$->%|bCt)<;uF*A&gn%(D*Bu;PNT^qd8QsVsD+D& ztXti&6|kP(C6`bZW@hfhh~yZinu3)%AyB-8V`F`yC0s~GDtAEop#?WTlY$pkf5QzgYzALhe- z8SEC(_V7IVK{OH04FH?(8P4C^GZH7!?bw(1`A^vzVJTgerLVZtGYFFQ*;g5zGauI@ z(pDG^m~-9IS)Dvt)Lrp}E`BKvJ6* zlb(*O)r<+vTv{#b|D<@d55B!aZ2PHA?QwwU?v~pA#^>Vc^iGQ9ty#E(wWpl|g~XG9 zWBlGI7qJXOW+TEPZCbd5`Eu7Snb)C|xfNM?$p{RmOW`3g4g`g$KxD-5mYB4-?*byG-(5KTgIOusb3n;_19$RA|ar@bB$J z1Sd*$vyIeg(DTz7hTU?3z$^z4D=b({5k>HaNb^JWB{BF;!@j=T+ zGixdP$Dlm>yzsP}U4RZgl5M7@TlDiHL~6>{nslq&WCQI)G)6j9-?jcRu4S{_j&BrM zG3h-1#cq<~K$H(xv%Kr|3v_xp1trLdlV|v$K__-lW}B)$yk#dK0MsJ4XMYv` z(O1bg-zr-9?X)39Y?jz$s6B#8#cP6T4)@o_)A!jn-0|!3?8zz}z8QP;f-k+F-4pI! zXg|AJC3Ea1$K>HMk!L;|6+`N(%-6xaGi^q}yQaA+P71Y_(!9DlM%)L#Jg|G84D$2GkkdaElk|XI z+$5B>@`$1@TV%v`tBpz2um_3CrTs+48{Xa?=uim%`%p-Y<$mY-u_434)!%$ndOVG+ z@x8ZchQteY46@BBL8_*aW6uU_8fHHQat;W^Xb6!!UwAGx2+wpGtTWh*3Zk?vbb5;o zT2F+E66Ov|8SPs-o27&qvS5;$=8768XiaVWq$6k#n7y`mPqSZGbxxlQ($6^%*1vwi z??d-Zm@xeAd z34@(|=o4?ykBHf-S};3$HmMWp-mS$KJ*jXIS&p~{@kq6ZVwjjl0@4A&Z2hAIXlRkSpbRRytJz#jJ zQn5tq9v2TXmXx&j#UpnpC}X99Vd&Umo4-#)M{n2XsQ5?u@JwoH_q*p1%`%Qa&X8Sk-bHxBK47OV&*wcl zU=kJ7=<80}cmH|J8^^mqbjO%I_QZzSg<}8;jLu-gq{=mlde93T{12365i|HJk*P;@ z@&kUM6lP>6PeGG2Rp5b zgWF-LsW%#Ii5V5cL3Tj29bW_P)U+#cTxdBD<&3@EIy&bT&21JDh^^%Oe7*9|VIup; zvkyrRz3%7?KD-KLOk7aLl%Dy733`Ez$zs4HFByCej&yu8V{_04hToPIBbCgr^o6ma z3tVW-gAeZ?IT2n-M`DG_Vp`_X_nfPx!yhi8PFhC!1$twc64NnFQ}BY)HIyUbxY*&W z+1dMLT3*HS&B2r_`F^V}ZaJ=`YLyx5r2b6Udpt$lJJT2uzr+`|mq5~4aW9$(Cmn+G zThFW2S3X!~O*GCYdCE`dnz$=kj#n*gpvLy5>?#|DxXqeQgkJSTl|Y(&3~~C)Vt0=q z?@GX-r*eR&>GP@vAdaK+c4>%MI!>IVc_8M1s~0c_{t)ZiY&iF~gDy5?KFHUXBJf2H zwQRb2Dkj1*lM_)-NB-(o4IcR-`nrtGKwK{!-ZUC87gjU%K+{C_*XWwD6 z)j!3F0;gbcSiyDtIihxXGm7oer=k1%B_s}l`lqEp7Xb1m9lu^^N}g5~6U^CM$8AYu z-%FT?&|j9=-j{3n-Ue#NG*{mx2$V=5-{hbEC#MDpex#gQ=F&-qzP>&?)TEjd-3`(o zTjyPnSX1&CxZXeDf=G(eGSt;JL!8A8Dg$nLy!)+T-*UB2z)VcUz-xJ2t-C86jMn$H zbM#>v6JMjD)5!T?PPtj5ZEG8zr+*v{9QX4F8JZY1rKkC;ntaLGC7K1=oJ?hpSt)9nuNp46J?vI3%-iCKF~$0Hov<~TZ@aCPrMqM6n7vT%AipDNy%cpaZ&SIE zlhl)KuVriTQE_`y;=$Nsopj&kzLtPnOW5n!P)Jb&O1B+Z=f4VG;ADDletwuPUm=qY z)eaJ|^inz}rwpMP8NRvJGY&|kkHHhtlK%kQE`NX;tq0Zkhk{QA3*Pc(opgG>)batt zIOf6|9hw7059s1@uyxe68N#|P1Ia8Nl$)o|u(7w_(&`jZV z1rf135;le%EECzyH|`4;ya5nSt8yJW3+F#L3-J%Pr8AX>0oLiC^o+c=(}Spm$85Ck z3I9CT+~zv__EyH776sEUVQ&4Y&W3LDZb`KbGl8q@=8GE9bS;WuP~*BgWX^3dvbc)-8kxx6tL{yuy2QGGcYrn}t|dYWePQLH^vGis%Sdbdio7KOnb z_>0j4!zBT#gqVKVH;(Kz>u#SF-v9A%YlLdZ3s!D5@n}RSr2z2+`z93r{BHv>^9(&v zhvwh>8GIVch2&KO71F+C7ShizN$o!}32EpJ6s7`swt|P80e~(H&~NW>zV`P4<_~J{ z42Bm#_1~8XoH5K_s4t5daWS3dvPkjm@?$}H4*ogZ5NxmO@=(G-hyw;@dEWE?eRTs2 zA9_FfzcpxT^shP47o@UQ!%}diI%&KecP`=FIRGtRQm+7D!MO`s=&{8Ff1l2v@4x(F zQvaQSEQR%7oeTJ&T3R&34idceNkHBGh;7L3<|Ew_U`FoeEVb}`;BR-_IN_-+T(|I=( z%218|169B4!NhGzVq~FyE&uh{h+(Or|(VV901BdZ{f7Fmx<_^wYveZ#2YpPI4Ft(@4u}e{tMOVe^9U8FOGjSOf|8> zJ=|>#S(#4>Rsi40fH@gkS2t;?6xJ zPm^A>jm`^8dlVWl85nhTbgYf%aUt8+4Bz#63jTf+`m65vr&l)ICuK@${_-VoRAa2u z)ufZ{Ac~*yP`I_{!k)9{r~Y2Ytf74ghvFii0J>`9RbpLC@#)AEF?1L?4ZWk=u;1 z5h}ue9~uYgjlNOws%8n@W%x_-xxpb*aYP1FVpp1VR1T)9CFfcD8 zXKP!0xII77gJdg8cYOQYLmwV)n}um^3$E7xmKY8#?Z}5TR~1N_V^V+qTtx?MaDx|h zjPs;}r^9;_|RPcCRsl+a<);=@r_O`aImF$ielrif4X4uTEVDY@R zD<7fDM!)q==!cn|oqanLxPIgJ;5!k2+7_%n0Jy$@Bq=%ge0M}p_T(HFD=WOZT6EQB z3%KzT>7OP_=!Ll`WCn-BxBPfDJ2>ZvwhlGx@PhY36hsg9(03qyFY1it-oo$^yoV)p z-CyR#>Yw{DW;EV*PODz><>#KeCmTlB6Vi9*;jD(_vi;31^0?s#|7Oe>3HVt>Ln$v0 zKyTm+Jeu+GG`#do3q!PinB*T;0HdA5R@X*(3v#mH*#R7&pR>WH{Jj|ft&nepMry5x zoonv%)wqxsutOO;GjjzDJ6>2LyRcbNQ{9Fj_|vdZ*Hu6Tx05@J~)k>286f@r(ZjePw<~ literal 0 HcmV?d00001 diff --git a/docs/features/traffic-management/istio.md b/docs/features/traffic-management/istio.md index 2dc4c8a3dd..f980b423ac 100644 --- a/docs/features/traffic-management/istio.md +++ b/docs/features/traffic-management/istio.md @@ -1,17 +1,37 @@ # Istio -[Istio](https://istio.io/) is one of the most popular service mesh in the community and offers a rich feature-set to control the flow of traffic. Istio offers this functionality through a set of CRDs, and the Argo Rollouts controller modifies these resources to manipulate the traffic routing into the desired state. However, the Argo Rollouts controller modifies the Istio resources minimally to gives the developer flexibility while configuring their resources. +[Istio](https://istio.io/) is a service mesh that offers a rich feature-set to control the flow of +traffic to a web service. Istio offers this functionality through a set of CRDs, and Argo Rollouts +automates the management of these resources to provide advanced traffic shaping capabilities to the +different versions of the Rollout during an update. -## Istio and Rollouts +## How it works -The Argo Rollout controller achieves traffic shaping by manipulating the Virtual Service. A Virtual Service provides the flexibility to define how to route traffic when a host address is hit. The Argo Rollouts controller manipulates the Virtual Service by using the following Rollout configuration: +Traffic splitting is accomplished in Istio by adjusting traffic weights defined in an +[Istio VirtualService](https://istio.io/latest/docs/reference/config/networking/virtual-service/). +When using Argo Rollouts with Istio, a user deploys a VirtualService containing at least one +[HTTP route](https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRoute) containing two +[HTTP route destinations](https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRouteDestination): +a route destination targeting the pods of canary ReplicaSet, and a route destination targeting the pods +stable ReplicaSet. Istio provides two approaches for weighted traffic splitting, both approaches +are available as options in Argo Rollouts: -- Canary Service name -- Stable Service name -- Virtual Service Name -- Which HTTP Routes in the Virtual Service +1. [Host-level traffic splitting](#host-level-traffic-splitting) +2. [Subset-lvel traffic splitting](#subset-level-traffic-splitting) -Below is an example of a Rollout with all the required fields configured: +## Host-level Traffic Splitting + +The first approach to traffic splitting using Argo Rollouts and Istio, is splitting between two +hostnames, or Kubernetes Services: a canary Service and a stable Service. This approach is +similar to the way all other Argo Rollouts mesh/ingress-controller integrations work (e.g. ALB, SMI, +Nginx). Using this approach, the user is required to deploy the following resources: + +* Rollout +* Service (canary) +* Service (stable) +* VirtualService + +The Rollout should define the following fields: ```yaml apiVersion: argoproj.io/v1alpha1 @@ -22,22 +42,158 @@ spec: ... strategy: canary: + canaryService: canary-svc # required + stableService: stable-svc # required + trafficRouting: + istio: + virtualService: + name: rollout-vsvc # required + routes: + - primary # required steps: - setWeight: 5 - pause: duration: 10m - canaryService: canary-svc # required - stableService: stable-svc # required +``` + +The VirtualService must contain an HTTP route with a name referenced in the Rollout, containing +two route destinations with `host` values that match the `canaryService` and `stableService` +referenced in the Rollout. Note that Istio require that all weights add to 100, so the initial +weights can be be 100% to stable, and 0% to canary. + +```yaml +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: rollout-vsvc +spec: + gateways: + - istio-rollout-gateway + hosts: + - istio-rollout.dev.argoproj.io + http: + - name: primary # referenced in canary.trafficRouting.istio.virtualService.routes + route: + - destination: + host: stable-svc # referenced in canary.stableService + weight: 100 + - destination: + host: canary-svc # referenced in canary.canaryService + weight: 0 +``` + +Finally, a canary and stable Service should be deployed. The selector of these Services will be +modified by the Rollout during an update to target the canary and stable ReplicaSet pods. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: canary-svc +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: rollouts-demo + # This selector will be updated with the pod-template-hash of the canary ReplicaSet. e.g.: + # rollouts-pod-template-hash: 7bf84f9696 +--- +apiVersion: v1 +kind: Service +metadata: + name: stable-svc +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: rollouts-demo + # This selector will be updated with the pod-template-hash of the stable ReplicaSet. e.g.: + # rollouts-pod-template-hash: 123746c88d +``` + +During the lifecycle of a Rollout update, Argo Rollouts will continuously: +* modify the canary Service `spec.selector` to contain the `rollouts-pod-template-hash` label of the canary ReplicaSet +* modify the stable Service `spec.selector` to contain the `rollouts-pod-template-hash` label of the stable ReplicaSet +* modify the VirtualService `spec.http[].route[].weight` to match the current desired canary weight + +!!! note + + Rollout does not make any other assumptions about the fields within the Virtual Service or the Istio mesh. The user could specify additional configurations for the virtual service like URI rewrite rules on the primary route or any other route if desired. The user can also create specific destination rules for each of the services. + + +## Subset-level Traffic Splitting + +!!! important + + Available since v1.0 + +The second approach to traffic splitting using Argo Rollouts and Istio, is splitting between two +Istio [DestinationRule Subsets](https://istio.io/latest/docs/reference/config/networking/destination-rule/#Subset): +a canary subset and a stable subset. When splitting by DestinationRule subsets, the user is +required to deploy the following resources: + +* Rollout +* Service +* VirtualService +* DestinationRule + +The Rollout should define the following fields: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: rollout-example +spec: + ... + strategy: + canary: trafficRouting: istio: - virtualService: - name: rollout-vsvc # required + virtualService: + name: rollout-vsvc # required routes: - - primary # At least one route is required + - primary # required + destinationRule: + name: rollout-destrule # required + canarySubsetName: canary # required + stableSubsetName: stable # required + steps: + - setWeight: 5 + - pause: + duration: 10m ``` +A single service should be defined, which target the Rollout pods. Note that unlike the first +approach, where traffic splitting is against multiple Services which are modified to contain the +rollout-pod-template-hash of the canary/stable ReplicaSets, this Service is not modified by +the rollout controller. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: rollout-example +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: rollout-example +``` -The controller looks for both the canary and stable service listed as destination hosts within the HTTP routes of the specified Virtual Service and modifies the weights of the destinations as desired. The above Rollout expects that there is a virtual service named `rollout-vsvc` with an HTTP route named `primary`. That route should have exactly two destinations: `canary-service` and `stable-svc` Services. The `canary-svc` and `stable-svc` are required because they indicate to Istio which Pods are the Stable and Canary pods. Here is a Virtual Service that works with the Rollout specified above: +The VirtualService must contain an HTTP route with a name referenced in the Rollout, containing +two route destinations with `subset` values that match the `canarySubsetName` and `stableSubsetName` +referenced in the Rollout. Note that Istio require that all weights add to 100, so the initial +weights can be be 100% to stable, and 0% to canary. ```yaml apiVersion: networking.istio.io/v1alpha3 @@ -46,39 +202,159 @@ metadata: name: rollout-vsvc spec: gateways: - - istio-rollout-gateway + - istio-rollout-gateway hosts: - - istio-rollout.dev.argoproj.io + - istio-rollout.dev.argoproj.io http: - - name: primary - route: - - destination: - host: stable-svc - weight: 100 - - destination: - host: canary-svc - weight: 0 + - name: primary # referenced in canary.trafficRouting.istio.virtualService.routes + route: + - destination: + host: rollout-example + subset: stable # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName + weight: 100 + - destination: + host: rollout-example + subset: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName + weight: 0 +``` + +Finally, the DestinationRule containing the canary and stable subsets referenced in the Rollout. + +```yaml +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: rollout-destrule +spec: + host: rollout-example + subsets: + - name: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName + labels: # labels will be injected with canary rollouts-pod-template-hash value + app: rollout-example + - name: stable # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName + labels: # labels will be injected with canary rollouts-pod-template-hash value + app: rollout-example ``` -When the above Rollout progresses through its steps, the controller changes Virtual Service's `stable-svc`'s weight to 95 and `canary-svc`'s to 5, wait 5 minutes, and then scales up the canary ReplicaSet to a full replica count. Once it is entirely healthy, the controller changes `stable-svc`'s selector to point at the canary ReplicaSet and switch the weight back to 100 to `stable-svc` and 0 to `canary-svc`. +During the lifecycle of a Rollout using Istio DestinationRule, Argo Rollouts will continuously: +* modify the VirtualService `spec.http[].route[].weight` to match the current desired canary weight +* modify the DestinationRule `spec.subsets[].labels` to contain the `rollouts-pod-template-hash` + label of the canary and stable ReplicaSets -!!! note - The Rollout does not make any other assumptions about the fields within the Virtual Service or the Istio mesh. The user could specify additional configurations for the virtual service like URI rewrite rules on the primary route or any other route if desired. The user can also create specific destination rules for each of the services. +## Comparison Between Approaches + +There are some advantages and disadvantages of host-level traffic splitting vs. subset-level traffic +splitting. + +### DNS requirements + +With host-level splitting, the VirtualService requires different `host` values to split among the +two destinations. However, using two host values implies that there are different DNS names. For +north-south traffic, which reach the service through the Istio Gateway, having multiple DNS names to +reach the canary vs. stable pods may not matter. However, for east-west traffic that happen inside +the cluster, it forces microservice-to-microservice communication to choose whether to hit the +stable or the canary DNS name, go through the gateway, or add DNS entries for the virtualservices. +In this situation, the DestinationRule subset traffic splitting would be a better option for +intra-cluster canarying. + +### Metrics + +Depending on the choice of host-level splitting vs. subset-level splitting, there will be different +styles of prometheus metrics available. For example, if using host-level splitting, the metrics of +the canary vs. stable would appear in the Istio Service metrics dashboard: + +![Istio Service Metrics](istio-service-metrics.png) + +On the other hand, when splitting via subsets, it would be necessary to query prometheus using +different parameters, such as the workload name: + +![Istio Workload Metrics](istio-workload-metrics.png) ## Integrating with GitOps -The above strategy introduces a problem for users practicing GitOps. The Rollout requires the user-defined Virtual Service to define an HTTP route with both destinations hosts. However, Istio requires routes with multiple destinations to assign a weight to each destination. Since the Argo Rollout controller modifies these Virtual Service's weights as a Rollout progresses through its steps, the Virtual Service becomes out of sync with the Git version. -Additionally, if a GitOps tool does an apply after the Argo Rollouts controller changes the Virtual Service's weight, the apply would revert the weight to the percentage stored in the Git repo. At best, the user can specify the desired weight of 100% to the stable service and 0% to the canary service. In this case, the Virtual Service is synced with the Git repo when the Rollout completed all the steps. -Argo CD has an [open issue here](https://github.com/argoproj/argo-cd/issues/2913) to address this problem. The proposed solution is to introduce an annotation to the VirtualService which tells Argo CD controller to respect the current weights listed and let the Argo Rollouts controller manage them instead. +Earlier it was explained that VirtualServices should be deployed with an initial canary and stable +weight of 0 and 100, respectively, such as in the following example: + +```yaml + http: + - name: primary + route: + - destination: + host: stable-svc + weight: 100 + - destination: + host: canary-svc + weight: 0 +``` + +This introduces a problem for users practicing GitOps. Since a Rollout will modify these +VirtualService weights as the Rollout progresses through its steps, it unfortunately causes the +VirtualService to become OutOfSync with the version in git. Additionally, if the VirtualService in +git were to be applied while the Rollout is in this state (splitting traffic between the services), +the apply would revert the weights back to the values in git (i.e. 100 to stable, 0 to canary). + +One protection which is implemented in Argo Rollouts, is that it continually watches for changes to +managed VirtualServices. In the event that a `kubectl apply` were to happen using the VirtualService +in git, the change would be detected immediately by the rollout controller, and the controller will +instantly set the VirtualService weights back to the canary weight appropriate for the given step of +the Rollout. But since there is momentary flapping of weights, this behavior should be understood. + +Some best practices to follow when using Argo CD with Argo Rollouts to prevent this behavior, is to +leverage the following Argo CD features: + +1. Configure the application to ignore differences in the VirtualService. e.g.: + + ```yaml + apiVersion: argoproj.io/v1alpha1 + kind: Application + metadata: + name: guestbook + spec: + ignoreDifferences: + - group: networking.istio.io + kind: VirtualService + jsonPointers: + - /spec/http/0 + ``` + + Ignoring the differences in the VirtualServices HTTP route, prevents gitops differences + in the VirtualService HTTP routes to contribute to the overall sync status of the Argo CD + application. This adds the additional benefit of prevent auto-sync operations from being + triggered. + +2. Configure the Application to only apply OutOfSync resources: + + ```yaml + apiVersion: argoproj.io/v1alpha1 + kind: Application + metadata: + name: guestbook + spec: + syncPolicy: + syncOptions: + - ApplyOutOfSyncOnly=true + ``` + + By default, when Argo CD syncs an application, it runs `kubectl apply` against all resources in + git which are part of the application. The `ApplyOutOfSyncOnly=true` sync option indicates to + Argo CD to skip applying resources which it already considers `Synced`, and only apply the ones + which are `OutOfSync`. This option, when used in conjunction with the `ignoreDifferences` + feature, provides a way to manage the conflict in the desired state of a VirtualService between + Argo CD and Argo Rollouts. + +Argo CD also has an [open issue here](https://github.com/argoproj/argo-cd/issues/2913) which would +help address this problem. The proposed solution is to introduce an annotation to resources, which +indicates to Argo CD to respect and preserve the differences at a specified path, in order to allow +other controllers (e.g. Argo Rollouts) controller manage them instead. ## Alternatives Considered ### Rollout ownership over the Virtual Service -Instead of the controller modifying a reference to a Virtual Service, the Rollout controller would create, manage, and own a Virtual Service. While this approach is GitOps friendly, it introduces other issues: +An early design alternative was that instead of the controller modifying a referenced VirtualService, the Rollout controller would create, manage, and own a Virtual Service. While this approach is GitOps friendly, it introduces other issues: -* To provide the same flexibility as referencing Virtual Service within a Rollout, the Rollout needs to inline a large portion of the Istio spec. However, networking is outside the responsibility of the Rollout and makes the Rollout spec unnecessary complicated. +* To provide the same flexibility as referencing VirtualService within a Rollout, the Rollout needs to inline a large portion of the Istio spec. However, networking is outside the responsibility of the Rollout and makes the Rollout spec unnecessary complicated. * If Istio introduces a feature, that feature will not be available in Argo Rollouts until implemented within Argo Rollouts. Both of these issues adds more complexity to the users and Argo Rollouts developers compared to referencing a Virtual Service. diff --git a/docs/getting-started/setup/index.md b/docs/getting-started/setup/index.md index 89c58c4a54..8066de72a1 100644 --- a/docs/getting-started/setup/index.md +++ b/docs/getting-started/setup/index.md @@ -74,7 +74,7 @@ minikube service grafana -n istio-system In order for traffic to enter the Istio mesh, the request needs to go through an Istio ingress gateway, which is simply a normal Kubernetes Deployment and Service. One convenient way to reach -the gateway using minikube, is using the `minikube tunnel` command which assigns Services a +the gateway using minikube, is using the `minikube tunnel` command, which assigns Services a LoadBalancer. This command should be run in the background, usually in a separate terminal window: ```shell diff --git a/docs/roadmap.md b/docs/roadmap.md index 6a1399f997..7e12bbdd80 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -5,11 +5,42 @@ may fall into releases, visit the [github milestones](https://github.com/argopro and notice if the item appears in the milestone description. - [Roadmap](#roadmap) + - [Weight Verification](#weight-verification) + - [Istio Canary using DestinationRule subsets](#istio-canary-using-destinationrule-subsets) - [Webhook Notifications](#webhook-notifications) - [Rollback Window](#rollback-window) - [Header Based Routing](#header-based-routing) - [Shadow Traffic](#shadow-traffic) +# v1.0 + +## Weight Verification + +[Issue #701](https://github.com/argoproj/argo-rollouts/issues/701) + +When Argo Rollouts adjusts a canary weight, it currently assumes that the adjustment was made and +moves on to the next step. However, for some traffic routing providers, this change can take a long +time to take effect (or possibly never even made) since external factors may cause the change to +become delayed. + +This proposal is to add verification to the traffic routers so that after a setWeight step, the +rollout controller could verify that the weight took effect before moving on to the next step. This +is especially important for the ALB ingress controller which are affected by things like rate +limiting, the ALB ingress controller not running, etc... + + +## Istio Canary using DestinationRule subsets + +[Issue #617](https://github.com/argoproj/argo-rollouts/issues/617) + +Currently, Rollouts supports only host-level traffic splitting using two Kubernetes Services. +For some use cases (e.g. east-west canarying intra-cluster), this pattern not desirable and traffic +splitting should be achieved using two +Istio [DestinationRule Subsets](https://istio.io/latest/docs/reference/config/networking/destination-rule/#Subset) +instead. + + +# v1.1+ ## Webhook Notifications @@ -19,7 +50,52 @@ When a rollout transitions state, such as an aborted rollout due to failed analy A webhook notification feature of Rollouts would allow a push-based model where the Rollout controller itself would push an event to an external system, in the form of a webhook/cloud event. -## Rollback Window + +## Workload Referencing + +[Issue #676](https://github.com/argoproj/argo-rollouts/issues/676) + +Currently, the Rollout spec contains both the deployment strategy (e.g. blueGreen/canary), +as well as the pod template. This proposal is to support a way to reference the pod template +definition from another group/kind (e.g. a Deployment, PodTemplate) so that the rollout strategy +could be separated from the workload definition. This is motivated by the following use cases: + +* CRDs (e.g. Rollouts) are not supported well in kustomize, and strategic merge patches simply + don't work as expected with a Rollout because lists will be replaced and not merged. By + referencing a native Kubernetes kind, kustomize would work expectedly against the k8s native + referenced object, which is the portion of the spec that users typically want to customize + overlays against. +* During a migration from a Deployment to a Rollout, it has been inconvenient for users to duplicate + the entire Deployment spec to a Rollout, and keeping them always in sync during the transition. + By referencing the definition, we would be able to eliminate the possibility of pod template spec + duplication. + + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: guestbook-canary +spec: + replicas: 5 + workloadRef: + kind: Deployment + name: guestbook + strategy: + canary: + steps: + - setWeight: 20 + - pause: {duration: 1h} + - setWeight: 40 + - pause: {duration: 1h} + - setWeight: 60 + - pause: {duration: 1h} + - setWeight: 80 + - pause: {duration: 1h} +``` + + +## Rollback Windows [Issue #574](https://github.com/argoproj/argo-rollouts/issues/574) diff --git a/go.mod b/go.mod index 9a6c306097..8f13a79cdd 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.0.0 github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.0.0 github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect + github.com/evanphx/json-patch/v5 v5.2.0 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-openapi/spec v0.19.3 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect @@ -23,6 +24,7 @@ require ( github.com/spaceapegames/go-wavefront v1.8.1 github.com/spf13/cobra v1.1.1 github.com/stretchr/testify v1.6.1 + github.com/tj/assert v0.0.3 github.com/undefinedlabs/go-mpatch v1.0.6 github.com/valyala/fasttemplate v1.2.1 github.com/vektra/mockery v1.1.2 diff --git a/go.sum b/go.sum index e9d72fa01e..a5dc7d6f9b 100644 --- a/go.sum +++ b/go.sum @@ -315,6 +315,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.2.0 h1:8ozOH5xxoMYDt5/u+yMTsVXydVCbTORFnOOoq2lumco= +github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= @@ -1680,6 +1682,7 @@ k8s.io/code-generator v0.19.4 h1:c8IL7RgTgJaYgr2bYMgjN0WikHnohbBhEgajfIkuP5I= k8s.io/code-generator v0.19.4/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/component-base v0.19.4 h1:HobPRToQ8KJ9ubRju6PUAk9I5V1GNMJZ4PyWbiWA0uI= k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70= +k8s.io/cri-api v0.19.4 h1:Vc00x5LSSbLBgvj7UAi4kjsv276n4SGX0XlI/pWhG2E= k8s.io/cri-api v0.19.4/go.mod h1:UN/iU9Ua0iYdDREBXNE9vqCJ7MIh/FW3VIL0d8pw7Fw= k8s.io/csi-translation-lib v0.19.4/go.mod h1:Zqw8qVIHp6OU65hvIYeOlkMwHLpKy72h3P15AkY90W0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= diff --git a/manifests/crds/rollout-crd.yaml b/manifests/crds/rollout-crd.yaml index 83fe6956d8..62d9a13126 100644 --- a/manifests/crds/rollout-crd.yaml +++ b/manifests/crds/rollout-crd.yaml @@ -504,6 +504,19 @@ spec: type: object istio: properties: + destinationRule: + properties: + canarySubsetName: + type: string + name: + type: string + stableSubsetName: + type: string + required: + - canarySubsetName + - name + - stableSubsetName + type: object virtualService: properties: name: diff --git a/manifests/install.yaml b/manifests/install.yaml index 56b160884e..b222d4b8ad 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -12038,6 +12038,19 @@ spec: type: object istio: properties: + destinationRule: + properties: + canarySubsetName: + type: string + name: + type: string + stableSubsetName: + type: string + required: + - canarySubsetName + - name + - stableSubsetName + type: object virtualService: properties: name: @@ -15037,10 +15050,12 @@ rules: - networking.istio.io resources: - virtualservices + - destinationrules verbs: - watch - get - update + - patch - list - apiGroups: - split.smi-spec.io diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml index 84139106f7..552d331b57 100644 --- a/manifests/namespace-install.yaml +++ b/manifests/namespace-install.yaml @@ -12038,6 +12038,19 @@ spec: type: object istio: properties: + destinationRule: + properties: + canarySubsetName: + type: string + name: + type: string + stableSubsetName: + type: string + required: + - canarySubsetName + - name + - stableSubsetName + type: object virtualService: properties: name: @@ -14953,10 +14966,12 @@ rules: - networking.istio.io resources: - virtualservices + - destinationrules verbs: - watch - get - update + - patch - list - apiGroups: - split.smi-spec.io diff --git a/manifests/role/argo-rollouts-clusterrole.yaml b/manifests/role/argo-rollouts-clusterrole.yaml index 952b703005..a3a77e65a4 100644 --- a/manifests/role/argo-rollouts-clusterrole.yaml +++ b/manifests/role/argo-rollouts-clusterrole.yaml @@ -124,15 +124,17 @@ rules: - update - patch - delete -# virtualservice access needed for using the Istio provider +# virtualservice/destinationrule access needed for using the Istio provider - apiGroups: - networking.istio.io resources: - virtualservices + - destinationrules verbs: - watch - get - update + - patch - list # trafficsplit access needed for using the SMI provider - apiGroups: diff --git a/metricproviders/datadog/datadog.go b/metricproviders/datadog/datadog.go index 607c061600..b1d40871b2 100644 --- a/metricproviders/datadog/datadog.go +++ b/metricproviders/datadog/datadog.go @@ -8,12 +8,11 @@ import ( "io/ioutil" "net/http" "net/url" - "os" "strconv" - "strings" "time" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/defaults" "github.com/argoproj/argo-rollouts/utils/evaluate" metricutil "github.com/argoproj/argo-rollouts/utils/metric" log "github.com/sirupsen/logrus" @@ -167,7 +166,7 @@ func (p *Provider) GarbageCollect(run *v1alpha1.AnalysisRun, metric v1alpha1.Met } func NewDatadogProvider(logCtx log.Entry, kubeclientset kubernetes.Interface) (*Provider, error) { - ns := Namespace() + ns := defaults.Namespace() secret, err := kubeclientset.CoreV1().Secrets(ns).Get(context.TODO(), DatadogTokensSecretName, metav1.GetOptions{}) if err != nil { return nil, err @@ -194,18 +193,3 @@ func NewDatadogProvider(logCtx log.Entry, kubeclientset kubernetes.Interface) (* } } - -func Namespace() string { - // This way assumes you've set the POD_NAMESPACE environment variable using the downward API. - // This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up - if ns, ok := os.LookupEnv("POD_NAMESPACE"); ok { - return ns - } - // Fall back to the namespace associated with the service account token, if available - if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { - if ns := strings.TrimSpace(string(data)); len(ns) > 0 { - return ns - } - } - return "argo-rollouts" -} diff --git a/metricproviders/newrelic/newrelic.go b/metricproviders/newrelic/newrelic.go index ad705fd417..0c8bcb31bf 100644 --- a/metricproviders/newrelic/newrelic.go +++ b/metricproviders/newrelic/newrelic.go @@ -5,10 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" - "os" "strconv" - "strings" "github.com/newrelic/newrelic-client-go/newrelic" "github.com/newrelic/newrelic-client-go/pkg/nrdb" @@ -17,6 +14,7 @@ import ( "k8s.io/client-go/kubernetes" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/defaults" "github.com/argoproj/argo-rollouts/utils/evaluate" metricutil "github.com/argoproj/argo-rollouts/utils/metric" "github.com/argoproj/argo-rollouts/utils/version" @@ -142,7 +140,7 @@ func NewNewRelicProvider(api NewRelicClientAPI, logCtx log.Entry) *Provider { //NewNewRelicAPIClient creates a new NewRelic API client from metric configuration func NewNewRelicAPIClient(metric v1alpha1.Metric, kubeclientset kubernetes.Interface) (NewRelicClientAPI, error) { - ns := Namespace() + ns := defaults.Namespace() profileSecret := DefaultNewRelicProfileSecretName if metric.Provider.NewRelic.Profile != "" { profileSecret = metric.Provider.NewRelic.Profile @@ -173,18 +171,3 @@ func NewNewRelicAPIClient(metric v1alpha1.Metric, kubeclientset kubernetes.Inter return nil, errors.New("account ID or personal API key not found") } } - -func Namespace() string { - // This way assumes you've set the POD_NAMESPACE environment variable using the downward API. - // This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up - if ns, ok := os.LookupEnv("POD_NAMESPACE"); ok { - return ns - } - // Fall back to the namespace associated with the service account token, if available - if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { - if ns := strings.TrimSpace(string(data)); len(ns) > 0 { - return ns - } - } - return "argo-rollouts" -} diff --git a/metricproviders/wavefront/wavefront.go b/metricproviders/wavefront/wavefront.go index e2c5e4e5d6..01dab18e06 100644 --- a/metricproviders/wavefront/wavefront.go +++ b/metricproviders/wavefront/wavefront.go @@ -4,11 +4,8 @@ import ( "context" "errors" "fmt" - "io/ioutil" "math" - "os" "strconv" - "strings" log "github.com/sirupsen/logrus" wavefrontapi "github.com/spaceapegames/go-wavefront" @@ -16,6 +13,7 @@ import ( "k8s.io/client-go/kubernetes" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/defaults" "github.com/argoproj/argo-rollouts/utils/evaluate" metricutil "github.com/argoproj/argo-rollouts/utils/metric" ) @@ -196,7 +194,7 @@ func NewWavefrontProvider(api WavefrontClientAPI, logCtx log.Entry) *Provider { // NewWavefrontAPI generates a Wavefront API client from the metric configuration func NewWavefrontAPI(metric v1alpha1.Metric, kubeclientset kubernetes.Interface) (WavefrontClientAPI, error) { - ns := Namespace() + ns := defaults.Namespace() secret, err := kubeclientset.CoreV1().Secrets(ns).Get(context.TODO(), WavefrontTokensSecretName, metav1.GetOptions{}) if err != nil { return nil, err @@ -216,18 +214,3 @@ func NewWavefrontAPI(metric v1alpha1.Metric, kubeclientset kubernetes.Interface) return nil, errors.New("API token not found") } } - -func Namespace() string { - // This way assumes you've set the POD_NAMESPACE environment variable using the downward API. - // This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up - if ns, ok := os.LookupEnv("POD_NAMESPACE"); ok { - return ns - } - // Fall back to the namespace associated with the service account token, if available - if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { - if ns := strings.TrimSpace(string(data)); len(ns) > 0 { - return ns - } - } - return "argo-rollouts" -} diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index 5cc5a0c258..57044c80b3 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -57,6 +57,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.ExperimentSpec": schema_pkg_apis_rollouts_v1alpha1_ExperimentSpec(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.ExperimentStatus": schema_pkg_apis_rollouts_v1alpha1_ExperimentStatus(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.FieldRef": schema_pkg_apis_rollouts_v1alpha1_FieldRef(ref), + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioDestinationRule": schema_pkg_apis_rollouts_v1alpha1_IstioDestinationRule(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioTrafficRouting": schema_pkg_apis_rollouts_v1alpha1_IstioTrafficRouting(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioVirtualService": schema_pkg_apis_rollouts_v1alpha1_IstioVirtualService(ref), "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.JobMetric": schema_pkg_apis_rollouts_v1alpha1_JobMetric(ref), @@ -767,12 +768,24 @@ func schema_pkg_apis_rollouts_v1alpha1_BlueGreenStrategy(ref common.ReferenceCal Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis"), }, }, + "previewMetadata": { + SchemaProps: spec.SchemaProps{ + Description: "PreviewMetadata specify labels and annotations which will be attached to the preview pods for the duration which they act as a preview pod, and will be removed after", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PodTemplateMetadata"), + }, + }, + "activeMetadata": { + SchemaProps: spec.SchemaProps{ + Description: "ActiveMetadata specify labels and annotations which will be attached to the active pods for the duration which they act as a active pod, and will be removed after", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PodTemplateMetadata"), + }, + }, }, Required: []string{"activeService"}, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.AntiAffinity", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis", "k8s.io/apimachinery/pkg/util/intstr.IntOrString"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.AntiAffinity", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.PodTemplateMetadata", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.RolloutAnalysis", "k8s.io/apimachinery/pkg/util/intstr.IntOrString"}, } } @@ -912,13 +925,13 @@ func schema_pkg_apis_rollouts_v1alpha1_CanaryStrategy(ref common.ReferenceCallba }, "maxUnavailable": { SchemaProps: spec.SchemaProps{ - Description: "MaxUnavailable The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total pods at the start of update (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. By default, a fixed value of 1 is used. Example: when this is set to 30%, the old RC can be scaled down by 30% immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that at least 70% of original number of pods are available at all times during the update.", + Description: "MaxUnavailable The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of total pods at the start of update (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. By default, a fixed value of 25% is used. Example: when this is set to 30%, the old RC can be scaled down by 30% immediately when the rolling update starts. Once new pods are ready, old RC can be scaled down further, followed by scaling up the new RC, ensuring that at least 70% of original number of pods are available at all times during the update.", Ref: ref("k8s.io/apimachinery/pkg/util/intstr.IntOrString"), }, }, "maxSurge": { SchemaProps: spec.SchemaProps{ - Description: "MaxSurge The maximum number of pods that can be scheduled above the original number of pods. Value can be an absolute number (ex: 5) or a percentage of total pods at the start of the update (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. By default, a value of 1 is used. Example: when this is set to 30%, the new RC can be scaled up by 30% immediately when the rolling update starts. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of original pods.", + Description: "MaxSurge The maximum number of pods that can be scheduled above the original number of pods. Value can be an absolute number (ex: 5) or a percentage of total pods at the start of the update (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. By default, a value of 25% is used. Example: when this is set to 30%, the new RC can be scaled up by 30% immediately when the rolling update starts. Once old pods have been killed, new RC can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of original pods.", Ref: ref("k8s.io/apimachinery/pkg/util/intstr.IntOrString"), }, }, @@ -1486,6 +1499,41 @@ func schema_pkg_apis_rollouts_v1alpha1_FieldRef(ref common.ReferenceCallback) co } } +func schema_pkg_apis_rollouts_v1alpha1_IstioDestinationRule(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "IstioDestinationRule is a reference to an Istio DestinationRule to modify and shape traffic", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name holds the name of the DestinationRule", + Type: []string{"string"}, + Format: "", + }, + }, + "canarySubsetName": { + SchemaProps: spec.SchemaProps{ + Description: "CanarySubsetName is the subset name to modify labels with canary ReplicaSet pod template hash value", + Type: []string{"string"}, + Format: "", + }, + }, + "stableSubsetName": { + SchemaProps: spec.SchemaProps{ + Description: "StableSubsetName is the subset name to modify labels with stable ReplicaSet pod template hash value", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "canarySubsetName", "stableSubsetName"}, + }, + }, + } +} + func schema_pkg_apis_rollouts_v1alpha1_IstioTrafficRouting(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1495,16 +1543,22 @@ func schema_pkg_apis_rollouts_v1alpha1_IstioTrafficRouting(ref common.ReferenceC Properties: map[string]spec.Schema{ "virtualService": { SchemaProps: spec.SchemaProps{ - Description: "VirtualService reference to a Virtual Service that modified to shape traffic", + Description: "VirtualService references an Istio VirtualService to modify to shape traffic", Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioVirtualService"), }, }, + "destinationRule": { + SchemaProps: spec.SchemaProps{ + Description: "DestinationRule references an Istio DestinationRule to modify to shape traffic", + Ref: ref("github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioDestinationRule"), + }, + }, }, Required: []string{"virtualService"}, }, }, Dependencies: []string{ - "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioVirtualService"}, + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioDestinationRule", "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1.IstioVirtualService"}, } } diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index ea86e7cf30..686abcb345 100644 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -264,8 +264,10 @@ type NginxTrafficRouting struct { // IstioTrafficRouting configuration for Istio service mesh to enable fine grain configuration type IstioTrafficRouting struct { - // VirtualService reference to a Virtual Service that modified to shape traffic + // VirtualService references an Istio VirtualService to modify to shape traffic VirtualService IstioVirtualService `json:"virtualService"` + // DestinationRule references an Istio DestinationRule to modify to shape traffic + DestinationRule *IstioDestinationRule `json:"destinationRule,omitempty"` } // IstioVirtualService holds information on the virtual service the rollout needs to modify @@ -276,6 +278,16 @@ type IstioVirtualService struct { Routes []string `json:"routes"` } +// IstioDestinationRule is a reference to an Istio DestinationRule to modify and shape traffic +type IstioDestinationRule struct { + // Name holds the name of the DestinationRule + Name string `json:"name"` + // CanarySubsetName is the subset name to modify labels with canary ReplicaSet pod template hash value + CanarySubsetName string `json:"canarySubsetName"` + // StableSubsetName is the subset name to modify labels with stable ReplicaSet pod template hash value + StableSubsetName string `json:"stableSubsetName"` +} + // RolloutExperimentStep defines a template that is used to create a experiment for a step type RolloutExperimentStep struct { // Templates what templates that should be added to the experiment. Should be non-nil diff --git a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go index 333aa29bf4..3c97992407 100644 --- a/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go @@ -859,10 +859,31 @@ func (in *FieldRef) DeepCopy() *FieldRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstioDestinationRule) DeepCopyInto(out *IstioDestinationRule) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstioDestinationRule. +func (in *IstioDestinationRule) DeepCopy() *IstioDestinationRule { + if in == nil { + return nil + } + out := new(IstioDestinationRule) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IstioTrafficRouting) DeepCopyInto(out *IstioTrafficRouting) { *out = *in in.VirtualService.DeepCopyInto(&out.VirtualService) + if in.DestinationRule != nil { + in, out := &in.DestinationRule, &out.DestinationRule + *out = new(IstioDestinationRule) + **out = **in + } return } diff --git a/pkg/apis/rollouts/validation/validation.go b/pkg/apis/rollouts/validation/validation.go index d4265a7800..846eeddecb 100644 --- a/pkg/apis/rollouts/validation/validation.go +++ b/pkg/apis/rollouts/validation/validation.go @@ -174,6 +174,16 @@ func ValidateRolloutStrategyBlueGreen(rollout *v1alpha1.Rollout, fldPath *field. return allErrs } +// requireCanaryStableServices returns true if the rollout requires canary.stableService and +// canary.canaryService to be defined +func requireCanaryStableServices(rollout *v1alpha1.Rollout) bool { + canary := rollout.Spec.Strategy.Canary + if canary.TrafficRouting == nil || (canary.TrafficRouting.Istio != nil && canary.TrafficRouting.Istio.DestinationRule != nil) { + return false + } + return true +} + func ValidateRolloutStrategyCanary(rollout *v1alpha1.Rollout, fldPath *field.Path) field.ErrorList { canary := rollout.Spec.Strategy.Canary allErrs := field.ErrorList{} @@ -181,7 +191,7 @@ func ValidateRolloutStrategyCanary(rollout *v1alpha1.Rollout, fldPath *field.Pat if canary.CanaryService != "" && canary.StableService != "" && canary.CanaryService == canary.StableService { allErrs = append(allErrs, field.Invalid(fldPath.Child("stableService"), canary.StableService, DuplicatedServicesCanaryMessage)) } - if canary.TrafficRouting != nil { + if requireCanaryStableServices(rollout) { if canary.StableService == "" { allErrs = append(allErrs, field.Invalid(fldPath.Child("stableService"), canary.StableService, InvalidTrafficRoutingMessage)) } diff --git a/rollout/controller.go b/rollout/controller.go index 189e16dcf5..1a211a4063 100644 --- a/rollout/controller.go +++ b/rollout/controller.go @@ -14,14 +14,12 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" - "k8s.io/client-go/dynamic/dynamiclister" appsinformers "k8s.io/client-go/informers/apps/v1" coreinformers "k8s.io/client-go/informers/core/v1" extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1" @@ -32,7 +30,6 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" - "k8s.io/kubernetes/cmd/kubeadm/app/util" "k8s.io/kubernetes/pkg/controller" "k8s.io/utils/pointer" @@ -56,10 +53,6 @@ import ( unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured" ) -const ( - virtualServiceIndexName = "byVirtualService" -) - // Controller is the controller implementation for Rollout resources type Controller struct { reconcilerBase @@ -97,14 +90,13 @@ type ControllerConfig struct { IngressInformer extensionsinformers.IngressInformer RolloutsInformer informers.RolloutInformer IstioVirtualServiceInformer cache.SharedIndexInformer + IstioDestinationRuleInformer cache.SharedIndexInformer ResyncPeriod time.Duration RolloutWorkQueue workqueue.RateLimitingInterface ServiceWorkQueue workqueue.RateLimitingInterface IngressWorkQueue workqueue.RateLimitingInterface MetricsServer *metrics.MetricsServer Recorder record.EventRecorder - DefaultIstioVersion string - DefaultTrafficSplitVersion string } // reconcilerBase is a shared datastructure containing all clients and configuration necessary to @@ -116,10 +108,8 @@ type reconcilerBase struct { argoprojclientset clientset.Interface // dynamicclientset is a dynamic clientset for interacting with unstructured resources. // It is used to interact with TrafficRouting resources - dynamicclientset dynamic.Interface - smiclientset smiclientset.Interface - defaultIstioVersion string - defaultTrafficSplitVersion string + dynamicclientset dynamic.Interface + smiclientset smiclientset.Interface replicaSetLister appslisters.ReplicaSetLister replicaSetSynced cache.InformerSynced @@ -133,10 +123,7 @@ type reconcilerBase struct { analysisRunLister listers.AnalysisRunLister analysisTemplateLister listers.AnalysisTemplateLister clusterAnalysisTemplateLister listers.ClusterAnalysisTemplateLister - // Include istioVirtualServiceInformer in Controller struct. If Istio does not exist and is - // later added, then controller will auto-detect change and start istioVirtualServiceInformer - istioVirtualServiceInformer cache.SharedIndexInformer - istioVirtualServiceLister dynamiclister.Lister + IstioController *istio.IstioController podRestarter RolloutPodRestarter @@ -171,8 +158,6 @@ func NewController(cfg ControllerConfig) *Controller { argoprojclientset: cfg.ArgoProjClientset, dynamicclientset: cfg.DynamicClientSet, smiclientset: cfg.SmiClientSet, - defaultIstioVersion: cfg.DefaultIstioVersion, - defaultTrafficSplitVersion: cfg.DefaultTrafficSplitVersion, replicaSetLister: cfg.ReplicaSetInformer.Lister(), replicaSetSynced: cfg.ReplicaSetInformer.Informer().HasSynced, rolloutsInformer: cfg.RolloutsInformer.Informer(), @@ -185,8 +170,6 @@ func NewController(cfg ControllerConfig) *Controller { analysisRunLister: cfg.AnalysisRunInformer.Lister(), analysisTemplateLister: cfg.AnalysisTemplateInformer.Lister(), clusterAnalysisTemplateLister: cfg.ClusterAnalysisTemplateInformer.Lister(), - istioVirtualServiceLister: dynamiclister.New(cfg.IstioVirtualServiceInformer.GetIndexer(), istioutil.GetIstioGVR(cfg.DefaultIstioVersion)), - istioVirtualServiceInformer: cfg.IstioVirtualServiceInformer, recorder: cfg.Recorder, resyncPeriod: cfg.ResyncPeriod, podRestarter: podRestarter, @@ -208,6 +191,15 @@ func NewController(cfg ControllerConfig) *Controller { controllerutil.EnqueueAfter(obj, duration, cfg.RolloutWorkQueue) } + controller.IstioController = istio.NewIstioController(istio.IstioControllerConfig{ + ArgoprojClientSet: cfg.ArgoProjClientset, + DynamicClientSet: cfg.DynamicClientSet, + EnqueueRollout: controller.enqueueRollout, + RolloutsInformer: cfg.RolloutsInformer, + VirtualServiceInformer: cfg.IstioVirtualServiceInformer, + DestinationRuleInformer: cfg.IstioDestinationRuleInformer, + }) + controller.newTrafficRoutingReconciler = controller.NewTrafficRoutingReconciler log.Info("Setting up event handlers") @@ -217,33 +209,35 @@ func NewController(cfg ControllerConfig) *Controller { UpdateFunc: func(old, new interface{}) { oldRollout := unstructuredutil.ObjectToRollout(old) newRollout := unstructuredutil.ObjectToRollout(new) - if old == nil || new == nil { - return - } - for _, s := range serviceutil.GetRolloutServiceKeys(oldRollout) { - controller.serviceWorkqueue.AddRateLimited(s) + if oldRollout != nil && newRollout != nil { + // Check if rollout services/destinationrules were modified, if so we enqueue the + // referenced Service and/or DestinationRules so that the rollouts-pod-template-hash + // can be cleared from each + if modifiedKeys("Service", oldRollout, newRollout, serviceutil.GetRolloutServiceKeys) { + for _, s := range serviceutil.GetRolloutServiceKeys(oldRollout) { + controller.serviceWorkqueue.AddRateLimited(s) + } + } + if modifiedKeys("DestinationRule", oldRollout, newRollout, istioutil.GetRolloutDesinationRuleKeys) { + controller.IstioController.EnqueueDestinationRuleFromRollout(oldRollout) + } } controller.enqueueRollout(newRollout) }, DeleteFunc: func(obj interface{}) { if ro := unstructuredutil.ObjectToRollout(obj); ro != nil { + logCtx := logutil.WithRollout(ro) + logCtx.Info("rollout deleted") + // Rollout is deleted, queue up the referenced Service and/or DestinationRules so + // that the rollouts-pod-template-hash can be cleared from each for _, s := range serviceutil.GetRolloutServiceKeys(ro) { controller.serviceWorkqueue.AddRateLimited(s) } + controller.IstioController.EnqueueDestinationRuleFromRollout(ro) } }, }) - // Indexer to frequently check/enqueue Rollouts that reference virtualServices - util.CheckErr(cfg.RolloutsInformer.Informer().AddIndexers(cache.Indexers{ - virtualServiceIndexName: func(obj interface{}) (strings []string, e error) { - if ro := unstructuredutil.ObjectToRollout(obj); ro != nil { - return istio.GetRolloutVirtualServiceKeys(ro), nil - } - return - }, - })) - cfg.ReplicaSetInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { controllerutil.EnqueueParentObject(obj, register.RolloutKind, controller.enqueueRollout) @@ -284,22 +278,31 @@ func NewController(cfg ControllerConfig) *Controller { }, }) - cfg.IstioVirtualServiceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - controller.EnqueueIstioVsvc(obj) - }, - // TODO: DeepEquals on httpRoutes - UpdateFunc: func(old, new interface{}) { - controller.EnqueueIstioVsvc(new) - }, - DeleteFunc: func(obj interface{}) { - controller.EnqueueIstioVsvc(obj) - }, - }) - return controller } +// modifiedKeys returns true if the indexer keys have been modified in the given rollout +func modifiedKeys(name string, old, new *v1alpha1.Rollout, keyFunc func(ro *v1alpha1.Rollout) []string) bool { + oldKeys := keyFunc(old) + newKeys := keyFunc(new) + modified := false + if len(oldKeys) != len(newKeys) { + modified = true + } else { + for i := 0; i < len(oldKeys); i++ { + if oldKeys[i] != newKeys[i] { + modified = true + break + } + } + } + if modified { + logCtx := logutil.WithRollout(old) + logCtx.Infof("%s index keys modified. before: %v, after: %v", name, oldKeys, newKeys) + } + return modified +} + // Run will set up the event handlers for types we are interested in, as well // as syncing informer caches and starting workers. It will block until stopCh // is closed, at which point it will shutdown the workqueue and wait for @@ -313,9 +316,7 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error { } log.Info("Started Rollout workers") - // Auto-detect whether user adds Istio Virtual Service to cluster - // If it is added, then run the istioVirtualServiceInformer so that we can use istioVirtualServiceLister - go c.runVirtualServiceInformer(stopCh) + go c.IstioController.Run(stopCh) <-stopCh log.Info("Shutting down workers") @@ -323,40 +324,6 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error { return nil } -func (c *Controller) runVirtualServiceInformer(stopCh <-chan struct{}) { - ticker := time.NewTicker(10 * time.Minute) - for !istioutil.DoesIstioExist(c.dynamicclientset, c.namespace, c.defaultIstioVersion) { - // Should only execute if Istio is not installed on cluster - select { - case <-stopCh: - ticker.Stop() - return - case <-ticker.C: - } - } - ticker.Stop() - if !c.istioVirtualServiceInformer.HasSynced() { - // Should only execute if Istio was installed after Rollout Controller was started - c.istioVirtualServiceInformer.Run(stopCh) - } -} - -func (c *Controller) EnqueueIstioVsvc(vsvc interface{}) { - acc, err := meta.Accessor(vsvc) - if err != nil { - log.Errorf("Error processing istio vsvc from watch: %v: %v", err, vsvc) - return - } - rolloutToEnqueue, err := c.rolloutsIndexer.ByIndex(virtualServiceIndexName, fmt.Sprintf("%s/%s", acc.GetNamespace(), acc.GetName())) - if err != nil { - log.Errorf("Cannot process indexer: %s", err.Error()) - return - } - for i := range rolloutToEnqueue { - c.enqueueRollout(rolloutToEnqueue[i]) - } -} - // syncHandler compares the actual state with the desired, and attempts to // converge the two. It then updates the Phase block of the Rollout resource // with the current status of the resource. @@ -374,7 +341,7 @@ func (c *Controller) syncHandler(key string) error { if err != nil { return err } - log.WithField(logutil.RolloutKey, name).WithField(logutil.NamespaceKey, namespace).Infof("Started syncing rollout at (%v)", startTime) + log.WithField(logutil.RolloutKey, name).WithField(logutil.NamespaceKey, namespace).Info("Started syncing rollout") // Remarshal the rollout to normalize all fields so that when we calculate hashes against the // rollout spec and pod template spec, the hash will be consistent. See issue #70 @@ -539,7 +506,7 @@ func (c *rolloutContext) getRolloutReferencedResources() (*validation.Referenced } refResources.Ingresses = *ingresses - virtualServices, err := c.getReferencedVirtualServices() + virtualServices, err := c.IstioController.GetReferencedVirtualServices(c.rollout) if err != nil { return nil, err } @@ -728,34 +695,6 @@ func (c *rolloutContext) getReferencedIngresses() (*[]v1beta1.Ingress, error) { return &ingresses, nil } -func (c *rolloutContext) getReferencedVirtualServices() (*[]unstructured.Unstructured, error) { - ctx := context.TODO() - virtualServices := []unstructured.Unstructured{} - fldPath := field.NewPath("spec", "strategy", "canary", "trafficRouting", "istio", "virtualService", "name") - if c.rollout.Spec.Strategy.Canary != nil { - canary := c.rollout.Spec.Strategy.Canary - if canary.TrafficRouting != nil && canary.TrafficRouting.Istio != nil { - var vsvc *unstructured.Unstructured - var err error - vsvcName := canary.TrafficRouting.Istio.VirtualService.Name - if c.istioVirtualServiceInformer.HasSynced() { - vsvc, err = c.istioVirtualServiceLister.Namespace(c.rollout.Namespace).Get(vsvcName) - } else { - vsvc, err = c.dynamicclientset.Resource(istioutil.GetIstioGVR(c.defaultIstioVersion)).Namespace(c.rollout.Namespace).Get(ctx, vsvcName, metav1.GetOptions{}) - } - - if k8serrors.IsNotFound(err) { - return nil, field.Invalid(fldPath, vsvcName, err.Error()) - } - if err != nil { - return nil, err - } - virtualServices = append(virtualServices, *vsvc) - } - } - return &virtualServices, nil -} - func remarshalRollout(r *v1alpha1.Rollout) *v1alpha1.Rollout { rolloutBytes, err := json.Marshal(r) if err != nil { diff --git a/rollout/controller_test.go b/rollout/controller_test.go index 29bb12fe15..3e4bd66044 100644 --- a/rollout/controller_test.go +++ b/rollout/controller_test.go @@ -416,7 +416,8 @@ func (f *fixture) newController(resync resyncFunc) (*Controller, informers.Share // Pass in objects to to dynamicClient dynamicClient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme()) dynamicInformerFactory := dynamicinformer.NewDynamicSharedInformerFactory(dynamicClient, 0) - istioVirtualServiceInformer := dynamicInformerFactory.ForResource(istioutil.GetIstioGVR("v1alpha3")).Informer() + istioVirtualServiceInformer := dynamicInformerFactory.ForResource(istioutil.GetIstioVirtualServiceGVR()).Informer() + istioDestinationRuleInformer := dynamicInformerFactory.ForResource(istioutil.GetIstioDestinationRuleGVR()).Informer() rolloutWorkqueue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Rollouts") serviceWorkqueue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Services") @@ -441,13 +442,13 @@ func (f *fixture) newController(resync resyncFunc) (*Controller, informers.Share IngressInformer: k8sI.Extensions().V1beta1().Ingresses(), RolloutsInformer: i.Argoproj().V1alpha1().Rollouts(), IstioVirtualServiceInformer: istioVirtualServiceInformer, + IstioDestinationRuleInformer: istioDestinationRuleInformer, ResyncPeriod: resync(), RolloutWorkQueue: rolloutWorkqueue, ServiceWorkQueue: serviceWorkqueue, IngressWorkQueue: ingressWorkqueue, MetricsServer: metricsServer, Recorder: &FakeEventRecorder{}, - DefaultIstioVersion: "v1alpha3", }) var enqueuedObjectsLock sync.Mutex @@ -1464,31 +1465,6 @@ func TestGetReferencedIngressesNginx(t *testing.T) { }) } -func TestGetReferencedVirtualServices(t *testing.T) { - f := newFixture(t) - defer f.Close() - r := newCanaryRollout("rollout", 1, nil, nil, nil, intstr.FromInt(0), intstr.FromInt(1)) - r.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{ - Istio: &v1alpha1.IstioTrafficRouting{ - VirtualService: v1alpha1.IstioVirtualService{ - Name: "istio-vsvc-name", - }, - }, - } - r.Namespace = metav1.NamespaceDefault - - t.Run("get referenced virtualService - fail", func(t *testing.T) { - c, _, _ := f.newController(noResyncPeriodFunc) - schema := runtime.NewScheme() - c.dynamicclientset = dynamicfake.NewSimpleDynamicClient(schema) - roCtx, err := c.newRolloutContext(r) - assert.NoError(t, err) - _, err = roCtx.getReferencedVirtualServices() - expectedErr := field.Invalid(field.NewPath("spec", "strategy", "canary", "trafficRouting", "istio", "virtualService", "name"), "istio-vsvc-name", "virtualservices.networking.istio.io \"istio-vsvc-name\" not found") - assert.Equal(t, expectedErr.Error(), err.Error()) - }) -} - func TestRolloutStrategyNotSet(t *testing.T) { f := newFixture(t) defer f.Close() diff --git a/rollout/mocks/TrafficRoutingReconciler.go b/rollout/mocks/TrafficRoutingReconciler.go index cf17fa6ea2..98cc134265 100644 --- a/rollout/mocks/TrafficRoutingReconciler.go +++ b/rollout/mocks/TrafficRoutingReconciler.go @@ -37,6 +37,20 @@ func (_m *TrafficRoutingReconciler) Type() string { return r0 } +// UpdateHash provides a mock function with given fields: canaryHash, stableHash +func (_m *TrafficRoutingReconciler) UpdateHash(canaryHash string, stableHash string) error { + ret := _m.Called(canaryHash, stableHash) + + var r0 error + if rf, ok := ret.Get(0).(func(string, string) error); ok { + r0 = rf(canaryHash, stableHash) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // VerifyWeight provides a mock function with given fields: desiredWeight func (_m *TrafficRoutingReconciler) VerifyWeight(desiredWeight int32) (bool, error) { ret := _m.Called(desiredWeight) diff --git a/rollout/trafficrouting.go b/rollout/trafficrouting.go index 05d05eb30b..095342ca6f 100644 --- a/rollout/trafficrouting.go +++ b/rollout/trafficrouting.go @@ -5,6 +5,7 @@ import ( corev1 "k8s.io/api/core/v1" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/alb" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/istio" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/nginx" @@ -15,6 +16,8 @@ import ( // TrafficRoutingReconciler common function across all TrafficRouting implementation type TrafficRoutingReconciler interface { + // UpdateHash informs a traffic routing reconciler about new canary/stable pod hashes + UpdateHash(canaryHash, stableHash string) error // SetWeight sets the canary weight to the desired weight SetWeight(desiredWeight int32) error // VerifyWeight returns true if the canary is at the desired weight @@ -30,10 +33,10 @@ func (c *Controller) NewTrafficRoutingReconciler(roCtx *rolloutContext) (Traffic return nil, nil } if rollout.Spec.Strategy.Canary.TrafficRouting.Istio != nil { - if c.istioVirtualServiceInformer.HasSynced() { - return istio.NewReconciler(rollout, c.dynamicclientset, c.recorder, c.defaultIstioVersion, c.istioVirtualServiceLister), nil + if c.IstioController.VirtualServiceInformer.HasSynced() { + return istio.NewReconciler(rollout, c.dynamicclientset, c.recorder, c.IstioController.VirtualServiceLister, c.IstioController.DestinationRuleLister), nil } else { - return istio.NewReconciler(rollout, c.dynamicclientset, c.recorder, c.defaultIstioVersion, nil), nil + return istio.NewReconciler(rollout, c.dynamicclientset, c.recorder, nil, nil), nil } } if rollout.Spec.Strategy.Canary.TrafficRouting.Nginx != nil { @@ -60,7 +63,6 @@ func (c *Controller) NewTrafficRoutingReconciler(roCtx *rolloutContext) (Traffic Client: c.smiclientset, Recorder: c.recorder, ControllerKind: controllerKind, - ApiVersion: c.defaultTrafficSplitVersion, }) } return nil, nil @@ -76,6 +78,18 @@ func (c *rolloutContext) reconcileTrafficRouting() error { } c.log.Infof("Reconciling TrafficRouting with type '%s'", reconciler.Type()) + var canaryHash, stableHash string + if c.stableRS != nil { + stableHash = c.stableRS.Labels[v1alpha1.DefaultRolloutUniqueLabelKey] + } + if c.newRS != nil { + canaryHash = c.newRS.Labels[v1alpha1.DefaultRolloutUniqueLabelKey] + } + err = reconciler.UpdateHash(canaryHash, stableHash) + if err != nil { + return err + } + currentStep, index := replicasetutil.GetCurrentCanaryStep(c.rollout) desiredWeight := int32(0) if c.rollout.Status.StableRS == c.rollout.Status.CurrentPodHash { diff --git a/rollout/trafficrouting/alb/alb.go b/rollout/trafficrouting/alb/alb.go index ee2c8ed612..a03fa39434 100644 --- a/rollout/trafficrouting/alb/alb.go +++ b/rollout/trafficrouting/alb/alb.go @@ -220,3 +220,8 @@ func getDesiredAnnotations(current *extensionsv1beta1.Ingress, r *v1alpha1.Rollo desired[ingressutil.ManagedActionsAnnotation] = m.String() return desired, nil } + +// UpdateHash informs a traffic routing reconciler about new canary/stable pod hashes +func (r *Reconciler) UpdateHash(canaryHash, stableHash string) error { + return nil +} diff --git a/rollout/trafficrouting/istio/controller.go b/rollout/trafficrouting/istio/controller.go new file mode 100644 index 0000000000..895674b88f --- /dev/null +++ b/rollout/trafficrouting/istio/controller.go @@ -0,0 +1,290 @@ +package istio + +import ( + "context" + "fmt" + "time" + + log "github.com/sirupsen/logrus" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamiclister" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/slice" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + roclientset "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned" + informers "github.com/argoproj/argo-rollouts/pkg/client/informers/externalversions/rollouts/v1alpha1" + controllerutil "github.com/argoproj/argo-rollouts/utils/controller" + "github.com/argoproj/argo-rollouts/utils/defaults" + istioutil "github.com/argoproj/argo-rollouts/utils/istio" + logutil "github.com/argoproj/argo-rollouts/utils/log" + unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured" +) + +const ( + // names for the rollout indexer + virtualServiceIndexName = "byVirtualService" + destinationRuleIndexName = "byDestinationRule" + + // default number of workers to handle DestinationRule update events + destinationRuleWorkers = 10 +) + +type IstioControllerConfig struct { + ArgoprojClientSet roclientset.Interface + DynamicClientSet dynamic.Interface + EnqueueRollout func(ro interface{}) + RolloutsInformer informers.RolloutInformer + VirtualServiceInformer cache.SharedIndexInformer + DestinationRuleInformer cache.SharedIndexInformer +} + +type IstioController struct { + IstioControllerConfig + VirtualServiceLister dynamiclister.Lister + DestinationRuleLister dynamiclister.Lister + + destinationRuleWorkqueue workqueue.RateLimitingInterface +} + +func NewIstioController(cfg IstioControllerConfig) *IstioController { + c := IstioController{ + IstioControllerConfig: cfg, + destinationRuleWorkqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DestinationRules"), + VirtualServiceLister: dynamiclister.New(cfg.VirtualServiceInformer.GetIndexer(), istioutil.GetIstioVirtualServiceGVR()), + DestinationRuleLister: dynamiclister.New(cfg.DestinationRuleInformer.GetIndexer(), istioutil.GetIstioDestinationRuleGVR()), + } + + // Add a Rollout index against referenced VirtualServices and DestinationRules + util.CheckErr(cfg.RolloutsInformer.Informer().AddIndexers(cache.Indexers{ + virtualServiceIndexName: func(obj interface{}) (strings []string, e error) { + if ro := unstructuredutil.ObjectToRollout(obj); ro != nil { + return istioutil.GetRolloutVirtualServiceKeys(ro), nil + } + return + }, + })) + util.CheckErr(cfg.RolloutsInformer.Informer().AddIndexers(cache.Indexers{ + destinationRuleIndexName: func(obj interface{}) (strings []string, e error) { + if ro := unstructuredutil.ObjectToRollout(obj); ro != nil { + return istioutil.GetRolloutDesinationRuleKeys(ro), nil + } + return + }, + })) + + // When a VirtualService changes, simply enqueue the referencing rollout + c.VirtualServiceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + c.EnqueueRolloutFromIstioVirtualService(obj) + }, + // TODO: DeepEquals on httpRoutes + UpdateFunc: func(old, new interface{}) { + c.EnqueueRolloutFromIstioVirtualService(new) + }, + DeleteFunc: func(obj interface{}) { + c.EnqueueRolloutFromIstioVirtualService(obj) + }, + }) + + // When a DestinationRule changes, enqueue the DestinationRule for processing + c.DestinationRuleInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + c.EnqueueDestinationRule(obj) + }, + UpdateFunc: func(old, new interface{}) { + c.EnqueueDestinationRule(new) + }, + DeleteFunc: func(obj interface{}) { + c.EnqueueDestinationRule(obj) + }, + }) + return &c +} + +// Run starts the Istio informers. If Istio is not installed, will periodically check for presence +// of Istio, then start informers once detected. This allows Argo Rollouts to be installed in any +// order during cluster bootstrapping. +func (c *IstioController) Run(stopCh <-chan struct{}) { + ns := defaults.Namespace() + waitForIstioInstall := !istioutil.DoesIstioExist(c.DynamicClientSet, ns) + if waitForIstioInstall { + ticker := time.NewTicker(10 * time.Minute) + for !istioutil.DoesIstioExist(c.DynamicClientSet, ns) { + // Should only execute if Istio is not installed on cluster + select { + case <-stopCh: + ticker.Stop() + return + case <-ticker.C: + } + } + ticker.Stop() + log.Info("Istio install detected. Starting informers") + go c.VirtualServiceInformer.Run(stopCh) + go c.DestinationRuleInformer.Run(stopCh) + } else { + log.Info("Istio detected") + } + + cache.WaitForCacheSync(stopCh, c.VirtualServiceInformer.HasSynced, c.DestinationRuleInformer.HasSynced) + + for i := 0; i < destinationRuleWorkers; i++ { + go wait.Until(func() { + controllerutil.RunWorker(c.destinationRuleWorkqueue, "destinationrule", c.syncDestinationRule, nil) + }, time.Second, stopCh) + } + log.Infof("Istio workers (%d) started", destinationRuleWorkers) + + <-stopCh + log.Info("Istio controller stopped") +} + +// EnqueueDestinationRule examines a VirtualService, finds the Rollout referencing +// that VirtualService, and enqueues the corresponding Rollout for reconciliation +func (c *IstioController) EnqueueDestinationRule(obj interface{}) { + controllerutil.EnqueueRateLimited(obj, c.destinationRuleWorkqueue) +} + +// EnqueueDestinationRuleFromRollout examines a VirtualService, finds the Rollout referencing +// that VirtualService, and enqueues the corresponding Rollout for reconciliation +func (c *IstioController) EnqueueDestinationRuleFromRollout(ro *v1alpha1.Rollout) { + for _, dRuleKey := range istioutil.GetRolloutDesinationRuleKeys(ro) { + controllerutil.EnqueueRateLimited(dRuleKey, c.destinationRuleWorkqueue) + } +} + +// EnqueueRolloutFromIstioVirtualService examines a VirtualService, finds the Rollout referencing +// that VirtualService, and enqueues the corresponding Rollout for reconciliation +func (c *IstioController) EnqueueRolloutFromIstioVirtualService(vsvc interface{}) { + acc, err := meta.Accessor(vsvc) + if err != nil { + log.Errorf("Error processing istio VirtualService from watch: %v: %v", err, vsvc) + return + } + rolloutToEnqueue, err := c.RolloutsInformer.Informer().GetIndexer().ByIndex(virtualServiceIndexName, fmt.Sprintf("%s/%s", acc.GetNamespace(), acc.GetName())) + if err != nil { + log.Errorf("Cannot process indexer: %s", err.Error()) + return + } + for i := range rolloutToEnqueue { + c.EnqueueRollout(rolloutToEnqueue[i]) + } +} + +func (c *IstioController) GetReferencedVirtualServices(ro *v1alpha1.Rollout) (*[]unstructured.Unstructured, error) { + ctx := context.TODO() + virtualServices := []unstructured.Unstructured{} + fldPath := field.NewPath("spec", "strategy", "canary", "trafficRouting", "istio", "virtualService", "name") + if ro.Spec.Strategy.Canary != nil { + canary := ro.Spec.Strategy.Canary + if canary.TrafficRouting != nil && canary.TrafficRouting.Istio != nil { + var vsvc *unstructured.Unstructured + var err error + vsvcName := canary.TrafficRouting.Istio.VirtualService.Name + if c.VirtualServiceInformer.HasSynced() { + vsvc, err = c.VirtualServiceLister.Namespace(ro.Namespace).Get(vsvcName) + } else { + vsvc, err = c.DynamicClientSet.Resource(istioutil.GetIstioVirtualServiceGVR()).Namespace(ro.Namespace).Get(ctx, vsvcName, metav1.GetOptions{}) + } + + if k8serrors.IsNotFound(err) { + return nil, field.Invalid(fldPath, vsvcName, err.Error()) + } + if err != nil { + return nil, err + } + virtualServices = append(virtualServices, *vsvc) + } + } + return &virtualServices, nil +} + +// syncDestinationRule examines a DestinationRule, finds the Rollout which is managing that +// DestinationRule, and enqueues it for reconciliation. If no Rollout is managing the +// DestinationRule, it removes any injected labels/annotations in that DestinationRule (i.e. the +// `rollouts-pod-template-hash` label and the managed-by annotation. This handles the case when a +// Rollout has either been deleted, or modified such that it is longer referencing the +// DestinationRule. +func (c *IstioController) syncDestinationRule(key string) error { + namespace, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + return err + } + dRuleUn, err := c.DestinationRuleLister.Namespace(namespace).Get(name) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return err + } + managingRolloutName := getManagingRolloutName(dRuleUn) + if managingRolloutName == "" { + // Ignore DestinationRules not managed by a Rollout + return nil + } + + logCtx := log.WithField(logutil.RolloutKey, managingRolloutName).WithField(logutil.NamespaceKey, namespace).WithField("destinationrule", name) + + cleanDestRule := false + ro, err := c.ArgoprojClientSet.ArgoprojV1alpha1().Rollouts(namespace).Get(context.TODO(), managingRolloutName, metav1.GetOptions{}) + if err != nil { + if !k8serrors.IsNotFound(err) { + return err + } + logCtx.Infof("cleaning destinationrule: rollout does not exist") + cleanDestRule = true + } else { + if !slice.ContainsString(istioutil.GetRolloutDesinationRuleKeys(ro), key, nil) { + logCtx.Infof("cleaning destinationrule: rollout no longer references rule") + cleanDestRule = true + } + } + + if cleanDestRule { + // remove any fields we may have injected into a DestinationRule + origBytes, dRule, dRuleNew, err := unstructuredToDestinationRules(dRuleUn) + if err != nil { + return err + } + if dRuleNew.Annotations != nil { + delete(dRuleNew.Annotations, v1alpha1.ManagedByRolloutsKey) + } + for i, subset := range dRuleNew.Spec.Subsets { + if _, exists := subset.Labels[v1alpha1.DefaultRolloutUniqueLabelKey]; exists { + delete(subset.Labels, v1alpha1.DefaultRolloutUniqueLabelKey) + dRuleNew.Spec.Subsets[i] = subset + } + } + dRuleClient := c.DynamicClientSet.Resource(istioutil.GetIstioDestinationRuleGVR()).Namespace(dRule.Namespace) + modified, err := updateDestinationRule(context.TODO(), dRuleClient, origBytes, dRule, dRuleNew) + if err != nil { + return err + } + if modified { + logCtx.Infof("cleaned destination rule") + return nil + } + } + + // destination rule changed, re-reconcile rollout + c.EnqueueRollout(namespace + "/" + managingRolloutName) + return nil +} + +// getManagingRollout returns the name of the rollout managing this DestinationRule or empty string if none +func getManagingRolloutName(un *unstructured.Unstructured) string { + annots := un.GetAnnotations() + if annots == nil { + return "" + } + return annots[v1alpha1.ManagedByRolloutsKey] +} diff --git a/rollout/trafficrouting/istio/controller_test.go b/rollout/trafficrouting/istio/controller_test.go new file mode 100644 index 0000000000..bf2e6f3024 --- /dev/null +++ b/rollout/trafficrouting/istio/controller_test.go @@ -0,0 +1,200 @@ +package istio + +import ( + "context" + "testing" + "time" + + "github.com/tj/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/client-go/dynamic/dynamicinformer" + dynamicfake "k8s.io/client-go/dynamic/fake" + "k8s.io/client-go/tools/cache" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + rolloutfake "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned/fake" + rolloutinformers "github.com/argoproj/argo-rollouts/pkg/client/informers/externalversions" + istioutil "github.com/argoproj/argo-rollouts/utils/istio" + unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured" +) + +func NewFakeIstioController(objs ...runtime.Object) *IstioController { + schema := runtime.NewScheme() + + var argoprojObjs []runtime.Object + var istioObjs []runtime.Object + + for _, obj := range objs { + switch obj.(type) { + case *v1alpha1.Rollout: + argoprojObjs = append(argoprojObjs, obj) + case *unstructured.Unstructured: + istioObjs = append(istioObjs, obj) + } + } + + rolloutClient := rolloutfake.NewSimpleClientset(argoprojObjs...) + rolloutInformerFactory := rolloutinformers.NewSharedInformerFactory(rolloutClient, 0) + dynamicClientSet := dynamicfake.NewSimpleDynamicClient(schema, istioObjs...) + dynamicInformerFactory := dynamicinformer.NewDynamicSharedInformerFactory(dynamicClientSet, 0) + virtualServiceInformer := dynamicInformerFactory.ForResource(istioutil.GetIstioVirtualServiceGVR()).Informer() + destinationRuleInformer := dynamicInformerFactory.ForResource(istioutil.GetIstioDestinationRuleGVR()).Informer() + + c := NewIstioController(IstioControllerConfig{ + ArgoprojClientSet: rolloutClient, + DynamicClientSet: dynamicClientSet, + EnqueueRollout: func(ro interface{}) {}, + RolloutsInformer: rolloutInformerFactory.Argoproj().V1alpha1().Rollouts(), + VirtualServiceInformer: virtualServiceInformer, + DestinationRuleInformer: destinationRuleInformer, + }) + return c +} + +func TestGetReferencedVirtualServices(t *testing.T) { + ro := v1alpha1.Rollout{ + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{}, + }, + }, + } + ro.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{ + Istio: &v1alpha1.IstioTrafficRouting{ + VirtualService: v1alpha1.IstioVirtualService{ + Name: "istio-vsvc-name", + }, + }, + } + ro.Namespace = metav1.NamespaceDefault + + t.Run("get referenced virtualService - fail", func(t *testing.T) { + c := NewFakeIstioController() + _, err := c.GetReferencedVirtualServices(&ro) + expectedErr := field.Invalid(field.NewPath("spec", "strategy", "canary", "trafficRouting", "istio", "virtualService", "name"), "istio-vsvc-name", "virtualservices.networking.istio.io \"istio-vsvc-name\" not found") + assert.Equal(t, expectedErr.Error(), err.Error()) + }) +} + +func TestSyncDestinationRule(t *testing.T) { + ro := &v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: "istio-rollout", + Namespace: metav1.NamespaceDefault, + }, + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{ + TrafficRouting: &v1alpha1.RolloutTrafficRouting{ + Istio: &v1alpha1.IstioTrafficRouting{ + VirtualService: v1alpha1.IstioVirtualService{ + Name: "istio-vsvc", + }, + DestinationRule: &v1alpha1.IstioDestinationRule{ + Name: "istio-destrule", + CanarySubsetName: "canary", + StableSubsetName: "stable", + }, + }, + }, + }, + }, + }, + } + destRule := unstructuredutil.StrToUnstructuredUnsafe(` +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-destrule + namespace: default + annotations: + argo-rollouts.argoproj.io/managed-by-rollouts: istio-rollout +spec: + subsets: + - name: stable + labels: + app: istio-subset-split + rollouts-pod-template-hash: abc123 + - name: canary + labels: + app: istio-subset-split + rollouts-pod-template-hash: def456 +`) + { + // Verify we don't clean a DestinationRule when it is still being referenced + c := NewFakeIstioController(ro, destRule) + err := c.DestinationRuleInformer.GetIndexer().Add(destRule) + assert.NoError(t, err) + key, err := cache.MetaNamespaceKeyFunc(destRule) + assert.NoError(t, err) + enqueueCalled := false + c.EnqueueRollout = func(obj interface{}) { + enqueueCalled = true + } + + err = c.syncDestinationRule(key) + assert.NoError(t, err) + actions := c.DynamicClientSet.(*dynamicfake.FakeDynamicClient).Actions() + assert.Len(t, actions, 0) + assert.True(t, enqueueCalled) + } + + { + // Verify clean a DestinationRule rule when rollout no longer references it + ro = ro.DeepCopy() + ro.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule = nil + c := NewFakeIstioController(ro, destRule) + err := c.DestinationRuleInformer.GetIndexer().Add(destRule) + assert.NoError(t, err) + key, err := cache.MetaNamespaceKeyFunc(destRule) + assert.NoError(t, err) + enqueueCalled := false + c.EnqueueRollout = func(obj interface{}) { + enqueueCalled = true + } + + err = c.syncDestinationRule(key) + assert.NoError(t, err) + actions := c.DynamicClientSet.(*dynamicfake.FakeDynamicClient).Actions() + assert.Len(t, actions, 1) + assert.Equal(t, "update", actions[0].GetVerb()) + assert.False(t, enqueueCalled) + } + + { + // Verify clean a DestinationRule rule when rollout no longer exists + c := NewFakeIstioController(destRule) + err := c.DestinationRuleInformer.GetIndexer().Add(destRule) + assert.NoError(t, err) + key, err := cache.MetaNamespaceKeyFunc(destRule) + assert.NoError(t, err) + enqueueCalled := false + c.EnqueueRollout = func(obj interface{}) { + enqueueCalled = true + } + + err = c.syncDestinationRule(key) + assert.NoError(t, err) + actions := c.DynamicClientSet.(*dynamicfake.FakeDynamicClient).Actions() + assert.Len(t, actions, 1) + assert.Equal(t, "update", actions[0].GetVerb()) + assert.False(t, enqueueCalled) + } +} + +func TestRun(t *testing.T) { + // make sure we can start and top the controller + c := NewFakeIstioController() + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + go func() { + time.Sleep(100 * time.Millisecond) + cancel() + }() + go c.DestinationRuleInformer.Run(ctx.Done()) + go c.VirtualServiceInformer.Run(ctx.Done()) + c.Run(ctx.Done()) +} diff --git a/rollout/trafficrouting/istio/istio.go b/rollout/trafficrouting/istio/istio.go index 92c369e40c..ef18c60f18 100644 --- a/rollout/trafficrouting/istio/istio.go +++ b/rollout/trafficrouting/istio/istio.go @@ -5,7 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/sirupsen/logrus" + jsonpatch "github.com/evanphx/json-patch/v5" + log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -22,43 +23,26 @@ import ( const Type = "Istio" // NewReconciler returns a reconciler struct that brings the Virtual Service into the desired state -func NewReconciler(r *v1alpha1.Rollout, client dynamic.Interface, recorder record.EventRecorder, defaultAPIVersion string, istioVirtualServiceLister dynamiclister.Lister) *Reconciler { +func NewReconciler(r *v1alpha1.Rollout, client dynamic.Interface, recorder record.EventRecorder, virtualServiceLister, destinationRuleLister dynamiclister.Lister) *Reconciler { return &Reconciler{ rollout: r, log: logutil.WithRollout(r), - client: client, - recorder: recorder, - defaultAPIVersion: defaultAPIVersion, - istioVirtualServiceLister: istioVirtualServiceLister, + client: client, + recorder: recorder, + virtualServiceLister: virtualServiceLister, + destinationRuleLister: destinationRuleLister, } } -// GetRolloutVirtualServiceKeys gets the virtual service and its namespace from a rollout -func GetRolloutVirtualServiceKeys(rollout *v1alpha1.Rollout) []string { - if rollout.Spec.Strategy.Canary == nil { - return []string{} - } - if rollout.Spec.Strategy.Canary.TrafficRouting == nil { - return []string{} - } - if rollout.Spec.Strategy.Canary.TrafficRouting.Istio == nil { - return []string{} - } - if rollout.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Name == "" { - return []string{} - } - return []string{fmt.Sprintf("%s/%s", rollout.Namespace, rollout.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Name)} -} - // Reconciler holds required fields to reconcile Istio resources type Reconciler struct { - rollout *v1alpha1.Rollout - log *logrus.Entry - client dynamic.Interface - recorder record.EventRecorder - defaultAPIVersion string - istioVirtualServiceLister dynamiclister.Lister + rollout *v1alpha1.Rollout + log *log.Entry + client dynamic.Interface + recorder record.EventRecorder + virtualServiceLister dynamiclister.Lister + destinationRuleLister dynamiclister.Lister } type virtualServicePatch struct { @@ -95,13 +79,19 @@ func (patches virtualServicePatches) patchVirtualService(httpRoutes []interface{ return nil } -func (r *Reconciler) generateVirtualServicePatches(httpRoutes []HttpRoute, desiredWeight int64) virtualServicePatches { +func (r *Reconciler) generateVirtualServicePatches(httpRoutes []VirtualServiceHTTPRoute, desiredWeight int64) virtualServicePatches { canarySvc := r.rollout.Spec.Strategy.Canary.CanaryService stableSvc := r.rollout.Spec.Strategy.Canary.StableService routes := map[string]bool{} for _, r := range r.rollout.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Routes { routes[r] = true } + canarySubset := "" + stableSubset := "" + if r.rollout.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule != nil { + canarySubset = r.rollout.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule.CanarySubsetName + stableSubset = r.rollout.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule.StableSubsetName + } patches := virtualServicePatches{} for i := range httpRoutes { @@ -112,22 +102,27 @@ func (r *Reconciler) generateVirtualServicePatches(httpRoutes []HttpRoute, desir for j := range route.Route { destination := httpRoutes[i].Route[j] host := destination.Destination.Host + subset := destination.Destination.Subset weight := destination.Weight - if host == canarySvc && weight != desiredWeight { - patch := virtualServicePatch{ - routeIndex: i, - destinationIndex: j, - weight: desiredWeight, + if (host != "" && host == canarySvc) || (subset != "" && subset == canarySubset) { + if weight != desiredWeight { + patch := virtualServicePatch{ + routeIndex: i, + destinationIndex: j, + weight: desiredWeight, + } + patches = append(patches, patch) } - patches = append(patches, patch) } - if host == stableSvc && weight != 100-desiredWeight { - patch := virtualServicePatch{ - routeIndex: i, - destinationIndex: j, - weight: 100 - desiredWeight, + if (host != "" && host == stableSvc) || (subset != "" && subset == stableSubset) { + if weight != 100-desiredWeight { + patch := virtualServicePatch{ + routeIndex: i, + destinationIndex: j, + weight: 100 - desiredWeight, + } + patches = append(patches, patch) } - patches = append(patches, patch) } } } @@ -156,6 +151,129 @@ func (r *Reconciler) reconcileVirtualService(obj *unstructured.Unstructured, des return newObj, len(patches) > 0, err } +func (r *Reconciler) UpdateHash(canaryHash, stableHash string) error { + dRuleSpec := r.rollout.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule + if dRuleSpec == nil { + return nil + } + ctx := context.TODO() + client := r.client.Resource(istioutil.GetIstioDestinationRuleGVR()).Namespace(r.rollout.Namespace) + + var dRuleUn *unstructured.Unstructured + var err error + if r.destinationRuleLister != nil { + dRuleUn, err = r.destinationRuleLister.Namespace(r.rollout.Namespace).Get(dRuleSpec.Name) + } else { + dRuleUn, err = client.Get(ctx, dRuleSpec.Name, metav1.GetOptions{}) + } + + if err != nil { + if k8serrors.IsNotFound(err) { + msg := fmt.Sprintf("DestinationRule `%s` not found", dRuleSpec.Name) + r.recorder.Event(r.rollout, corev1.EventTypeWarning, "DestinationRuleNotFound", msg) + } + return err + } + origBytes, dRule, dRuleNew, err := unstructuredToDestinationRules(dRuleUn) + if err != nil { + return err + } + if dRuleNew.Annotations == nil { + dRuleNew.Annotations = make(map[string]string) + } + dRuleNew.Annotations[v1alpha1.ManagedByRolloutsKey] = r.rollout.Name + for i, subset := range dRuleNew.Spec.Subsets { + if subset.Name == dRuleSpec.CanarySubsetName { + if subset.Labels == nil { + subset.Labels = make(map[string]string) + } + if canaryHash != "" { + subset.Labels[v1alpha1.DefaultRolloutUniqueLabelKey] = canaryHash + } else { + delete(subset.Labels, v1alpha1.DefaultRolloutUniqueLabelKey) + } + } else if subset.Name == dRuleSpec.StableSubsetName { + if subset.Labels == nil { + subset.Labels = make(map[string]string) + } + if stableHash != "" { + subset.Labels[v1alpha1.DefaultRolloutUniqueLabelKey] = stableHash + } else { + delete(subset.Labels, v1alpha1.DefaultRolloutUniqueLabelKey) + } + } + dRuleNew.Spec.Subsets[i] = subset + } + modified, err := updateDestinationRule(ctx, client, origBytes, dRule, dRuleNew) + if err != nil { + return err + } + if modified { + r.log.Infof("DestinationRule %s subset updated (%s: %s, %s: %s)", dRuleSpec.Name, dRuleSpec.CanarySubsetName, canaryHash, dRuleSpec.StableSubsetName, stableHash) + } + return nil +} + +func updateDestinationRule(ctx context.Context, client dynamic.ResourceInterface, orig []byte, dRule, dRuleNew *DestinationRule) (bool, error) { + dRuleBytes, err := json.Marshal(dRule) + if err != nil { + return false, err + } + dRuleNewBytes, err := json.Marshal(dRuleNew) + if err != nil { + return false, err + } + patch, err := jsonpatch.CreateMergePatch(dRuleBytes, dRuleNewBytes) + if err != nil { + return false, err + } + if string(patch) == "{}" { + return false, nil + } + dRuleNewBytes, err = jsonpatch.MergePatch(orig, patch) + if err != nil { + return false, err + } + var newDRuleUn unstructured.Unstructured + err = json.Unmarshal(dRuleNewBytes, &newDRuleUn.Object) + if err != nil { + return false, err + } + _, err = client.Update(ctx, &newDRuleUn, metav1.UpdateOptions{}) + if err != nil { + return false, err + } + log.Infof("updated destinationrule: %s", string(patch)) + return true, nil +} + +// unstructuredToDestinationRules is a helper which returns two instances of DestinationRule +// from an unstructured object. The two copies are used to calculate patches. +func unstructuredToDestinationRules(un *unstructured.Unstructured) ([]byte, *DestinationRule, *DestinationRule, error) { + dRuleBytes, err := json.Marshal(un) + if err != nil { + return nil, nil, nil, err + } + dRule1, err := jsonBytesToDestinationRule(dRuleBytes) + if err != nil { + return nil, nil, nil, err + } + dRule2, err := jsonBytesToDestinationRule(dRuleBytes) + if err != nil { + return nil, nil, nil, err + } + return dRuleBytes, dRule1, dRule2, nil +} + +func jsonBytesToDestinationRule(dRuleBytes []byte) (*DestinationRule, error) { + var dRule DestinationRule + err := json.Unmarshal(dRuleBytes, &dRule) + if err != nil { + return nil, err + } + return &dRule, nil +} + func GetHttpRoutesI(obj *unstructured.Unstructured) ([]interface{}, error) { httpRoutesI, notFound, err := unstructured.NestedSlice(obj.Object, "spec", "http") if !notFound { @@ -167,13 +285,13 @@ func GetHttpRoutesI(obj *unstructured.Unstructured) ([]interface{}, error) { return httpRoutesI, nil } -func GetHttpRoutes(obj *unstructured.Unstructured, httpRoutesI []interface{}) ([]HttpRoute, error) { +func GetHttpRoutes(obj *unstructured.Unstructured, httpRoutesI []interface{}) ([]VirtualServiceHTTPRoute, error) { routeBytes, err := json.Marshal(httpRoutesI) if err != nil { return nil, err } - var httpRoutes []HttpRoute + var httpRoutes []VirtualServiceHTTPRoute err = json.Unmarshal(routeBytes, &httpRoutes) if err != nil { return nil, err @@ -193,15 +311,15 @@ func (r *Reconciler) SetWeight(desiredWeight int32) error { var vsvc *unstructured.Unstructured var err error vsvcName := r.rollout.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Name - client := r.client.Resource(istioutil.GetIstioGVR(r.defaultAPIVersion)).Namespace(r.rollout.Namespace) - if r.istioVirtualServiceLister != nil { - vsvc, err = r.istioVirtualServiceLister.Namespace(r.rollout.Namespace).Get(vsvcName) + client := r.client.Resource(istioutil.GetIstioVirtualServiceGVR()).Namespace(r.rollout.Namespace) + if r.virtualServiceLister != nil { + vsvc, err = r.virtualServiceLister.Namespace(r.rollout.Namespace).Get(vsvcName) } else { vsvc, err = client.Get(ctx, vsvcName, metav1.GetOptions{}) } if err != nil { if k8serrors.IsNotFound(err) { - msg := fmt.Sprintf("Virtual Service `%s` not found", vsvcName) + msg := fmt.Sprintf("VirtualService `%s` not found", vsvcName) r.recorder.Event(r.rollout, corev1.EventTypeWarning, "VirtualServiceNotFound", msg) } return err @@ -225,7 +343,7 @@ func (r *Reconciler) VerifyWeight(desiredWeight int32) (bool, error) { } // validateHTTPRoutes ensures that all the routes in the rollout exist and they only have two destinations -func ValidateHTTPRoutes(r *v1alpha1.Rollout, httpRoutes []HttpRoute) error { +func ValidateHTTPRoutes(r *v1alpha1.Rollout, httpRoutes []VirtualServiceHTTPRoute) error { routes := r.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Routes stableSvc := r.Spec.Strategy.Canary.StableService canarySvc := r.Spec.Strategy.Canary.CanaryService @@ -239,7 +357,7 @@ func ValidateHTTPRoutes(r *v1alpha1.Rollout, httpRoutes []HttpRoute) error { // check if the httpRoute is in the list of routes from the rollout if _, ok := routesPatched[route.Name]; ok { routesPatched[route.Name] = true - err := validateHosts(route, stableSvc, canarySvc) + err := validateVirtualServiceHTTPRouteDestinations(route, stableSvc, canarySvc, r.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule) if err != nil { return err } @@ -255,48 +373,47 @@ func ValidateHTTPRoutes(r *v1alpha1.Rollout, httpRoutes []HttpRoute) error { return nil } -// validateHosts ensures there are two destinations within a route and their hosts are the stable and canary service -func validateHosts(hr HttpRoute, stableSvc, canarySvc string) error { +// validateVirtualServiceHTTPRouteDestinations ensures there are two destinations within a route and +// verifies that there is both a canary and a stable host or subset specified +func validateVirtualServiceHTTPRouteDestinations(hr VirtualServiceHTTPRoute, stableSvc, canarySvc string, dRule *v1alpha1.IstioDestinationRule) error { if len(hr.Route) != 2 { return fmt.Errorf("Route '%s' does not have exactly two routes", hr.Name) } hasStableSvc := false hasCanarySvc := false + hasStableSubset := false + hasCanarySubset := false for _, r := range hr.Route { - if r.Destination.Host == stableSvc { + if stableSvc != "" && r.Destination.Host == stableSvc { hasStableSvc = true } - if r.Destination.Host == canarySvc { + if canarySvc != "" && r.Destination.Host == canarySvc { hasCanarySvc = true } + if dRule != nil { + if dRule.StableSubsetName != "" && r.Destination.Subset == dRule.StableSubsetName { + hasStableSubset = true + } + if dRule.CanarySubsetName != "" && r.Destination.Subset == dRule.CanarySubsetName { + hasCanarySubset = true + } + } } - if !hasCanarySvc { - return fmt.Errorf("Canary Service '%s' not found in route", canarySvc) - } - if !hasStableSvc { - return fmt.Errorf("Stable Service '%s' not found in route", stableSvc) + if dRule != nil { + if !hasCanarySubset { + return fmt.Errorf("Canary DestinationRule subset '%s' not found in route", dRule.CanarySubsetName) + } + if !hasStableSubset { + return fmt.Errorf("Stable DestinationRule subset '%s' not found in route", dRule.StableSubsetName) + } + } else { + if !hasCanarySvc { + return fmt.Errorf("Canary Service '%s' not found in route", canarySvc) + } + if !hasStableSvc { + return fmt.Errorf("Stable Service '%s' not found in route", stableSvc) + } } return nil } - -// Structs below describe fields within Istio's VirtualService that the Rollout needs to modify - -// Destination fields within the destination struct of the Virtual Service that the controller modifies -type destination struct { - Host string `json:"host,omitempty"` -} - -// route fields within the route struct of the Virtual Service that the controller modifies -type route struct { - // Destination holds the destination struct of the virtual service - Destination destination `json:"destination,omitempty"` - // Weight holds the destination struct of the virtual service - Weight int64 `json:"weight,omitempty"` -} - -// httpRoute fields within the HTTP struct of the Virtual Service that the controller modifies -type HttpRoute struct { - Name string `json:"name,omitempty"` - Route []route `json:"route,omitempty"` -} diff --git a/rollout/trafficrouting/istio/istio_test.go b/rollout/trafficrouting/istio/istio_test.go index fe07789898..8fa0e88ed1 100644 --- a/rollout/trafficrouting/istio/istio_test.go +++ b/rollout/trafficrouting/istio/istio_test.go @@ -1,47 +1,39 @@ package istio import ( + "context" "fmt" - "strings" "testing" - istioutil "github.com/argoproj/argo-rollouts/utils/istio" - - "k8s.io/client-go/dynamic" - "k8s.io/client-go/dynamic/dynamicinformer" - "k8s.io/client-go/dynamic/dynamiclister" - - "github.com/ghodss/yaml" "github.com/stretchr/testify/assert" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/dynamic/fake" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamicinformer" + "k8s.io/client-go/dynamic/dynamiclister" + dynamicfake "k8s.io/client-go/dynamic/fake" "k8s.io/client-go/tools/record" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + istioutil "github.com/argoproj/argo-rollouts/utils/istio" + unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured" ) -func strToUnstructured(yamlStr string) *unstructured.Unstructured { - obj := make(map[string]interface{}) - yamlStr = strings.ReplaceAll(yamlStr, "\t", " ") - err := yaml.Unmarshal([]byte(yamlStr), &obj) - if err != nil { - panic(err) - } - return &unstructured.Unstructured{Object: obj} -} - -func getVirtualServiceLister(client dynamic.Interface) dynamiclister.Lister { - istioGVR := istioutil.GetIstioGVR("v1alpha3") +func getIstioListers(client dynamic.Interface) (dynamiclister.Lister, dynamiclister.Lister) { + vsvcGVR := istioutil.GetIstioVirtualServiceGVR() + druleGVR := istioutil.GetIstioDestinationRuleGVR() dynamicInformerFactory := dynamicinformer.NewDynamicSharedInformerFactory(client, 0) - istioVirtualServiceInformer := dynamicInformerFactory.ForResource(istioGVR).Informer() + istioVirtualServiceInformer := dynamicInformerFactory.ForResource(vsvcGVR).Informer() + destinationRuleInformer := dynamicInformerFactory.ForResource(druleGVR).Informer() stopCh := make(chan struct{}) dynamicInformerFactory.Start(stopCh) dynamicInformerFactory.WaitForCacheSync(stopCh) close(stopCh) - return dynamiclister.New(istioVirtualServiceInformer.GetIndexer(), istioGVR) + vsvcLister := dynamiclister.New(istioVirtualServiceInformer.GetIndexer(), vsvcGVR) + druleLister := dynamiclister.New(destinationRuleInformer.GetIndexer(), druleGVR) + return vsvcLister, druleLister } func rollout(stableSvc, canarySvc, vsvc string, routes []string) *v1alpha1.Rollout { @@ -101,21 +93,21 @@ spec: weight: 100 - destination: host: canary - weight: 0 + weight: 0 - name: secondary - route: - - destination: - host: 'stable' - weight: 100 - - destination: - host: canary - weight: 0` + route: + - destination: + host: 'stable' + weight: 100 + - destination: + host: canary + weight: 0` func TestReconcileWeightsBaseCase(t *testing.T) { r := &Reconciler{ rollout: rollout("stable", "canary", "vsvc", []string{"primary"}), } - obj := strToUnstructured(regularVsvc) + obj := unstructuredutil.StrToUnstructuredUnsafe(regularVsvc) modifiedObj, _, err := r.reconcileVirtualService(obj, 10) assert.Nil(t, err) assert.NotNil(t, modifiedObj) @@ -133,12 +125,12 @@ func TestReconcileWeightsBaseCase(t *testing.T) { } func TestReconcileUpdateVirtualService(t *testing.T) { - obj := strToUnstructured(regularVsvc) + obj := unstructuredutil.StrToUnstructuredUnsafe(regularVsvc) schema := runtime.NewScheme() - client := fake.NewSimpleDynamicClient(schema, obj) + client := dynamicfake.NewSimpleDynamicClient(schema, obj) ro := rollout("stable", "canary", "vsvc", []string{"primary"}) - vsvcLister := getVirtualServiceLister(client) - r := NewReconciler(ro, client, &record.FakeRecorder{}, "v1alpha3", vsvcLister) + vsvcLister, druleLister := getIstioListers(client) + r := NewReconciler(ro, client, &record.FakeRecorder{}, vsvcLister, druleLister) client.ClearActions() err := r.SetWeight(10) assert.Nil(t, err) @@ -148,11 +140,11 @@ func TestReconcileUpdateVirtualService(t *testing.T) { } func TestReconcileNoChanges(t *testing.T) { - obj := strToUnstructured(regularVsvc) + obj := unstructuredutil.StrToUnstructuredUnsafe(regularVsvc) schema := runtime.NewScheme() - client := fake.NewSimpleDynamicClient(schema, obj) + client := dynamicfake.NewSimpleDynamicClient(schema, obj) ro := rollout("stable", "canary", "vsvc", []string{"primary"}) - r := NewReconciler(ro, client, &record.FakeRecorder{}, "v1alpha3", nil) + r := NewReconciler(ro, client, &record.FakeRecorder{}, nil, nil) err := r.SetWeight(0) assert.Nil(t, err) assert.Len(t, client.Actions(), 1) @@ -160,12 +152,12 @@ func TestReconcileNoChanges(t *testing.T) { } func TestReconcileInvalidValidation(t *testing.T) { - obj := strToUnstructured(regularVsvc) + obj := unstructuredutil.StrToUnstructuredUnsafe(regularVsvc) schema := runtime.NewScheme() - client := fake.NewSimpleDynamicClient(schema, obj) + client := dynamicfake.NewSimpleDynamicClient(schema, obj) ro := rollout("stable", "canary", "vsvc", []string{"route-not-found"}) - vsvcLister := getVirtualServiceLister(client) - r := NewReconciler(ro, client, &record.FakeRecorder{}, "v1alpha3", vsvcLister) + vsvcLister, druleLister := getIstioListers(client) + r := NewReconciler(ro, client, &record.FakeRecorder{}, vsvcLister, druleLister) client.ClearActions() err := r.SetWeight(0) assert.Equal(t, "Route 'route-not-found' is not found", err.Error()) @@ -173,10 +165,10 @@ func TestReconcileInvalidValidation(t *testing.T) { func TestReconcileVirtualServiceNotFound(t *testing.T) { schema := runtime.NewScheme() - client := fake.NewSimpleDynamicClient(schema) + client := dynamicfake.NewSimpleDynamicClient(schema) ro := rollout("stable", "canary", "vsvc", []string{"primary"}) - vsvcLister := getVirtualServiceLister(client) - r := NewReconciler(ro, client, &record.FakeRecorder{}, "v1alpha3", vsvcLister) + vsvcLister, druleLister := getIstioListers(client) + r := NewReconciler(ro, client, &record.FakeRecorder{}, vsvcLister, druleLister) client.ClearActions() err := r.SetWeight(10) assert.NotNil(t, err) @@ -185,9 +177,9 @@ func TestReconcileVirtualServiceNotFound(t *testing.T) { func TestType(t *testing.T) { schema := runtime.NewScheme() - client := fake.NewSimpleDynamicClient(schema) + client := dynamicfake.NewSimpleDynamicClient(schema) ro := rollout("stable", "canary", "vsvc", []string{"primary"}) - r := NewReconciler(ro, client, &record.FakeRecorder{}, "v1alpha3", nil) + r := NewReconciler(ro, client, &record.FakeRecorder{}, nil, nil) assert.Equal(t, Type, r.Type()) } @@ -245,10 +237,10 @@ func TestValidateHTTPRoutes(t *testing.T) { }, } } - httpRoutes := []HttpRoute{{ + httpRoutes := []VirtualServiceHTTPRoute{{ Name: "test", - Route: []route{{ - Destination: destination{ + Route: []VirtualServiceHTTPRouteDestination{{ + Destination: VirtualServiceDestination{ Host: "stable", }, }}, @@ -257,12 +249,12 @@ func TestValidateHTTPRoutes(t *testing.T) { err := ValidateHTTPRoutes(rollout, httpRoutes) assert.Equal(t, fmt.Errorf("Route 'test' does not have exactly two routes"), err) - httpRoutes[0].Route = []route{{ - Destination: destination{ + httpRoutes[0].Route = []VirtualServiceHTTPRouteDestination{{ + Destination: VirtualServiceDestination{ Host: "stable", }, }, { - Destination: destination{ + Destination: VirtualServiceDestination{ Host: "canary", }, }} @@ -276,57 +268,231 @@ func TestValidateHTTPRoutes(t *testing.T) { } func TestValidateHosts(t *testing.T) { - hr := HttpRoute{ + hr := VirtualServiceHTTPRoute{ Name: "test", - Route: []route{{ - Destination: destination{ + Route: []VirtualServiceHTTPRouteDestination{{ + Destination: VirtualServiceDestination{ Host: "stable", }, }}, } - err := validateHosts(hr, "stable", "canary") + err := validateVirtualServiceHTTPRouteDestinations(hr, "stable", "canary", nil) assert.Equal(t, fmt.Errorf("Route 'test' does not have exactly two routes"), err) - hr.Route = []route{{ - Destination: destination{ + hr.Route = []VirtualServiceHTTPRouteDestination{{ + Destination: VirtualServiceDestination{ Host: "stable", }, }, { - Destination: destination{ + Destination: VirtualServiceDestination{ Host: "canary", }, }} - err = validateHosts(hr, "stable", "canary") + err = validateVirtualServiceHTTPRouteDestinations(hr, "stable", "canary", nil) assert.Nil(t, err) - err = validateHosts(hr, "not-found-stable", "canary") + err = validateVirtualServiceHTTPRouteDestinations(hr, "not-found-stable", "canary", nil) assert.Equal(t, fmt.Errorf("Stable Service 'not-found-stable' not found in route"), err) - err = validateHosts(hr, "stable", "not-found-canary") + err = validateVirtualServiceHTTPRouteDestinations(hr, "stable", "not-found-canary", nil) assert.Equal(t, fmt.Errorf("Canary Service 'not-found-canary' not found in route"), err) } -func TestGetRolloutVirtualServiceKeys(t *testing.T) { - ro := &v1alpha1.Rollout{ +func TestValidateHTTPRoutesSubsets(t *testing.T) { + rollout := &v1alpha1.Rollout{ + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{ + TrafficRouting: &v1alpha1.RolloutTrafficRouting{ + Istio: &v1alpha1.IstioTrafficRouting{ + VirtualService: v1alpha1.IstioVirtualService{ + Routes: []string{"primary"}, + }, + DestinationRule: &v1alpha1.IstioDestinationRule{ + Name: "subset", + CanarySubsetName: "canary", + StableSubsetName: "stable", + }, + }, + }, + }, + }, + }, + } + httpRoutes := []VirtualServiceHTTPRoute{{ + Name: "primary", + Route: []VirtualServiceHTTPRouteDestination{ + { + Destination: VirtualServiceDestination{ + Host: "rollout", + Subset: "stable", + }, + }, + { + Destination: VirtualServiceDestination{ + Host: "rollout", + Subset: "canary", + }, + }, + }, + }} + + { + // the good case + err := ValidateHTTPRoutes(rollout, httpRoutes) + assert.NoError(t, err) + } + { + // the stable subset doesnt exist + rollout = rollout.DeepCopy() + rollout.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule.StableSubsetName = "doesntexist" + err := ValidateHTTPRoutes(rollout, httpRoutes) + assert.EqualError(t, err, "Stable DestinationRule subset 'doesntexist' not found in route") + } + { + // the canary subset doesnt exist + rollout = rollout.DeepCopy() + rollout.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule.CanarySubsetName = "doesntexist" + err := ValidateHTTPRoutes(rollout, httpRoutes) + assert.EqualError(t, err, "Canary DestinationRule subset 'doesntexist' not found in route") + } +} + +func rolloutWithDestinationRule() *v1alpha1.Rollout { + return &v1alpha1.Rollout{ ObjectMeta: metav1.ObjectMeta{ - Name: "foo", + Name: "rollout", Namespace: metav1.NamespaceDefault, }, Spec: v1alpha1.RolloutSpec{ - Strategy: v1alpha1.RolloutStrategy{}, + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{ + TrafficRouting: &v1alpha1.RolloutTrafficRouting{ + Istio: &v1alpha1.IstioTrafficRouting{ + VirtualService: v1alpha1.IstioVirtualService{ + Routes: []string{"primary"}, + }, + DestinationRule: &v1alpha1.IstioDestinationRule{ + Name: "istio-destrule", + CanarySubsetName: "canary", + StableSubsetName: "stable", + }, + }, + }, + }, + }, }, } - assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) - ro.Spec.Strategy.Canary = &v1alpha1.CanaryStrategy{} - assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) - ro.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{} - assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) - ro.Spec.Strategy.Canary.TrafficRouting.Istio = &v1alpha1.IstioTrafficRouting{ - VirtualService: v1alpha1.IstioVirtualService{}, - } - assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) - ro.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Name = "test" - keys := GetRolloutVirtualServiceKeys(ro) - assert.Len(t, keys, 1) - assert.Equal(t, keys[0], "default/test") +} + +// TestUpdateHashWithListers verifies behavior of UpdateHash when using informers/listers +func TestUpdateHashWithListers(t *testing.T) { + ro := rolloutWithDestinationRule() + obj := unstructuredutil.StrToUnstructuredUnsafe(` +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-destrule + namespace: default +spec: + subsets: + - name: stable + - name: canary +`) + client := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme(), obj) + vsvcLister, druleLister := getIstioListers(client) + r := NewReconciler(ro, client, &record.FakeRecorder{}, vsvcLister, druleLister) + client.ClearActions() + + err := r.UpdateHash("abc123", "def456") + assert.NoError(t, err) + actions := client.Actions() + assert.Len(t, actions, 1) + assert.Equal(t, "update", actions[0].GetVerb()) + + dRuleUn, err := client.Resource(istioutil.GetIstioDestinationRuleGVR()).Namespace(r.rollout.Namespace).Get(context.TODO(), "istio-destrule", metav1.GetOptions{}) + assert.NoError(t, err) + _, dRule, _, err := unstructuredToDestinationRules(dRuleUn) + assert.NoError(t, err) + assert.Equal(t, dRule.Annotations[v1alpha1.ManagedByRolloutsKey], "rollout") + assert.Equal(t, dRule.Spec.Subsets[0].Labels[v1alpha1.DefaultRolloutUniqueLabelKey], "def456") + assert.Equal(t, dRule.Spec.Subsets[1].Labels[v1alpha1.DefaultRolloutUniqueLabelKey], "abc123") +} + +// TestUpdateHashNoChange verifies we don't make any API calls when there are no changes necessary to the destinationRule +func TestUpdateHashNoChange(t *testing.T) { + ro := rolloutWithDestinationRule() + obj := unstructuredutil.StrToUnstructuredUnsafe(` +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-destrule + namespace: default + annotations: + argo-rollouts.argoproj.io/managed-by-rollouts: rollout +spec: + subsets: + - name: stable + labels: + rollouts-pod-template-hash: def456 + - name: canary + labels: + rollouts-pod-template-hash: abc123 +`) + client := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme(), obj) + vsvcLister, druleLister := getIstioListers(client) + r := NewReconciler(ro, client, &record.FakeRecorder{}, vsvcLister, druleLister) + client.ClearActions() + + err := r.UpdateHash("abc123", "def456") + assert.NoError(t, err) + actions := client.Actions() + assert.Len(t, actions, 0) +} + +// TestUpdateHashWithListers verifies behavior of UpdateHash when we do not yet have a lister/informer +func TestUpdateHashWithoutListers(t *testing.T) { + ro := rolloutWithDestinationRule() + obj := unstructuredutil.StrToUnstructuredUnsafe(` +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-destrule + namespace: default +spec: + subsets: + - name: stable + - name: canary +`) + client := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme(), obj) + r := NewReconciler(ro, client, &record.FakeRecorder{}, nil, nil) + client.ClearActions() + + err := r.UpdateHash("abc123", "def456") + assert.NoError(t, err) + actions := client.Actions() + assert.Len(t, actions, 2) + assert.Equal(t, "get", actions[0].GetVerb()) + assert.Equal(t, "update", actions[1].GetVerb()) + + dRuleUn, err := client.Resource(istioutil.GetIstioDestinationRuleGVR()).Namespace(r.rollout.Namespace).Get(context.TODO(), "istio-destrule", metav1.GetOptions{}) + assert.NoError(t, err) + _, dRule, _, err := unstructuredToDestinationRules(dRuleUn) + assert.NoError(t, err) + assert.Equal(t, dRule.Annotations[v1alpha1.ManagedByRolloutsKey], "rollout") + assert.Equal(t, dRule.Spec.Subsets[0].Labels[v1alpha1.DefaultRolloutUniqueLabelKey], "def456") + assert.Equal(t, dRule.Spec.Subsets[1].Labels[v1alpha1.DefaultRolloutUniqueLabelKey], "abc123") +} + +func TestUpdateHashDestinationRuleNotFound(t *testing.T) { + ro := rolloutWithDestinationRule() + client := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme()) + vsvcLister, druleLister := getIstioListers(client) + r := NewReconciler(ro, client, &record.FakeRecorder{}, vsvcLister, druleLister) + client.ClearActions() + + err := r.UpdateHash("abc123", "def456") + actions := client.Actions() + assert.Len(t, actions, 0) + assert.EqualError(t, err, "destinationrules.networking.istio.io \"istio-destrule\" not found") } diff --git a/rollout/trafficrouting/istio/istio_types.go b/rollout/trafficrouting/istio/istio_types.go new file mode 100644 index 0000000000..d8e605cfd0 --- /dev/null +++ b/rollout/trafficrouting/istio/istio_types.go @@ -0,0 +1,50 @@ +package istio + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VirtualService is an Istio VirtualService containing only the fields which we care about +type VirtualService struct { + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec VirtualServiceSpec `json:"spec,omitempty"` +} + +type VirtualServiceSpec struct { + HTTP []VirtualServiceHTTPRoute `json:"http,omitempty"` +} + +// VirtualServiceHTTPRoute is a route in a VirtualService +type VirtualServiceHTTPRoute struct { + Name string `json:"name,omitempty"` + Route []VirtualServiceHTTPRouteDestination `json:"route,omitempty"` +} + +// VirtualServiceHTTPRouteDestination is a destination within an VirtualServiceHTTPRoute +type VirtualServiceHTTPRouteDestination struct { + // Destination holds the destination struct of the virtual service + Destination VirtualServiceDestination `json:"destination,omitempty"` + // Weight holds the destination struct of the virtual service + Weight int64 `json:"weight,omitempty"` +} + +// Destination fields within the VirtualServiceDestination struct of the Virtual Service that the controller modifies +type VirtualServiceDestination struct { + Host string `json:"host,omitempty"` + Subset string `json:"subset,omitempty"` +} + +// DestinationRule is an Istio DestinationRule containing only the fields which we care about +type DestinationRule struct { + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec DestinationRuleSpec `json:"spec,omitempty"` +} + +type DestinationRuleSpec struct { + Subsets []Subset `json:"subsets,omitempty"` +} + +type Subset struct { + Name string `json:"name,omitempty"` + Labels map[string]string `json:"labels,omitempty"` +} diff --git a/rollout/trafficrouting/nginx/nginx.go b/rollout/trafficrouting/nginx/nginx.go index a616c93833..fa47e7dd6f 100644 --- a/rollout/trafficrouting/nginx/nginx.go +++ b/rollout/trafficrouting/nginx/nginx.go @@ -230,3 +230,8 @@ func (r *Reconciler) SetWeight(desiredWeight int32) error { func (r *Reconciler) VerifyWeight(desiredWeight int32) (bool, error) { return true, nil } + +// UpdateHash informs a traffic routing reconciler about new canary/stable pod hashes +func (r *Reconciler) UpdateHash(canaryHash, stableHash string) error { + return nil +} diff --git a/rollout/trafficrouting/smi/smi.go b/rollout/trafficrouting/smi/smi.go index c973b30380..55fccc63a5 100644 --- a/rollout/trafficrouting/smi/smi.go +++ b/rollout/trafficrouting/smi/smi.go @@ -18,6 +18,7 @@ import ( "k8s.io/client-go/tools/record" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/defaults" "github.com/argoproj/argo-rollouts/utils/diff" logutil "github.com/argoproj/argo-rollouts/utils/log" ) @@ -33,7 +34,6 @@ type ReconcilerConfig struct { Client smiclientset.Interface Recorder record.EventRecorder ControllerKind schema.GroupVersionKind - ApiVersion string } // Reconciler holds required fields to reconcile SMI resources @@ -52,6 +52,12 @@ type VersionedTrafficSplits struct { ts3 *smiv1alpha3.TrafficSplit } +var smiAPIVersion = defaults.DefaultSMITrafficSplitVersion + +func SetSMIAPIVersion(apiVersion string) { + smiAPIVersion = apiVersion +} + // NewReconciler returns a reconciler struct that brings the SMI into the desired state func NewReconciler(cfg ReconcilerConfig) (*Reconciler, error) { r := &Reconciler{ @@ -59,7 +65,7 @@ func NewReconciler(cfg ReconcilerConfig) (*Reconciler, error) { log: logutil.WithRollout(cfg.Rollout), } ctx := context.TODO() - switch apiVersion := r.cfg.ApiVersion; apiVersion { + switch smiAPIVersion { case "v1alpha1": r.getTrafficSplit = func(trafficSplitName string) (VersionedTrafficSplits, error) { ts1, err := r.cfg.Client.SplitV1alpha1().TrafficSplits(r.cfg.Rollout.Namespace).Get(ctx, trafficSplitName, metav1.GetOptions{}) @@ -169,7 +175,7 @@ func NewReconciler(cfg ReconcilerConfig) (*Reconciler, error) { return metav1.IsControlledBy(ts.ts3, r.cfg.Rollout) } default: - err := fmt.Errorf("Unsupported TrafficSplit API version `%s`", apiVersion) + err := fmt.Errorf("Unsupported TrafficSplit API version `%s`", smiAPIVersion) return nil, err } return r, nil @@ -239,7 +245,7 @@ func (r *Reconciler) generateTrafficSplits(trafficSplitName string, desiredWeigh objectMeta := objectMeta(trafficSplitName, r.cfg.Rollout, r.cfg.ControllerKind) - switch apiVersion := r.cfg.ApiVersion; apiVersion { + switch smiAPIVersion { case "v1alpha1": trafficSplits.ts1 = trafficSplitV1Alpha1(r.cfg.Rollout, objectMeta, rootSvc, desiredWeight) case "v1alpha2": @@ -316,3 +322,8 @@ func trafficSplitV1Alpha3(ro *v1alpha1.Rollout, objectMeta metav1.ObjectMeta, ro }, } } + +// UpdateHash informs a traffic routing reconciler about new canary/stable pod hashes +func (r *Reconciler) UpdateHash(canaryHash, stableHash string) error { + return nil +} diff --git a/rollout/trafficrouting/smi/smi_test.go b/rollout/trafficrouting/smi/smi_test.go index da05262580..faccdd7d92 100644 --- a/rollout/trafficrouting/smi/smi_test.go +++ b/rollout/trafficrouting/smi/smi_test.go @@ -22,6 +22,7 @@ import ( "k8s.io/client-go/tools/record" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/defaults" ) func fakeRollout(stableSvc, canarySvc, rootSvc string, trafficSplitName string) *v1alpha1.Rollout { @@ -55,7 +56,6 @@ func TestType(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha1", }) assert.Nil(t, err) assert.Equal(t, Type, r.Type()) @@ -64,12 +64,13 @@ func TestType(t *testing.T) { func TestUnsupportedTrafficSplitApiVersionError(t *testing.T) { ro := fakeRollout("stable-service", "canary-service", "root-service", "traffic-split-name") client := fake.NewSimpleClientset() + SetSMIAPIVersion("does-not-exist") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) _, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "does-not-exist", }) assert.EqualError(t, err, "Unsupported TrafficSplit API version `does-not-exist`") } @@ -85,7 +86,6 @@ func TestReconcileCreateNewTrafficSplit(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha1", }) assert.Nil(t, err) @@ -113,12 +113,13 @@ func TestReconcileCreateNewTrafficSplit(t *testing.T) { t.Run("v1alpha2", func(t *testing.T) { ro := fakeRollout("stable-service", "canary-service", "root-service", "traffic-split-name") client := fake.NewSimpleClientset() + SetSMIAPIVersion("v1alpha2") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) r, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha2", }) assert.Nil(t, err) @@ -143,12 +144,13 @@ func TestReconcileCreateNewTrafficSplit(t *testing.T) { t.Run("v1alpha3", func(t *testing.T) { ro := fakeRollout("stable-service", "canary-service", "root-service", "traffic-split-name") client := fake.NewSimpleClientset() + SetSMIAPIVersion("v1alpha3") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) r, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha3", }) assert.Nil(t, err) @@ -183,7 +185,6 @@ func TestReconcilePatchExistingTrafficSplit(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha1", }) assert.Nil(t, err) @@ -213,12 +214,13 @@ func TestReconcilePatchExistingTrafficSplit(t *testing.T) { t.Run("v1alpha2", func(t *testing.T) { ts2 := trafficSplitV1Alpha2(ro, objectMeta, "root-service", int32(10)) client := fake.NewSimpleClientset(ts2) + SetSMIAPIVersion("v1alpha2") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) r, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha2", }) assert.Nil(t, err) @@ -244,12 +246,13 @@ func TestReconcilePatchExistingTrafficSplit(t *testing.T) { t.Run("v1alpha3", func(t *testing.T) { ts3 := trafficSplitV1Alpha3(ro, objectMeta, "root-service", int32(10)) client := fake.NewSimpleClientset(ts3) + SetSMIAPIVersion("v1alpha3") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) r, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha3", }) assert.Nil(t, err) @@ -285,7 +288,6 @@ func TestReconcilePatchExistingTrafficSplitNoChange(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha1", }) assert.Nil(t, err) @@ -305,12 +307,13 @@ func TestReconcilePatchExistingTrafficSplitNoChange(t *testing.T) { objMeta := objectMeta("traffic-split-v1alpha2", ro, schema.GroupVersionKind{}) ts2 := trafficSplitV1Alpha2(ro, objMeta, "root-service", int32(10)) client := fake.NewSimpleClientset(ts2) + SetSMIAPIVersion("v1alpha2") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) r, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha2", }) assert.Nil(t, err) @@ -329,12 +332,13 @@ func TestReconcilePatchExistingTrafficSplitNoChange(t *testing.T) { objMeta := objectMeta("traffic-split-v1alpha3", ro, schema.GroupVersionKind{}) ts3 := trafficSplitV1Alpha3(ro, objMeta, "root-service", int32(10)) client := fake.NewSimpleClientset(ts3) + SetSMIAPIVersion("v1alpha3") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) r, err := NewReconciler(ReconcilerConfig{ Rollout: ro, Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha3", }) assert.Nil(t, err) @@ -357,7 +361,6 @@ func TestReconcileGetTrafficSplitError(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha1", }) assert.Nil(t, err) //Throw error when client tries to get TrafficSplit @@ -384,7 +387,6 @@ func TestReconcileRolloutDoesNotOwnTrafficSplitError(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha1", }) assert.Nil(t, err) @@ -395,6 +397,8 @@ func TestReconcileRolloutDoesNotOwnTrafficSplitError(t *testing.T) { t.Run("v1alpha2", func(t *testing.T) { ts2 := trafficSplitV1Alpha2(ro, objMeta, "root-service", int32(10)) ts2.OwnerReferences = nil + SetSMIAPIVersion("v1alpha2") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) client := fake.NewSimpleClientset(ts2) r, err := NewReconciler(ReconcilerConfig{ @@ -402,7 +406,6 @@ func TestReconcileRolloutDoesNotOwnTrafficSplitError(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha2", }) assert.Nil(t, err) @@ -413,6 +416,8 @@ func TestReconcileRolloutDoesNotOwnTrafficSplitError(t *testing.T) { t.Run("v1alpha3", func(t *testing.T) { ts3 := trafficSplitV1Alpha3(ro, objMeta, "root-service", int32(10)) ts3.OwnerReferences = nil + SetSMIAPIVersion("v1alpha3") + defer SetSMIAPIVersion(defaults.DefaultSMITrafficSplitVersion) client := fake.NewSimpleClientset(ts3) r, err := NewReconciler(ReconcilerConfig{ @@ -420,7 +425,6 @@ func TestReconcileRolloutDoesNotOwnTrafficSplitError(t *testing.T) { Client: client, Recorder: &record.FakeRecorder{}, ControllerKind: schema.GroupVersionKind{}, - ApiVersion: "v1alpha3", }) assert.Nil(t, err) diff --git a/rollout/trafficrouting_test.go b/rollout/trafficrouting_test.go index 1f3dddf265..e8903e08d2 100644 --- a/rollout/trafficrouting_test.go +++ b/rollout/trafficrouting_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/dynamic/dynamicinformer" "k8s.io/client-go/dynamic/dynamiclister" @@ -22,6 +21,7 @@ import ( "github.com/argoproj/argo-rollouts/rollout/trafficrouting/nginx" "github.com/argoproj/argo-rollouts/rollout/trafficrouting/smi" "github.com/argoproj/argo-rollouts/utils/conditions" + istioutil "github.com/argoproj/argo-rollouts/utils/istio" logutil "github.com/argoproj/argo-rollouts/utils/log" ) @@ -31,6 +31,7 @@ func newFakeTrafficRoutingReconciler() *mocks.TrafficRoutingReconciler { r.On("Type").Return("fake") r.On("SetWeight", mock.Anything).Return(nil) r.On("VerifyWeight", mock.Anything).Return(true, nil) + r.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) return &r } @@ -80,6 +81,7 @@ func TestReconcileTrafficRoutingSetWeightErr(t *testing.T) { f, ro := newTrafficWeightFixture(t) defer f.Close() f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) f.fakeTrafficRouting.On("SetWeight", mock.Anything).Return(errors.New("Error message")) f.runExpectError(getKey(ro, t), true) } @@ -89,6 +91,7 @@ func TestReconcileTrafficRoutingVerifyWeightErr(t *testing.T) { f, ro := newTrafficWeightFixture(t) defer f.Close() f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) f.fakeTrafficRouting.On("SetWeight", mock.Anything).Return(nil) f.fakeTrafficRouting.On("VerifyWeight", mock.Anything).Return(false, errors.New("Error message")) f.runExpectError(getKey(ro, t), true) @@ -99,6 +102,7 @@ func TestReconcileTrafficRoutingVerifyWeightFalse(t *testing.T) { f, ro := newTrafficWeightFixture(t) defer f.Close() f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) f.fakeTrafficRouting.On("SetWeight", mock.Anything).Return(nil) f.fakeTrafficRouting.On("VerifyWeight", mock.Anything).Return(false, nil) c, i, k8sI := f.newController(noResyncPeriodFunc) @@ -152,6 +156,7 @@ func TestRolloutUseDesiredWeight(t *testing.T) { f.expectPatchRolloutAction(r2) f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) f.fakeTrafficRouting.On("SetWeight", mock.Anything).Return(func(desiredWeight int32) error { // make sure SetWeight was called with correct value assert.Equal(t, int32(10), desiredWeight) @@ -200,6 +205,7 @@ func TestRolloutUsePreviousSetWeight(t *testing.T) { f.expectPatchRolloutAction(r2) f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) f.fakeTrafficRouting.On("SetWeight", mock.Anything).Return(func(desiredWeight int32) error { // make sure SetWeight was called with correct value assert.Equal(t, int32(10), desiredWeight) @@ -240,6 +246,7 @@ func TestRolloutSetWeightToZeroWhenFullyRolledOut(t *testing.T) { f.expectPatchRolloutAction(r1) f.fakeTrafficRouting = newUnmockedFakeTrafficRoutingReconciler() + f.fakeTrafficRouting.On("UpdateHash", mock.Anything, mock.Anything).Return(nil) f.fakeTrafficRouting.On("SetWeight", mock.Anything).Return(func(desiredWeight int32) error { // make sure SetWeight was called with correct value assert.Equal(t, int32(0), desiredWeight) @@ -251,9 +258,12 @@ func TestRolloutSetWeightToZeroWhenFullyRolledOut(t *testing.T) { func TestNewTrafficRoutingReconciler(t *testing.T) { rc := Controller{} - gvk := schema.ParseGroupResource("virtualservices.networking.istio.io").WithVersion("v1alpha3") dynamicInformerFactory := dynamicinformer.NewDynamicSharedInformerFactory(dynamicfake.NewSimpleDynamicClient(runtime.NewScheme()), 0) - rc.istioVirtualServiceInformer = dynamicInformerFactory.ForResource(gvk).Informer() + vsvcGVR := istioutil.GetIstioVirtualServiceGVR() + druleGVR := istioutil.GetIstioDestinationRuleGVR() + rc.IstioController = &istio.IstioController{} + rc.IstioController.VirtualServiceInformer = dynamicInformerFactory.ForResource(vsvcGVR).Informer() + rc.IstioController.DestinationRuleInformer = dynamicInformerFactory.ForResource(druleGVR).Informer() steps := []v1alpha1.CanaryStep{ { @@ -303,7 +313,7 @@ func TestNewTrafficRoutingReconciler(t *testing.T) { dynamicInformerFactory.Start(stopCh) dynamicInformerFactory.WaitForCacheSync(stopCh) close(stopCh) - rc.istioVirtualServiceLister = dynamiclister.New(rc.istioVirtualServiceInformer.GetIndexer(), gvk) + rc.IstioController.VirtualServiceLister = dynamiclister.New(rc.IstioController.VirtualServiceInformer.GetIndexer(), vsvcGVR) r := newCanaryRollout("foo", 10, nil, steps, pointer.Int32Ptr(1), intstr.FromInt(1), intstr.FromInt(0)) r.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{ Istio: &v1alpha1.IstioTrafficRouting{}, @@ -345,22 +355,8 @@ func TestNewTrafficRoutingReconciler(t *testing.T) { assert.NotNil(t, networkReconciler) assert.Equal(t, alb.Type, networkReconciler.Type()) } - { - r := newCanaryRollout("foo", 10, nil, steps, pointer.Int32Ptr(1), intstr.FromInt(1), intstr.FromInt(0)) - r.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{ - SMI: &v1alpha1.SMITrafficRouting{}, - } - roCtx := &rolloutContext{ - rollout: r, - log: logutil.WithRollout(r), - } - _, err := rc.NewTrafficRoutingReconciler(roCtx) - assert.NotNil(t, err) - assert.EqualError(t, err, "Unsupported TrafficSplit API version ``") - } { tsController := Controller{} - tsController.defaultTrafficSplitVersion = "v1alpha1" r := newCanaryRollout("foo", 10, nil, steps, pointer.Int32Ptr(1), intstr.FromInt(1), intstr.FromInt(0)) r.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{ SMI: &v1alpha1.SMITrafficRouting{}, diff --git a/service/service.go b/service/service.go index 861a0591fd..47d0ac40d9 100644 --- a/service/service.go +++ b/service/service.go @@ -8,6 +8,7 @@ import ( log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" patchtypes "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" @@ -31,8 +32,7 @@ import ( const ( // serviceIndexName is the index by which Service resources are cached serviceIndexName = "byService" - removeSelectorPatch = `{ - "metadata": { + removeSelectorPatch = `{"metadata": { "annotations": { "` + v1alpha1.ManagedByRolloutsKey + `": null } @@ -144,6 +144,9 @@ func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error { return nil } +// syncService detects a change to a Service which is managed by a Rollout, and enqueues the +// related rollout for reconciliation. If no rollout is referencing the Service, then removes +// any injected fields in the service (e.g. rollouts-pod-template-hash and managed-by annotation) func (c *Controller) syncService(key string) error { ctx := context.TODO() namespace, name, err := cache.SplitMetaNamespaceKey(key) @@ -152,20 +155,25 @@ func (c *Controller) syncService(key string) error { } svc, err := c.servicesLister.Services(namespace).Get(name) if errors.IsNotFound(err) { - log.WithField(logutil.ServiceKey, key).Infof("Service %v has been deleted", key) return nil } if err != nil { return err } - // Return early if the svc does not have a hash selector if _, hasHashSelector := svc.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]; !hasHashSelector { return nil } + // Handles case where the controller is not watching all Rollouts in the cluster due to instance-ids by making an // API call to get Rollout and confirm it references the service. rolloutName, hasManagedBy := serviceutil.HasManagedByAnnotation(svc) + logCtx := log.WithField(logutil.ServiceKey, svc.Name).WithField(logutil.NamespaceKey, svc.Namespace) + if rolloutName != "" { + logCtx = logCtx.WithField(logutil.RolloutKey, rolloutName) + } + logCtx.Infof("syncing service") + if hasManagedBy { rollout, err := c.argoprojclientset.ArgoprojV1alpha1().Rollouts(svc.Namespace).Get(ctx, rolloutName, metav1.GetOptions{}) if err == nil { @@ -189,20 +197,30 @@ func (c *Controller) syncService(key string) error { } } - updatedSvc := svc.DeepCopy() - patch := generateRemovePatch(updatedSvc) - _, err = c.kubeclientset.CoreV1().Services(updatedSvc.Namespace).Patch(ctx, updatedSvc.Name, patchtypes.MergePatchType, []byte(patch), metav1.PatchOptions{}) - if errors.IsNotFound(err) { - return nil + patch := generateRemovePatch(svc) + if patch != "" { + _, err = c.kubeclientset.CoreV1().Services(svc.Namespace).Patch(ctx, svc.Name, patchtypes.MergePatchType, []byte(patch), metav1.PatchOptions{}) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return err + } + logCtx.Infof("cleaned service") } - return err + return nil } +// generateRemovePatch generates a patch which clears injected fields the controller may have injected +// against the Service func generateRemovePatch(svc *corev1.Service) string { if _, ok := svc.Annotations[v1alpha1.ManagedByRolloutsKey]; ok { return removeSelectorAndManagedByPatch } - return removeSelectorPatch + if _, ok := svc.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]; ok { + return removeSelectorPatch + } + return "" } // getRolloutsByService returns all rollouts which are referencing specified service diff --git a/service/service_test.go b/service/service_test.go index cb59f5452c..a1a6f2b0b5 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -38,6 +38,14 @@ func newService(name string, port int, selector map[string]string) *corev1.Servi func TestGenerateRemovePatch(t *testing.T) { svc := &corev1.Service{} + assert.Equal(t, "", generateRemovePatch(svc)) + svc = &corev1.Service{ + Spec: corev1.ServiceSpec{ + Selector: map[string]string{ + v1alpha1.DefaultRolloutUniqueLabelKey: "abc123", + }, + }, + } assert.Equal(t, removeSelectorPatch, generateRemovePatch(svc)) svc.Annotations = map[string]string{ v1alpha1.ManagedByRolloutsKey: "test", diff --git a/test/e2e/crds/README.md b/test/e2e/crds/README.md new file mode 100644 index 0000000000..f427de81a7 --- /dev/null +++ b/test/e2e/crds/README.md @@ -0,0 +1,3 @@ +# E2E CRDs + +This directory contains CRDs to install for e2e testing \ No newline at end of file diff --git a/test/e2e/crds/istio.yaml b/test/e2e/crds/istio.yaml new file mode 100644 index 0000000000..7491f5b3d5 --- /dev/null +++ b/test/e2e/crds/istio.yaml @@ -0,0 +1,3448 @@ +# DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: destinationrules.networking.istio.io +spec: + additionalPrinterColumns: + - JSONPath: .spec.host + description: The name of a service from the service registry + name: Host + type: string + - JSONPath: .metadata.creationTimestamp + description: 'CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: DestinationRule + listKind: DestinationRuleList + plural: destinationrules + shortNames: + - dr + singular: destinationrule + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting load balancing, outlier detection, + etc. See more details at: https://istio.io/docs/reference/config/networking/destination-rule.html' + properties: + exportTo: + description: A list of namespaces to which this destination rule is + exported. + items: + format: string + type: string + type: array + host: + description: The name of a service from the service registry. + format: string + type: string + subsets: + items: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + name: + description: Name of the subset. + format: string + type: string + trafficPolicy: + description: Traffic policies that apply to this subset. + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should + be upgraded to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP requests + to a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection + pool connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per connection + to a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + useClientProtocol: + description: If set to true, client protocol will + be preserved while initiating connection to backend. + type: boolean + type: object + tcp: + description: Settings common to both HTTP and TCP upstream + connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections + to a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on the socket + to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive + probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer algorithms. + oneOf: + - not: + anyOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + httpQueryParameterName: + description: Hash based on a specific HTTP query parameter. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + localityLbSetting: + properties: + distribute: + description: 'Optional: only one of distribute or + failover can be set.' + items: + properties: + from: + description: Originating locality, '/' separated, + e.g. + format: string + type: string + to: + additionalProperties: + type: integer + description: Map of upstream localities to traffic + distribution weights. + type: object + type: object + type: array + enabled: + description: enable locality load balancing, this + is DestinationRule-level and will override mesh + wide settings in entirety. + nullable: true + type: boolean + failover: + description: 'Optional: only failover or distribute + can be set.' + items: + properties: + from: + description: Originating region. + format: string + type: string + to: + format: string + type: string + type: object + type: array + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutive5xxErrors: + description: Number of 5xx errors before a host is ejected + from the connection pool. + nullable: true + type: integer + consecutiveErrors: + format: int32 + type: integer + consecutiveGatewayErrors: + description: Number of gateway errors before a host is + ejected from the connection pool. + nullable: true + type: integer + interval: + description: Time interval between ejection sweep analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + portLevelSettings: + description: Traffic policies specific to individual ports. + items: + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should + be upgraded to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP + requests to a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a + backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection + pool connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per + connection to a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + useClientProtocol: + description: If set to true, client protocol + will be preserved while initiating connection + to backend. + type: boolean + type: object + tcp: + description: Settings common to both HTTP and TCP + upstream connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections + to a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on + the socket to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive + probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer + algorithms. + oneOf: + - not: + anyOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + httpQueryParameterName: + description: Hash based on a specific HTTP query + parameter. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + localityLbSetting: + properties: + distribute: + description: 'Optional: only one of distribute + or failover can be set.' + items: + properties: + from: + description: Originating locality, '/' + separated, e.g. + format: string + type: string + to: + additionalProperties: + type: integer + description: Map of upstream localities + to traffic distribution weights. + type: object + type: object + type: array + enabled: + description: enable locality load balancing, + this is DestinationRule-level and will override + mesh wide settings in entirety. + nullable: true + type: boolean + failover: + description: 'Optional: only failover or distribute + can be set.' + items: + properties: + from: + description: Originating region. + format: string + type: string + to: + format: string + type: string + type: object + type: array + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutive5xxErrors: + description: Number of 5xx errors before a host + is ejected from the connection pool. + nullable: true + type: integer + consecutiveErrors: + format: int32 + type: integer + consecutiveGatewayErrors: + description: Number of gateway errors before a host + is ejected from the connection pool. + nullable: true + type: integer + interval: + description: Time interval between ejection sweep + analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + port: + properties: + number: + type: integer + type: object + tls: + description: TLS related settings for connections to + the upstream service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + credentialName: + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server + during TLS handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: array + tls: + description: TLS related settings for connections to the upstream + service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + credentialName: + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server during + TLS handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: object + type: array + trafficPolicy: + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should be upgraded + to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP requests to + a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection pool + connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per connection to + a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + useClientProtocol: + description: If set to true, client protocol will be preserved + while initiating connection to backend. + type: boolean + type: object + tcp: + description: Settings common to both HTTP and TCP upstream connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections to + a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on the socket + to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer algorithms. + oneOf: + - not: + anyOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + httpQueryParameterName: + description: Hash based on a specific HTTP query parameter. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + localityLbSetting: + properties: + distribute: + description: 'Optional: only one of distribute or failover + can be set.' + items: + properties: + from: + description: Originating locality, '/' separated, + e.g. + format: string + type: string + to: + additionalProperties: + type: integer + description: Map of upstream localities to traffic + distribution weights. + type: object + type: object + type: array + enabled: + description: enable locality load balancing, this is DestinationRule-level + and will override mesh wide settings in entirety. + nullable: true + type: boolean + failover: + description: 'Optional: only failover or distribute can + be set.' + items: + properties: + from: + description: Originating region. + format: string + type: string + to: + format: string + type: string + type: object + type: array + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutive5xxErrors: + description: Number of 5xx errors before a host is ejected from + the connection pool. + nullable: true + type: integer + consecutiveErrors: + format: int32 + type: integer + consecutiveGatewayErrors: + description: Number of gateway errors before a host is ejected + from the connection pool. + nullable: true + type: integer + interval: + description: Time interval between ejection sweep analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + portLevelSettings: + description: Traffic policies specific to individual ports. + items: + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should + be upgraded to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP requests + to a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection + pool connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per connection + to a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + useClientProtocol: + description: If set to true, client protocol will + be preserved while initiating connection to backend. + type: boolean + type: object + tcp: + description: Settings common to both HTTP and TCP upstream + connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections + to a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on the socket + to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive + probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer algorithms. + oneOf: + - not: + anyOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + - required: + - simple + - properties: + consistentHash: + oneOf: + - not: + anyOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + - required: + - httpQueryParameterName + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + httpQueryParameterName: + description: Hash based on a specific HTTP query parameter. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + localityLbSetting: + properties: + distribute: + description: 'Optional: only one of distribute or + failover can be set.' + items: + properties: + from: + description: Originating locality, '/' separated, + e.g. + format: string + type: string + to: + additionalProperties: + type: integer + description: Map of upstream localities to traffic + distribution weights. + type: object + type: object + type: array + enabled: + description: enable locality load balancing, this + is DestinationRule-level and will override mesh + wide settings in entirety. + nullable: true + type: boolean + failover: + description: 'Optional: only failover or distribute + can be set.' + items: + properties: + from: + description: Originating region. + format: string + type: string + to: + format: string + type: string + type: object + type: array + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutive5xxErrors: + description: Number of 5xx errors before a host is ejected + from the connection pool. + nullable: true + type: integer + consecutiveErrors: + format: int32 + type: integer + consecutiveGatewayErrors: + description: Number of gateway errors before a host is + ejected from the connection pool. + nullable: true + type: integer + interval: + description: Time interval between ejection sweep analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + port: + properties: + number: + type: integer + type: object + tls: + description: TLS related settings for connections to the upstream + service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + credentialName: + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server during + TLS handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: array + tls: + description: TLS related settings for connections to the upstream + service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + credentialName: + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server during TLS + handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: envoyfilters.networking.istio.io +spec: + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: EnvoyFilter + listKind: EnvoyFilterList + plural: envoyfilters + singular: envoyfilter + preserveUnknownFields: true + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Customizing Envoy configuration generated by Istio. See more + details at: https://istio.io/docs/reference/config/networking/envoy-filter.html' + properties: + configPatches: + description: One or more patches with match conditions. + items: + properties: + applyTo: + enum: + - INVALID + - LISTENER + - FILTER_CHAIN + - NETWORK_FILTER + - HTTP_FILTER + - ROUTE_CONFIGURATION + - VIRTUAL_HOST + - HTTP_ROUTE + - CLUSTER + - EXTENSION_CONFIG + type: string + match: + description: Match on listener/route configuration/cluster. + oneOf: + - not: + anyOf: + - required: + - listener + - required: + - routeConfiguration + - required: + - cluster + - required: + - listener + - required: + - routeConfiguration + - required: + - cluster + properties: + cluster: + description: Match on envoy cluster attributes. + properties: + name: + description: The exact name of the cluster to match. + format: string + type: string + portNumber: + description: The service port for which this cluster was + generated. + type: integer + service: + description: The fully qualified service name for this + cluster. + format: string + type: string + subset: + description: The subset associated with the service. + format: string + type: string + type: object + context: + description: The specific config generation context to match + on. + enum: + - ANY + - SIDECAR_INBOUND + - SIDECAR_OUTBOUND + - GATEWAY + type: string + listener: + description: Match on envoy listener attributes. + properties: + filterChain: + description: Match a specific filter chain in a listener. + properties: + applicationProtocols: + description: Applies only to sidecars. + format: string + type: string + destinationPort: + description: The destination_port value used by a + filter chain's match condition. + type: integer + filter: + description: The name of a specific filter to apply + the patch to. + properties: + name: + description: The filter name to match on. + format: string + type: string + subFilter: + properties: + name: + description: The filter name to match on. + format: string + type: string + type: object + type: object + name: + description: The name assigned to the filter chain. + format: string + type: string + sni: + description: The SNI value used by a filter chain's + match condition. + format: string + type: string + transportProtocol: + description: Applies only to `SIDECAR_INBOUND` context. + format: string + type: string + type: object + name: + description: Match a specific listener by its name. + format: string + type: string + portName: + format: string + type: string + portNumber: + type: integer + type: object + proxy: + description: Match on properties associated with a proxy. + properties: + metadata: + additionalProperties: + format: string + type: string + type: object + proxyVersion: + format: string + type: string + type: object + routeConfiguration: + description: Match on envoy HTTP route configuration attributes. + properties: + gateway: + format: string + type: string + name: + description: Route configuration name to match on. + format: string + type: string + portName: + description: Applicable only for GATEWAY context. + format: string + type: string + portNumber: + type: integer + vhost: + properties: + name: + format: string + type: string + route: + description: Match a specific route within the virtual + host. + properties: + action: + description: Match a route with specific action + type. + enum: + - ANY + - ROUTE + - REDIRECT + - DIRECT_RESPONSE + type: string + name: + format: string + type: string + type: object + type: object + type: object + type: object + patch: + description: The patch to apply along with the operation. + properties: + filterClass: + description: Determines the filter insertion order. + enum: + - UNSPECIFIED + - AUTHN + - AUTHZ + - STATS + type: string + operation: + description: Determines how the patch should be applied. + enum: + - INVALID + - MERGE + - ADD + - REMOVE + - INSERT_BEFORE + - INSERT_AFTER + - INSERT_FIRST + - REPLACE + type: string + value: + description: The JSON config of the object being patched. + type: object + type: object + type: object + type: array + workloadSelector: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: gateways.networking.istio.io +spec: + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: Gateway + listKind: GatewayList + plural: gateways + shortNames: + - gw + singular: gateway + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting edge load balancer. See more details + at: https://istio.io/docs/reference/config/networking/gateway.html' + properties: + selector: + additionalProperties: + format: string + type: string + type: object + servers: + description: A list of server specifications. + items: + properties: + bind: + format: string + type: string + defaultEndpoint: + format: string + type: string + hosts: + description: One or more hosts exposed by this gateway. + items: + format: string + type: string + type: array + name: + description: An optional name of the server, when set must be + unique across all servers. + format: string + type: string + port: + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + targetPort: + type: integer + type: object + tls: + description: Set of TLS related options that govern the server's + behavior. + properties: + caCertificates: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + cipherSuites: + description: 'Optional: If specified, only support the specified + cipher list.' + items: + format: string + type: string + type: array + credentialName: + format: string + type: string + httpsRedirect: + type: boolean + maxProtocolVersion: + description: 'Optional: Maximum TLS protocol version.' + enum: + - TLS_AUTO + - TLSV1_0 + - TLSV1_1 + - TLSV1_2 + - TLSV1_3 + type: string + minProtocolVersion: + description: 'Optional: Minimum TLS protocol version.' + enum: + - TLS_AUTO + - TLSV1_0 + - TLSV1_1 + - TLSV1_2 + - TLSV1_3 + type: string + mode: + enum: + - PASSTHROUGH + - SIMPLE + - MUTUAL + - AUTO_PASSTHROUGH + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `SIMPLE` or `MUTUAL`. + format: string + type: string + serverCertificate: + description: REQUIRED if mode is `SIMPLE` or `MUTUAL`. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + verifyCertificateHash: + items: + format: string + type: string + type: array + verifyCertificateSpki: + items: + format: string + type: string + type: array + type: object + type: object + type: array + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: serviceentries.networking.istio.io +spec: + additionalPrinterColumns: + - JSONPath: .spec.hosts + description: The hosts associated with the ServiceEntry + name: Hosts + type: string + - JSONPath: .spec.location + description: Whether the service is external to the mesh or part of the mesh (MESH_EXTERNAL + or MESH_INTERNAL) + name: Location + type: string + - JSONPath: .spec.resolution + description: Service discovery mode for the hosts (NONE, STATIC, or DNS) + name: Resolution + type: string + - JSONPath: .metadata.creationTimestamp + description: 'CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: ServiceEntry + listKind: ServiceEntryList + plural: serviceentries + shortNames: + - se + singular: serviceentry + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting service registry. See more details + at: https://istio.io/docs/reference/config/networking/service-entry.html' + properties: + addresses: + description: The virtual IP addresses associated with the service. + items: + format: string + type: string + type: array + endpoints: + description: One or more endpoints associated with the service. + items: + properties: + address: + format: string + type: string + labels: + additionalProperties: + format: string + type: string + description: One or more labels associated with the endpoint. + type: object + locality: + description: The locality associated with the endpoint. + format: string + type: string + network: + format: string + type: string + ports: + additionalProperties: + type: integer + description: Set of ports associated with the endpoint. + type: object + serviceAccount: + format: string + type: string + weight: + description: The load balancing weight associated with the endpoint. + type: integer + type: object + type: array + exportTo: + description: A list of namespaces to which this service is exported. + items: + format: string + type: string + type: array + hosts: + description: The hosts associated with the ServiceEntry. + items: + format: string + type: string + type: array + location: + enum: + - MESH_EXTERNAL + - MESH_INTERNAL + type: string + ports: + description: The ports associated with the external service. + items: + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + targetPort: + type: integer + type: object + type: array + resolution: + description: Service discovery mode for the hosts. + enum: + - NONE + - STATIC + - DNS + type: string + subjectAltNames: + items: + format: string + type: string + type: array + workloadSelector: + description: Applicable only for MESH_INTERNAL services. + properties: + labels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: sidecars.networking.istio.io +spec: + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: Sidecar + listKind: SidecarList + plural: sidecars + singular: sidecar + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting network reachability of a sidecar. + See more details at: https://istio.io/docs/reference/config/networking/sidecar.html' + properties: + egress: + items: + properties: + bind: + format: string + type: string + captureMode: + enum: + - DEFAULT + - IPTABLES + - NONE + type: string + hosts: + items: + format: string + type: string + type: array + port: + description: The port associated with the listener. + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + targetPort: + type: integer + type: object + type: object + type: array + ingress: + items: + properties: + bind: + description: The IP to which the listener should be bound. + format: string + type: string + captureMode: + enum: + - DEFAULT + - IPTABLES + - NONE + type: string + defaultEndpoint: + format: string + type: string + port: + description: The port associated with the listener. + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + targetPort: + type: integer + type: object + type: object + type: array + outboundTrafficPolicy: + description: Configuration for the outbound traffic policy. + properties: + egressProxy: + properties: + host: + description: The name of a service from the service registry. + format: string + type: string + port: + description: Specifies the port on the host that is being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + mode: + enum: + - REGISTRY_ONLY + - ALLOW_ANY + type: string + type: object + workloadSelector: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: virtualservices.networking.istio.io +spec: + additionalPrinterColumns: + - JSONPath: .spec.gateways + description: The names of gateways and sidecars that should apply these routes + name: Gateways + type: string + - JSONPath: .spec.hosts + description: The destination hosts to which traffic is being sent + name: Hosts + type: string + - JSONPath: .metadata.creationTimestamp + description: 'CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: VirtualService + listKind: VirtualServiceList + plural: virtualservices + shortNames: + - vs + singular: virtualservice + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting label/content routing, sni routing, + etc. See more details at: https://istio.io/docs/reference/config/networking/virtual-service.html' + properties: + exportTo: + description: A list of namespaces to which this virtual service is exported. + items: + format: string + type: string + type: array + gateways: + description: The names of gateways and sidecars that should apply these + routes. + items: + format: string + type: string + type: array + hosts: + description: The destination hosts to which traffic is being sent. + items: + format: string + type: string + type: array + http: + description: An ordered list of route rules for HTTP traffic. + items: + properties: + corsPolicy: + description: Cross-Origin Resource Sharing policy (CORS). + properties: + allowCredentials: + nullable: true + type: boolean + allowHeaders: + items: + format: string + type: string + type: array + allowMethods: + description: List of HTTP methods allowed to access the resource. + items: + format: string + type: string + type: array + allowOrigin: + description: The list of origins that are allowed to perform + CORS requests. + items: + format: string + type: string + type: array + allowOrigins: + description: String patterns that match allowed origins. + items: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + type: array + exposeHeaders: + items: + format: string + type: string + type: array + maxAge: + type: string + type: object + delegate: + properties: + name: + description: Name specifies the name of the delegate VirtualService. + format: string + type: string + namespace: + description: Namespace specifies the namespace where the delegate + VirtualService resides. + format: string + type: string + type: object + fault: + description: Fault injection policy to apply on HTTP traffic at + the client side. + properties: + abort: + oneOf: + - not: + anyOf: + - required: + - httpStatus + - required: + - grpcStatus + - required: + - http2Error + - required: + - httpStatus + - required: + - grpcStatus + - required: + - http2Error + properties: + grpcStatus: + format: string + type: string + http2Error: + format: string + type: string + httpStatus: + description: HTTP status code to use to abort the Http + request. + format: int32 + type: integer + percentage: + description: Percentage of requests to be aborted with + the error code provided. + properties: + value: + format: double + type: number + type: object + type: object + delay: + oneOf: + - not: + anyOf: + - required: + - fixedDelay + - required: + - exponentialDelay + - required: + - fixedDelay + - required: + - exponentialDelay + properties: + exponentialDelay: + type: string + fixedDelay: + description: Add a fixed delay before forwarding the request. + type: string + percent: + description: Percentage of requests on which the delay + will be injected (0-100). + format: int32 + type: integer + percentage: + description: Percentage of requests on which the delay + will be injected. + properties: + value: + format: double + type: number + type: object + type: object + type: object + headers: + properties: + request: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + response: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + match: + items: + properties: + authority: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + gateways: + description: Names of gateways where the rule should be + applied. + items: + format: string + type: string + type: array + headers: + additionalProperties: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + type: object + ignoreUriCase: + description: Flag to specify whether the URI matching should + be case-insensitive. + type: boolean + method: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + name: + description: The name assigned to a match. + format: string + type: string + port: + description: Specifies the ports on the host that is being + addressed. + type: integer + queryParams: + additionalProperties: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + description: Query parameters for matching. + type: object + scheme: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + sourceLabels: + additionalProperties: + format: string + type: string + type: object + sourceNamespace: + description: Source namespace constraining the applicability + of a rule to workloads in that namespace. + format: string + type: string + uri: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + withoutHeaders: + additionalProperties: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + description: RE2 style regex-based match (https://github.com/google/re2/wiki/Syntax). + format: string + type: string + type: object + description: withoutHeader has the same syntax with the + header, but has opposite meaning. + type: object + type: object + type: array + mirror: + properties: + host: + description: The name of a service from the service registry. + format: string + type: string + port: + description: Specifies the port on the host that is being + addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + mirror_percent: + description: Percentage of the traffic to be mirrored by the `mirror` + field. + nullable: true + type: integer + mirrorPercent: + description: Percentage of the traffic to be mirrored by the `mirror` + field. + nullable: true + type: integer + mirrorPercentage: + description: Percentage of the traffic to be mirrored by the `mirror` + field. + properties: + value: + format: double + type: number + type: object + name: + description: The name assigned to the route for debugging purposes. + format: string + type: string + redirect: + description: A HTTP rule can either redirect or forward (default) + traffic. + properties: + authority: + format: string + type: string + redirectCode: + type: integer + uri: + format: string + type: string + type: object + retries: + description: Retry policy for HTTP requests. + properties: + attempts: + description: Number of retries to be allowed for a given request. + format: int32 + type: integer + perTryTimeout: + description: Timeout per retry attempt for a given request. + type: string + retryOn: + description: Specifies the conditions under which retry takes + place. + format: string + type: string + retryRemoteLocalities: + description: Flag to specify whether the retries should retry + to other localities. + nullable: true + type: boolean + type: object + rewrite: + description: Rewrite HTTP URIs and Authority headers. + properties: + authority: + description: rewrite the Authority/Host header with this value. + format: string + type: string + uri: + format: string + type: string + type: object + route: + description: A HTTP rule can either redirect or forward (default) + traffic. + items: + properties: + destination: + properties: + host: + description: The name of a service from the service + registry. + format: string + type: string + port: + description: Specifies the port on the host that is + being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + headers: + properties: + request: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + response: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + weight: + format: int32 + type: integer + type: object + type: array + timeout: + description: Timeout for HTTP requests, default is disabled. + type: string + type: object + type: array + tcp: + description: An ordered list of route rules for opaque TCP traffic. + items: + properties: + match: + items: + properties: + destinationSubnets: + description: IPv4 or IPv6 ip addresses of destination with + optional subnet. + items: + format: string + type: string + type: array + gateways: + description: Names of gateways where the rule should be + applied. + items: + format: string + type: string + type: array + port: + description: Specifies the port on the host that is being + addressed. + type: integer + sourceLabels: + additionalProperties: + format: string + type: string + type: object + sourceNamespace: + description: Source namespace constraining the applicability + of a rule to workloads in that namespace. + format: string + type: string + sourceSubnet: + description: IPv4 or IPv6 ip address of source with optional + subnet. + format: string + type: string + type: object + type: array + route: + description: The destination to which the connection should be + forwarded to. + items: + properties: + destination: + properties: + host: + description: The name of a service from the service + registry. + format: string + type: string + port: + description: Specifies the port on the host that is + being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + weight: + format: int32 + type: integer + type: object + type: array + type: object + type: array + tls: + items: + properties: + match: + items: + properties: + destinationSubnets: + description: IPv4 or IPv6 ip addresses of destination with + optional subnet. + items: + format: string + type: string + type: array + gateways: + description: Names of gateways where the rule should be + applied. + items: + format: string + type: string + type: array + port: + description: Specifies the port on the host that is being + addressed. + type: integer + sniHosts: + description: SNI (server name indicator) to match on. + items: + format: string + type: string + type: array + sourceLabels: + additionalProperties: + format: string + type: string + type: object + sourceNamespace: + description: Source namespace constraining the applicability + of a rule to workloads in that namespace. + format: string + type: string + type: object + type: array + route: + description: The destination to which the connection should be + forwarded to. + items: + properties: + destination: + properties: + host: + description: The name of a service from the service + registry. + format: string + type: string + port: + description: Specifies the port on the host that is + being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + weight: + format: int32 + type: integer + type: object + type: array + type: object + type: array + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: workloadentries.networking.istio.io +spec: + additionalPrinterColumns: + - JSONPath: .metadata.creationTimestamp + description: 'CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + name: Age + type: date + - JSONPath: .spec.address + description: Address associated with the network endpoint. + name: Address + type: string + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: WorkloadEntry + listKind: WorkloadEntryList + plural: workloadentries + shortNames: + - we + singular: workloadentry + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting VMs onboarded into the mesh. See more + details at: https://istio.io/docs/reference/config/networking/workload-entry.html' + properties: + address: + format: string + type: string + labels: + additionalProperties: + format: string + type: string + description: One or more labels associated with the endpoint. + type: object + locality: + description: The locality associated with the endpoint. + format: string + type: string + network: + format: string + type: string + ports: + additionalProperties: + type: integer + description: Set of ports associated with the endpoint. + type: object + serviceAccount: + format: string + type: string + weight: + description: The load balancing weight associated with the endpoint. + type: integer + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + - name: v1beta1 + served: true + storage: false + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: workloadgroups.networking.istio.io +spec: + additionalPrinterColumns: + - JSONPath: .metadata.creationTimestamp + description: 'CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: WorkloadGroup + listKind: WorkloadGroupList + plural: workloadgroups + shortNames: + - wg + singular: workloadgroup + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Describes a collection of workload instances. See more details + at: https://istio.io/docs/reference/config/networking/workload-group.html' + properties: + metadata: + description: Metadata that will be used for all corresponding `WorkloadEntries`. + properties: + annotations: + additionalProperties: + format: string + type: string + type: object + labels: + additionalProperties: + format: string + type: string + type: object + type: object + probe: + description: '`ReadinessProbe` describes the configuration the user + must provide for healthchecking on their workload.' + oneOf: + - not: + anyOf: + - required: + - httpGet + - required: + - tcpSocket + - required: + - exec + - required: + - httpGet + - required: + - tcpSocket + - required: + - exec + properties: + exec: + description: Health is determined by how the command that is executed + exited. + properties: + command: + description: Command to run. + items: + format: string + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe to be considered + failed after having succeeded. + format: int32 + type: integer + httpGet: + properties: + host: + description: Host name to connect to, defaults to the pod IP. + format: string + type: string + httpHeaders: + description: Headers the proxy will pass on to make the request. + items: + properties: + name: + format: string + type: string + value: + format: string + type: string + type: object + type: array + path: + description: Path to access on the HTTP server. + format: string + type: string + port: + description: Port on which the endpoint lives. + type: integer + scheme: + format: string + type: string + type: object + initialDelaySeconds: + description: Number of seconds after the container has started before + readiness probes are initiated. + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe to be considered + successful after having failed. + format: int32 + type: integer + tcpSocket: + description: Health is determined by if the proxy is able to connect. + properties: + host: + format: string + type: string + port: + type: integer + type: object + timeoutSeconds: + description: Number of seconds after which the probe times out. + format: int32 + type: integer + type: object + template: + description: Template to be used for the generation of `WorkloadEntry` + resources that belong to this `WorkloadGroup`. + properties: + address: + format: string + type: string + labels: + additionalProperties: + format: string + type: string + description: One or more labels associated with the endpoint. + type: object + locality: + description: The locality associated with the endpoint. + format: string + type: string + network: + format: string + type: string + ports: + additionalProperties: + type: integer + description: Set of ports associated with the endpoint. + type: object + serviceAccount: + format: string + type: string + weight: + description: The load balancing weight associated with the endpoint. + type: integer + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1alpha3 + served: true + storage: true + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + istio: security + release: istio + name: authorizationpolicies.security.istio.io +spec: + group: security.istio.io + names: + categories: + - istio-io + - security-istio-io + kind: AuthorizationPolicy + listKind: AuthorizationPolicyList + plural: authorizationpolicies + singular: authorizationpolicy + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration for access control on workloads. See more details + at: https://istio.io/docs/reference/config/security/authorization-policy.html' + oneOf: + - not: + anyOf: + - required: + - provider + - required: + - provider + properties: + action: + description: Optional. + enum: + - ALLOW + - DENY + - AUDIT + - CUSTOM + type: string + provider: + description: Specifies detailed configuration of the CUSTOM action. + properties: + name: + description: Specifies the name of the extension provider. + format: string + type: string + type: object + rules: + description: Optional. + items: + properties: + from: + description: Optional. + items: + properties: + source: + description: Source specifies the source of a request. + properties: + ipBlocks: + description: Optional. + items: + format: string + type: string + type: array + namespaces: + description: Optional. + items: + format: string + type: string + type: array + notIpBlocks: + description: Optional. + items: + format: string + type: string + type: array + notNamespaces: + description: Optional. + items: + format: string + type: string + type: array + notPrincipals: + description: Optional. + items: + format: string + type: string + type: array + notRemoteIpBlocks: + description: Optional. + items: + format: string + type: string + type: array + notRequestPrincipals: + description: Optional. + items: + format: string + type: string + type: array + principals: + description: Optional. + items: + format: string + type: string + type: array + remoteIpBlocks: + description: Optional. + items: + format: string + type: string + type: array + requestPrincipals: + description: Optional. + items: + format: string + type: string + type: array + type: object + type: object + type: array + to: + description: Optional. + items: + properties: + operation: + description: Operation specifies the operation of a request. + properties: + hosts: + description: Optional. + items: + format: string + type: string + type: array + methods: + description: Optional. + items: + format: string + type: string + type: array + notHosts: + description: Optional. + items: + format: string + type: string + type: array + notMethods: + description: Optional. + items: + format: string + type: string + type: array + notPaths: + description: Optional. + items: + format: string + type: string + type: array + notPorts: + description: Optional. + items: + format: string + type: string + type: array + paths: + description: Optional. + items: + format: string + type: string + type: array + ports: + description: Optional. + items: + format: string + type: string + type: array + type: object + type: object + type: array + when: + description: Optional. + items: + properties: + key: + description: The name of an Istio attribute. + format: string + type: string + notValues: + description: Optional. + items: + format: string + type: string + type: array + values: + description: Optional. + items: + format: string + type: string + type: array + type: object + type: array + type: object + type: array + selector: + description: Optional. + properties: + matchLabels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1beta1 + served: true + storage: true + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + istio: security + release: istio + name: peerauthentications.security.istio.io +spec: + additionalPrinterColumns: + - JSONPath: .spec.mtls.mode + description: Defines the mTLS mode used for peer authentication. + name: Mode + type: string + - JSONPath: .metadata.creationTimestamp + description: 'CreationTimestamp is a timestamp representing the server time when + this object was created. It is not guaranteed to be set in happens-before order + across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + name: Age + type: date + group: security.istio.io + names: + categories: + - istio-io + - security-istio-io + kind: PeerAuthentication + listKind: PeerAuthenticationList + plural: peerauthentications + shortNames: + - pa + singular: peerauthentication + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: PeerAuthentication defines how traffic will be tunneled (or + not) to the sidecar. + properties: + mtls: + description: Mutual TLS settings for workload. + properties: + mode: + description: Defines the mTLS mode used for peer authentication. + enum: + - UNSET + - DISABLE + - PERMISSIVE + - STRICT + type: string + type: object + portLevelMtls: + additionalProperties: + properties: + mode: + description: Defines the mTLS mode used for peer authentication. + enum: + - UNSET + - DISABLE + - PERMISSIVE + - STRICT + type: string + type: object + description: Port specific mutual TLS settings. + type: object + selector: + description: The selector determines the workloads to apply the ChannelAuthentication + on. + properties: + matchLabels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1beta1 + served: true + storage: true + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + istio: security + release: istio + name: requestauthentications.security.istio.io +spec: + group: security.istio.io + names: + categories: + - istio-io + - security-istio-io + kind: RequestAuthentication + listKind: RequestAuthenticationList + plural: requestauthentications + shortNames: + - ra + singular: requestauthentication + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: RequestAuthentication defines what request authentication methods + are supported by a workload. + properties: + jwtRules: + description: Define the list of JWTs that can be validated at the selected + workloads' proxy. + items: + properties: + audiences: + items: + format: string + type: string + type: array + forwardOriginalToken: + description: If set to true, the orginal token will be kept for + the ustream request. + type: boolean + fromHeaders: + description: List of header locations from which JWT is expected. + items: + properties: + name: + description: The HTTP header name. + format: string + type: string + prefix: + description: The prefix that should be stripped before decoding + the token. + format: string + type: string + type: object + type: array + fromParams: + description: List of query parameters from which JWT is expected. + items: + format: string + type: string + type: array + issuer: + description: Identifies the issuer that issued the JWT. + format: string + type: string + jwks: + description: JSON Web Key Set of public keys to validate signature + of the JWT. + format: string + type: string + jwks_uri: + format: string + type: string + jwksUri: + format: string + type: string + outputPayloadToHeader: + format: string + type: string + type: object + type: array + selector: + description: The selector determines the workloads to apply the RequestAuthentication + on. + properties: + matchLabels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + versions: + - name: v1beta1 + served: true + storage: true + +--- \ No newline at end of file diff --git a/test/e2e/istio/istio-host-split.yaml b/test/e2e/istio/istio-host-split.yaml new file mode 100644 index 0000000000..7ca942d250 --- /dev/null +++ b/test/e2e/istio/istio-host-split.yaml @@ -0,0 +1,81 @@ +apiVersion: v1 +kind: Service +metadata: + name: istio-host-split-canary +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: istio-host-split + +--- +apiVersion: v1 +kind: Service +metadata: + name: istio-host-split-stable +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: istio-host-split + +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: istio-host-split-vsvc +spec: + http: + - name: primary + route: + - destination: + host: istio-host-split-stable + weight: 100 + - destination: + host: istio-host-split-canary + weight: 0 + +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: istio-host-split +spec: + strategy: + canary: + canaryService: istio-host-split-canary + stableService: istio-host-split-stable + trafficRouting: + istio: + virtualService: + name: istio-host-split-vsvc + routes: + - primary + steps: + - setWeight: 10 + - pause: {} + selector: + matchLabels: + app: istio-host-split + template: + metadata: + labels: + app: istio-host-split + spec: + containers: + - name: istio-host-split + image: nginx:1.19-alpine + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: + requests: + memory: 16Mi + cpu: 5m diff --git a/test/e2e/istio/istio-subset-split.yaml b/test/e2e/istio/istio-subset-split.yaml new file mode 100644 index 0000000000..4e62af0221 --- /dev/null +++ b/test/e2e/istio/istio-subset-split.yaml @@ -0,0 +1,85 @@ +apiVersion: v1 +kind: Service +metadata: + name: istio-subset-split +spec: + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: istio-subset-split + +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: istio-subset-split-vsvc +spec: + http: + - name: primary + route: + - destination: + host: istio-subset-split + subset: stable + weight: 100 + - destination: + host: istio-subset-split + subset: canary + weight: 0 + +--- +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-subset-split-destrule +spec: + subsets: + - name: stable + labels: + app: istio-subset-split + - name: canary + labels: + app: istio-subset-split + +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: istio-subset-split +spec: + strategy: + canary: + trafficRouting: + istio: + virtualService: + name: istio-subset-split-vsvc + routes: + - primary + destinationRule: + name: istio-subset-split-destrule + canarySubsetName: canary + stableSubsetName: stable + steps: + - setWeight: 10 + - pause: {} + selector: + matchLabels: + app: istio-subset-split + template: + metadata: + labels: + app: istio-subset-split + spec: + containers: + - name: istio-subset-split + image: nginx:1.19-alpine + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: + requests: + memory: 16Mi + cpu: 5m diff --git a/test/e2e/istio/load-test-job.yaml b/test/e2e/istio/load-test-job.yaml new file mode 100644 index 0000000000..2affe1e812 --- /dev/null +++ b/test/e2e/istio/load-test-job.yaml @@ -0,0 +1,21 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: load-test +spec: + backoffLimit: 0 + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + spec: + restartPolicy: Never + containers: + - name: load-tester + image: argoproj/load-tester:latest + command: [sh, -c, -x, -e] + args: + - | + wrk -t11 -c40 -d300s -s report.lua -H "Host: istio-rollout.local" http://istio-ingressgateway.istio-system/color + jq -e '.errors_ratio == 0' report.json + diff --git a/test/e2e/istio_test.go b/test/e2e/istio_test.go new file mode 100644 index 0000000000..3e18eee18f --- /dev/null +++ b/test/e2e/istio_test.go @@ -0,0 +1,144 @@ +// +build e2e + +package e2e + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + "github.com/tj/assert" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/test/fixtures" +) + +type IstioSuite struct { + fixtures.E2ESuite +} + +func TestIstioSuite(t *testing.T) { + suite.Run(t, new(IstioSuite)) +} + +func (s *IstioSuite) SetupSuite() { + s.E2ESuite.SetupSuite() + if !s.IstioEnabled { + s.T().SkipNow() + } +} + +func (s *IstioSuite) TestIstioHostSplit() { + s.Given(). + RolloutObjects("@istio/istio-host-split.yaml"). + When(). + ApplyManifests(). + WaitForRolloutStatus("Healthy"). + Then(). + Assert(func(t *fixtures.Then) { + vsvc := t.GetVirtualService() + assert.Equal(s.T(), int64(100), vsvc.Spec.HTTP[0].Route[0].Weight) + assert.Equal(s.T(), int64(0), vsvc.Spec.HTTP[0].Route[1].Weight) + + desired, stable := t.GetServices() + rs1 := t.GetReplicaSetByRevision("1") + assert.Equal(s.T(), rs1.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], desired.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]) + assert.Equal(s.T(), rs1.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], stable.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]) + }). + When(). + UpdateSpec(). + WaitForRolloutStatus("Paused"). + Then(). + Assert(func(t *fixtures.Then) { + vsvc := t.GetVirtualService() + assert.Equal(s.T(), int64(90), vsvc.Spec.HTTP[0].Route[0].Weight) + assert.Equal(s.T(), int64(10), vsvc.Spec.HTTP[0].Route[1].Weight) + + desired, stable := t.GetServices() + rs1 := t.GetReplicaSetByRevision("1") + rs2 := t.GetReplicaSetByRevision("2") + assert.Equal(s.T(), rs2.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], desired.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]) + assert.Equal(s.T(), rs1.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], stable.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]) + }). + When(). + PromoteRollout(). + WaitForRolloutStatus("Healthy"). + Then(). + Assert(func(t *fixtures.Then) { + vsvc := t.GetVirtualService() + assert.Equal(s.T(), int64(100), vsvc.Spec.HTTP[0].Route[0].Weight) + assert.Equal(s.T(), int64(0), vsvc.Spec.HTTP[0].Route[1].Weight) + + desired, stable := t.GetServices() + rs2 := t.GetReplicaSetByRevision("2") + assert.Equal(s.T(), rs2.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], desired.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]) + assert.Equal(s.T(), rs2.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], stable.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey]) + }) +} + +func (s *IstioSuite) TestIstioSubsetSplit() { + s.Given(). + RolloutObjects("@istio/istio-subset-split.yaml"). + When(). + ApplyManifests(). + WaitForRolloutStatus("Healthy"). + Then(). + Assert(func(t *fixtures.Then) { + vsvc := t.GetVirtualService() + assert.Equal(s.T(), int64(100), vsvc.Spec.HTTP[0].Route[0].Weight) + assert.Equal(s.T(), int64(0), vsvc.Spec.HTTP[0].Route[1].Weight) + + rs1 := t.GetReplicaSetByRevision("1") + destrule := t.GetDestinationRule() + assert.Equal(s.T(), rs1.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], destrule.Spec.Subsets[0].Labels[v1alpha1.DefaultRolloutUniqueLabelKey]) // stable + assert.Equal(s.T(), rs1.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], destrule.Spec.Subsets[1].Labels[v1alpha1.DefaultRolloutUniqueLabelKey]) // canary + }). + When(). + UpdateSpec(). + WaitForRolloutStatus("Paused"). + Then(). + Assert(func(t *fixtures.Then) { + vsvc := t.GetVirtualService() + assert.Equal(s.T(), int64(90), vsvc.Spec.HTTP[0].Route[0].Weight) + assert.Equal(s.T(), int64(10), vsvc.Spec.HTTP[0].Route[1].Weight) + + rs1 := t.GetReplicaSetByRevision("1") + rs2 := t.GetReplicaSetByRevision("2") + destrule := t.GetDestinationRule() + assert.Equal(s.T(), rs1.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], destrule.Spec.Subsets[0].Labels[v1alpha1.DefaultRolloutUniqueLabelKey]) // stable + assert.Equal(s.T(), rs2.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], destrule.Spec.Subsets[1].Labels[v1alpha1.DefaultRolloutUniqueLabelKey]) // canary + }). + When(). + PromoteRollout(). + WaitForRolloutStatus("Healthy"). + Then(). + Assert(func(t *fixtures.Then) { + vsvc := t.GetVirtualService() + assert.Equal(s.T(), int64(100), vsvc.Spec.HTTP[0].Route[0].Weight) + assert.Equal(s.T(), int64(0), vsvc.Spec.HTTP[0].Route[1].Weight) + + rs2 := t.GetReplicaSetByRevision("2") + destrule := t.GetDestinationRule() + assert.Equal(s.T(), rs2.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], destrule.Spec.Subsets[0].Labels[v1alpha1.DefaultRolloutUniqueLabelKey]) // stable + assert.Equal(s.T(), rs2.Spec.Template.Labels[v1alpha1.DefaultRolloutUniqueLabelKey], destrule.Spec.Subsets[1].Labels[v1alpha1.DefaultRolloutUniqueLabelKey]) // canary + }). + When(). + // Verify we remove the injections on the DestinationRule when a rollout no longer references it + UpdateSpec(` +spec: + strategy: + canary: + trafficRouting: null +`). + Sleep(2 * time.Second). + Then(). + Assert(func(t *fixtures.Then) { + destrule := t.GetDestinationRule() + _, ok := destrule.Annotations[v1alpha1.ManagedByRolloutsKey] + assert.False(s.T(), ok) + _, ok = destrule.Spec.Subsets[0].Labels[v1alpha1.DefaultRolloutUniqueLabelKey] + assert.False(s.T(), ok) + _, ok = destrule.Spec.Subsets[1].Labels[v1alpha1.DefaultRolloutUniqueLabelKey] + assert.False(s.T(), ok) + }) +} diff --git a/test/fixtures/common.go b/test/fixtures/common.go index 6ba3730462..d7111aab7e 100644 --- a/test/fixtures/common.go +++ b/test/fixtures/common.go @@ -30,7 +30,9 @@ import ( "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/get" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/options" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/viewcontroller" + "github.com/argoproj/argo-rollouts/rollout/trafficrouting/istio" "github.com/argoproj/argo-rollouts/utils/annotations" + istioutil "github.com/argoproj/argo-rollouts/utils/istio" replicasetutil "github.com/argoproj/argo-rollouts/utils/replicaset" unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured" ) @@ -410,3 +412,57 @@ func (c *Common) deleteObject(kind, name string) { } c.log.Info(string(out)) } + +func (c *Common) SetLabels(obj *unstructured.Unstructured) { + labels := obj.GetLabels() + labels[E2ELabelKeyTestName] = c.t.Name() + obj.SetLabels(labels) +} + +// GetServices() returns the desired (aka preview/canary) and stable (aka active) services +func (c *Common) GetServices() (*corev1.Service, *corev1.Service) { + var desiredName, stableName string + ro := c.Rollout() + if ro.Spec.Strategy.BlueGreen != nil { + desiredName = ro.Spec.Strategy.BlueGreen.PreviewService + stableName = ro.Spec.Strategy.BlueGreen.ActiveService + } else { + desiredName = ro.Spec.Strategy.Canary.CanaryService + stableName = ro.Spec.Strategy.Canary.StableService + } + var desiredSvc, stableSvc *corev1.Service + var err error + if desiredName != "" { + desiredSvc, err = c.kubeClient.CoreV1().Services(c.namespace).Get(c.Context, desiredName, metav1.GetOptions{}) + c.CheckError(err) + } + if stableName != "" { + stableSvc, err = c.kubeClient.CoreV1().Services(c.namespace).Get(c.Context, stableName, metav1.GetOptions{}) + c.CheckError(err) + } + return desiredSvc, stableSvc +} + +func (c *Common) GetVirtualService() *istio.VirtualService { + ro := c.Rollout() + name := ro.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Name + vsvcClient := c.dynamicClient.Resource(istioutil.GetIstioVirtualServiceGVR()).Namespace(c.namespace) + vsvcUn, err := vsvcClient.Get(c.Context, name, metav1.GetOptions{}) + c.CheckError(err) + var vsvc istio.VirtualService + err = runtime.DefaultUnstructuredConverter.FromUnstructured(vsvcUn.Object, &vsvc) + c.CheckError(err) + return &vsvc +} + +func (c *Common) GetDestinationRule() *istio.DestinationRule { + ro := c.Rollout() + name := ro.Spec.Strategy.Canary.TrafficRouting.Istio.DestinationRule.Name + destRuleClient := c.dynamicClient.Resource(istioutil.GetIstioDestinationRuleGVR()).Namespace(c.namespace) + destRuleUn, err := destRuleClient.Get(c.Context, name, metav1.GetOptions{}) + c.CheckError(err) + var destRule istio.DestinationRule + err = runtime.DefaultUnstructuredConverter.FromUnstructured(destRuleUn.Object, &destRule) + c.CheckError(err) + return &destRule +} diff --git a/test/fixtures/e2e_suite.go b/test/fixtures/e2e_suite.go index 3458f432f0..19368e95c9 100644 --- a/test/fixtures/e2e_suite.go +++ b/test/fixtures/e2e_suite.go @@ -48,6 +48,8 @@ var ( E2EWaitTimeout time.Duration = time.Second * 60 E2EPodDelay = 0 + E2EALBIngressAnnotations map[string]string + // All e2e tests will be labeled with this instance-id (unless E2E_INSTANCE_ID="") E2ELabelValueInstanceID = "argo-rollouts-e2e" // All e2e tests will be labeled with their test name @@ -67,8 +69,11 @@ var ( Version: "v1beta1", Resource: "poddisruptionbudgets", } - - E2EALBIngressAnnotations map[string]string + jobGVR = schema.GroupVersionResource{ + Group: "batch", + Version: "v1", + Resource: "jobs", + } ) func init() { @@ -101,6 +106,8 @@ func init() { type E2ESuite struct { suite.Suite Common + + IstioEnabled bool } func (s *E2ESuite) SetupSuite() { @@ -130,6 +137,10 @@ func (s *E2ESuite) SetupSuite() { _ = flag.Set("v", strconv.Itoa(7)) flag.Parse() } + + if istioutil.DoesIstioExist(s.dynamicClient, s.namespace) { + s.IstioEnabled = true + } } func (s *E2ESuite) TearDownSuite() { @@ -177,7 +188,9 @@ func (s *E2ESuite) deleteResources(req *labels.Requirement, propagationPolicy me serviceGVR, ingressGVR, pdbGVR, - istioutil.GetIstioGVR("v1alpha3"), + istioutil.GetIstioVirtualServiceGVR(), + istioutil.GetIstioDestinationRuleGVR(), + jobGVR, } deleteOpts := metav1.DeleteOptions{PropagationPolicy: &propagationPolicy} listOpts := metav1.ListOptions{LabelSelector: req.String()} diff --git a/test/fixtures/when.go b/test/fixtures/when.go index 21dbec33bc..9452f4ff62 100644 --- a/test/fixtures/when.go +++ b/test/fixtures/when.go @@ -3,6 +3,8 @@ package fixtures import ( "encoding/json" "fmt" + "os" + "os/exec" "strconv" "time" @@ -25,6 +27,7 @@ import ( "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/restart" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/cmd/retry" "github.com/argoproj/argo-rollouts/pkg/kubectl-argo-rollouts/info" + unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured" ) type When struct { @@ -221,6 +224,11 @@ func (w *When) WaitForRolloutStatus(status string, timeout ...time.Duration) *Wh return w.WaitForRolloutCondition(checkStatus, fmt.Sprintf("status=%s", status), timeout...) } +func (w *When) Wait(duration time.Duration) *When { + time.Sleep(duration) + return w +} + func (w *When) WaitForRolloutCanaryStepIndex(index int32, timeout ...time.Duration) *When { checkStatus := func(ro *rov1.Rollout) bool { if ro.Status.CurrentStepIndex == nil || *ro.Status.CurrentStepIndex != index { @@ -370,6 +378,26 @@ func (w *When) WaitForPostPromotionAnalysisRunPhase(phase string) *When { return w.WaitForAnalysisRunCondition(arun.Name, checkAnalysisRunPhase(phase), fmt.Sprintf("phase=%s", phase), E2EWaitTimeout) } +func (w *When) StartLoad() *When { + yamlBytes := w.yamlBytes("@istio/load-test-job.yaml") + objs, err := unstructuredutil.SplitYAML(string(yamlBytes)) + w.CheckError(err) + w.applyObject(objs[0]) + return w +} + +func (w *When) StopLoad() *When { + cmd := exec.Command("kubectl", "exec", "job/load-test", "--", "killall", "-s", "SIGINT", "wrk") + cmd.Env = os.Environ() + out, err := cmd.CombinedOutput() + if err != nil { + w.log.Errorf("kubectl exec failed: %s", out) + w.t.FailNow() + } + w.log.Info(string(out)) + return w +} + func (w *When) Then() *Then { return &Then{ Common: w.Common, diff --git a/utils/controller/controller.go b/utils/controller/controller.go index 4540a0658c..34364b18ca 100644 --- a/utils/controller/controller.go +++ b/utils/controller/controller.go @@ -176,10 +176,18 @@ func processNextWorkItem(workqueue workqueue.RateLimitingInterface, objType stri return true } +// metaNamespaceKeyFunc is a wrapper around cache.MetaNamespaceKeyFunc but also accepts strings +func metaNamespaceKeyFunc(obj interface{}) (string, error) { + if objStr, ok := obj.(string); ok { + obj = cache.ExplicitKey(objStr) + } + return cache.MetaNamespaceKeyFunc(obj) +} + func Enqueue(obj interface{}, q workqueue.RateLimitingInterface) { var key string var err error - if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + if key, err = metaNamespaceKeyFunc(obj); err != nil { runtime.HandleError(err) return } @@ -189,7 +197,7 @@ func Enqueue(obj interface{}, q workqueue.RateLimitingInterface) { func EnqueueAfter(obj interface{}, duration time.Duration, q workqueue.RateLimitingInterface) { var key string var err error - if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + if key, err = metaNamespaceKeyFunc(obj); err != nil { runtime.HandleError(err) return } @@ -199,7 +207,7 @@ func EnqueueAfter(obj interface{}, duration time.Duration, q workqueue.RateLimit func EnqueueRateLimited(obj interface{}, q workqueue.RateLimitingInterface) { var key string var err error - if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + if key, err = metaNamespaceKeyFunc(obj); err != nil { runtime.HandleError(err) return } diff --git a/utils/controller/controller_test.go b/utils/controller/controller_test.go index bd9a631560..8630c2d962 100644 --- a/utils/controller/controller_test.go +++ b/utils/controller/controller_test.go @@ -106,7 +106,7 @@ func TestEnqueue(t *testing.T) { func TestEnqueueInvalidObj(t *testing.T) { q := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Rollouts") - Enqueue("Invalid Object", q) + Enqueue(struct{}{}, q) assert.Equal(t, 0, q.Len()) } @@ -124,9 +124,15 @@ func TestEnqueueAfter(t *testing.T) { assert.Equal(t, 1, q.Len()) } +func TestEnqueueString(t *testing.T) { + q := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Rollouts") + Enqueue("default/foo", q) + assert.Equal(t, 1, q.Len()) +} + func TestEnqueueAfterInvalidObj(t *testing.T) { q := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Rollouts") - EnqueueAfter("Invalid Object", time.Duration(1), q) + EnqueueAfter(struct{}{}, time.Duration(1), q) assert.Equal(t, 0, q.Len()) time.Sleep(2 * time.Second) assert.Equal(t, 0, q.Len()) @@ -148,7 +154,7 @@ func TestEnqueueRateLimited(t *testing.T) { func TestEnqueueRateLimitedInvalidObject(t *testing.T) { q := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "Rollouts") - EnqueueRateLimited("invalid Object", q) + EnqueueRateLimited(struct{}{}, q) assert.Equal(t, 0, q.Len()) time.Sleep(time.Second) assert.Equal(t, 0, q.Len()) diff --git a/utils/defaults/defaults.go b/utils/defaults/defaults.go index 83417eafed..f46691055f 100644 --- a/utils/defaults/defaults.go +++ b/utils/defaults/defaults.go @@ -1,6 +1,10 @@ package defaults import ( + "io/ioutil" + "os" + "strings" + "k8s.io/apimachinery/pkg/util/intstr" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" @@ -26,6 +30,11 @@ const ( DefaultConsecutiveErrorLimit int32 = 4 ) +const ( + DefaultIstioVersion = "v1alpha3" + DefaultSMITrafficSplitVersion = "v1alpha1" +) + // GetReplicasOrDefault returns the deferenced number of replicas or the default number func GetReplicasOrDefault(replicas *int32) int32 { if replicas == nil { @@ -119,3 +128,18 @@ func GetConsecutiveErrorLimitOrDefault(metric *v1alpha1.Metric) int32 { } return DefaultConsecutiveErrorLimit } + +func Namespace() string { + // This way assumes you've set the POD_NAMESPACE environment variable using the downward API. + // This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up + if ns, ok := os.LookupEnv("POD_NAMESPACE"); ok { + return ns + } + // Fall back to the namespace associated with the service account token, if available + if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { + if ns := strings.TrimSpace(string(data)); len(ns) > 0 { + return ns + } + } + return "argo-rollouts" +} diff --git a/utils/istio/istio.go b/utils/istio/istio.go index c3c3baec59..a6d85db672 100644 --- a/utils/istio/istio.go +++ b/utils/istio/istio.go @@ -2,24 +2,66 @@ package istio import ( "context" + "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" + + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + "github.com/argoproj/argo-rollouts/utils/defaults" +) + +var ( + istioAPIVersion = defaults.DefaultIstioVersion ) -func DoesIstioExist(dynamicClient dynamic.Interface, namespace string, version string) bool { - _, err := dynamicClient.Resource(GetIstioGVR(version)).Namespace(namespace).List(context.TODO(), metav1.ListOptions{Limit: 1}) +func SetIstioAPIVersion(apiVersion string) { + istioAPIVersion = apiVersion +} + +func GetIstioAPIVersion() string { + return istioAPIVersion +} + +func DoesIstioExist(dynamicClient dynamic.Interface, namespace string) bool { + _, err := dynamicClient.Resource(GetIstioVirtualServiceGVR()).Namespace(namespace).List(context.TODO(), metav1.ListOptions{Limit: 1}) if err != nil { return false } return true } -func GetIstioGVR(version string) schema.GroupVersionResource { +func GetIstioVirtualServiceGVR() schema.GroupVersionResource { return schema.GroupVersionResource{ Group: "networking.istio.io", - Version: version, + Version: istioAPIVersion, Resource: "virtualservices", } } + +func GetIstioDestinationRuleGVR() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Group: "networking.istio.io", + Version: istioAPIVersion, + Resource: "destinationrules", + } +} + +// GetRolloutVirtualServiceKeys gets the referenced VirtualService and its namespace from a Rollout +func GetRolloutVirtualServiceKeys(ro *v1alpha1.Rollout) []string { + canary := ro.Spec.Strategy.Canary + if canary == nil || canary.TrafficRouting == nil || canary.TrafficRouting.Istio == nil || canary.TrafficRouting.Istio.VirtualService.Name == "" { + return []string{} + } + return []string{fmt.Sprintf("%s/%s", ro.Namespace, canary.TrafficRouting.Istio.VirtualService.Name)} +} + +// GetRolloutDesinationRuleKeys gets the referenced DestinationRule and its namespace from a Rollout +func GetRolloutDesinationRuleKeys(ro *v1alpha1.Rollout) []string { + canary := ro.Spec.Strategy.Canary + if canary == nil || canary.TrafficRouting == nil || canary.TrafficRouting.Istio == nil || canary.TrafficRouting.Istio.DestinationRule == nil || canary.TrafficRouting.Istio.DestinationRule.Name == "" { + return []string{} + } + return []string{fmt.Sprintf("%s/%s", ro.Namespace, canary.TrafficRouting.Istio.DestinationRule.Name)} +} diff --git a/utils/istio/istio_test.go b/utils/istio/istio_test.go index 02ed339dff..a6618660a9 100644 --- a/utils/istio/istio_test.go +++ b/utils/istio/istio_test.go @@ -5,6 +5,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/runtime" dynamicfake "k8s.io/client-go/dynamic/fake" @@ -12,14 +13,76 @@ import ( func TestDoesIstioExist(t *testing.T) { dynamicClient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme()) - assert.True(t, DoesIstioExist(dynamicClient, metav1.NamespaceAll, "v1alpha3")) + assert.True(t, DoesIstioExist(dynamicClient, metav1.NamespaceAll)) assert.Len(t, dynamicClient.Actions(), 1) assert.Equal(t, "list", dynamicClient.Actions()[0].GetVerb()) } -func TestGetIstioGVR(t *testing.T) { - gvr := GetIstioGVR("v1alpha3") +func TestGetIstioVirtualServiceGVR(t *testing.T) { + gvr := GetIstioVirtualServiceGVR() assert.Equal(t, "networking.istio.io", gvr.Group) assert.Equal(t, "v1alpha3", gvr.Version) assert.Equal(t, "virtualservices", gvr.Resource) } + +func TestGetIstioDestinationRuleGVR(t *testing.T) { + SetIstioAPIVersion("v1alpha4") + gvr := GetIstioDestinationRuleGVR() + assert.Equal(t, "networking.istio.io", gvr.Group) + assert.Equal(t, "v1alpha4", gvr.Version) + assert.Equal(t, "destinationrules", gvr.Resource) + SetIstioAPIVersion("v1alpha3") +} + +func TestGetRolloutVirtualServiceKeys(t *testing.T) { + ro := &v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: metav1.NamespaceDefault, + }, + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{}, + }, + } + assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) + ro.Spec.Strategy.Canary = &v1alpha1.CanaryStrategy{} + assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) + ro.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{} + assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) + ro.Spec.Strategy.Canary.TrafficRouting.Istio = &v1alpha1.IstioTrafficRouting{ + VirtualService: v1alpha1.IstioVirtualService{}, + } + assert.Len(t, GetRolloutVirtualServiceKeys(ro), 0) + ro.Spec.Strategy.Canary.TrafficRouting.Istio.VirtualService.Name = "test" + keys := GetRolloutVirtualServiceKeys(ro) + assert.Len(t, keys, 1) + assert.Equal(t, keys[0], "default/test") +} + +func TestGetRolloutDesinationRuleKeys(t *testing.T) { + ro := &v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: metav1.NamespaceDefault, + }, + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{}, + }, + }, + } + // rollout doesn't reference any dest rule + assert.Len(t, GetRolloutDesinationRuleKeys(ro), 0) + + // rollout references a destination rule + ro.Spec.Strategy.Canary.TrafficRouting = &v1alpha1.RolloutTrafficRouting{ + Istio: &v1alpha1.IstioTrafficRouting{ + DestinationRule: &v1alpha1.IstioDestinationRule{ + Name: "foo", + }, + }, + } + keys := GetRolloutDesinationRuleKeys(ro) + assert.Len(t, keys, 1) + assert.Equal(t, "default/foo", keys[0]) +}