Implement service name override

Use targetRef.name as the Kubernetes service name prefix only if service name is not specified
Warn about routing conflicts when service name changes
This commit is contained in:
stefanprodan
2020-01-26 12:48:49 +02:00
parent e3ecebc9ae
commit 940e547e88
8 changed files with 116 additions and 129 deletions
+12 -4
View File
@@ -105,17 +105,25 @@ func NewController(
flaggerInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: ctrl.enqueue,
UpdateFunc: func(old, new interface{}) {
oldRoll, ok := checkCustomResourceType(old, logger)
oldCanary, ok := checkCustomResourceType(old, logger)
if !ok {
return
}
newRoll, ok := checkCustomResourceType(new, logger)
newCanary, ok := checkCustomResourceType(new, logger)
if !ok {
return
}
if diff := cmp.Diff(newRoll.Spec, oldRoll.Spec); diff != "" {
ctrl.logger.Debugf("Diff detected %s.%s %s", oldRoll.Name, oldRoll.Namespace, diff)
if diff := cmp.Diff(newCanary.Spec, oldCanary.Spec); diff != "" {
ctrl.logger.Debugf("Diff detected %s.%s %s", oldCanary.Name, oldCanary.Namespace, diff)
// warn about routing conflicts when service name changes
if oldCanary.Spec.Service.Name != "" && oldCanary.Spec.Service.Name != newCanary.Spec.Service.Name {
ctrl.logger.With("canary", fmt.Sprintf("%s.%s", oldCanary.Name, oldCanary.Namespace)).
Warnf("The service name changed to %s, remove %s objects to avoid routing conflicts",
newCanary.Spec.Service.Name, oldCanary.Spec.Service.Name)
}
ctrl.enqueue(new)
}
},
+19 -21
View File
@@ -33,16 +33,14 @@ func (ar *AppMeshRouter) Reconcile(canary *flaggerv1.Canary) error {
return fmt.Errorf("mesh name cannot be empty")
}
targetName := canary.Spec.TargetRef.Name
targetHost := fmt.Sprintf("%s.%s", targetName, canary.Namespace)
primaryName := fmt.Sprintf("%s-primary", targetName)
apexName, primaryName, canaryName := canary.GetServiceNames()
targetHost := fmt.Sprintf("%s.%s", apexName, canary.Namespace)
primaryHost := fmt.Sprintf("%s.%s", primaryName, canary.Namespace)
canaryName := fmt.Sprintf("%s-canary", targetName)
canaryHost := fmt.Sprintf("%s.%s", canaryName, canary.Namespace)
// sync virtual node e.g. app-namespace
// DNS app.namespace
err := ar.reconcileVirtualNode(canary, targetName, primaryHost)
err := ar.reconcileVirtualNode(canary, apexName, primaryHost)
if err != nil {
return err
}
@@ -162,14 +160,14 @@ func (ar *AppMeshRouter) reconcileVirtualNode(canary *flaggerv1.Canary, name str
// reconcileVirtualService creates or updates a virtual service
func (ar *AppMeshRouter) reconcileVirtualService(canary *flaggerv1.Canary, name string, canaryWeight int64) error {
targetName := canary.Spec.TargetRef.Name
canaryVirtualNode := fmt.Sprintf("%s-canary", targetName)
primaryVirtualNode := fmt.Sprintf("%s-primary", targetName)
apexName, _, _ := canary.GetServiceNames()
canaryVirtualNode := fmt.Sprintf("%s-canary", apexName)
primaryVirtualNode := fmt.Sprintf("%s-primary", apexName)
protocol := ar.getProtocol(canary)
routerName := targetName
routerName := apexName
if canaryWeight > 0 {
routerName = fmt.Sprintf("%s-canary", targetName)
routerName = fmt.Sprintf("%s-canary", apexName)
}
// App Mesh supports only URI prefix
routePrefix := "/"
@@ -208,7 +206,7 @@ func (ar *AppMeshRouter) reconcileVirtualService(canary *flaggerv1.Canary, name
if len(canary.Spec.CanaryAnalysis.Match) > 0 && canaryWeight == 0 {
routes = []appmeshv1.Route{
{
Name: fmt.Sprintf("%s-a", targetName),
Name: fmt.Sprintf("%s-a", apexName),
Priority: int64p(10),
Http: &appmeshv1.HttpRoute{
Match: appmeshv1.HttpRouteMatch{
@@ -231,7 +229,7 @@ func (ar *AppMeshRouter) reconcileVirtualService(canary *flaggerv1.Canary, name
},
},
{
Name: fmt.Sprintf("%s-b", targetName),
Name: fmt.Sprintf("%s-b", apexName),
Priority: int64p(20),
Http: &appmeshv1.HttpRoute{
Match: appmeshv1.HttpRouteMatch{
@@ -341,8 +339,8 @@ func (ar *AppMeshRouter) GetRoutes(canary *flaggerv1.Canary) (
mirrored bool,
err error,
) {
targetName := canary.Spec.TargetRef.Name
vsName := fmt.Sprintf("%s.%s", targetName, canary.Namespace)
apexName, _, _ := canary.GetServiceNames()
vsName := fmt.Sprintf("%s.%s", apexName, canary.Namespace)
vs, err := ar.appmeshClient.AppmeshV1beta1().VirtualServices(canary.Namespace).Get(vsName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
@@ -360,17 +358,17 @@ func (ar *AppMeshRouter) GetRoutes(canary *flaggerv1.Canary) (
targets := vs.Spec.Routes[0].Http.Action.WeightedTargets
for _, t := range targets {
if t.VirtualNodeName == fmt.Sprintf("%s-canary", targetName) {
if t.VirtualNodeName == fmt.Sprintf("%s-canary", apexName) {
canaryWeight = int(t.Weight)
}
if t.VirtualNodeName == fmt.Sprintf("%s-primary", targetName) {
if t.VirtualNodeName == fmt.Sprintf("%s-primary", apexName) {
primaryWeight = int(t.Weight)
}
}
if primaryWeight == 0 && canaryWeight == 0 {
err = fmt.Errorf("VirtualService %s does not contain routes for %s-primary and %s-canary",
vsName, targetName, targetName)
vsName, apexName, apexName)
}
mirrored = false
@@ -385,8 +383,8 @@ func (ar *AppMeshRouter) SetRoutes(
canaryWeight int,
mirrored bool,
) error {
targetName := canary.Spec.TargetRef.Name
vsName := fmt.Sprintf("%s.%s", targetName, canary.Namespace)
apexName, _, _ := canary.GetServiceNames()
vsName := fmt.Sprintf("%s.%s", apexName, canary.Namespace)
vs, err := ar.appmeshClient.AppmeshV1beta1().VirtualServices(canary.Namespace).Get(vsName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
@@ -399,11 +397,11 @@ func (ar *AppMeshRouter) SetRoutes(
vsClone.Spec.Routes[0].Http.Action = appmeshv1.HttpRouteAction{
WeightedTargets: []appmeshv1.WeightedTarget{
{
VirtualNodeName: fmt.Sprintf("%s-canary", targetName),
VirtualNodeName: fmt.Sprintf("%s-canary", apexName),
Weight: int64(canaryWeight),
},
{
VirtualNodeName: fmt.Sprintf("%s-primary", targetName),
VirtualNodeName: fmt.Sprintf("%s-primary", apexName),
Weight: int64(primaryWeight),
},
},
+17 -22
View File
@@ -26,9 +26,7 @@ type ContourRouter struct {
// Reconcile creates or updates the HTTP proxy
func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error {
targetName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
canaryName := fmt.Sprintf("%s-canary", targetName)
apexName, primaryName, canaryName := canary.GetServiceNames()
newSpec := contourv1.HTTPProxySpec{
Routes: []contourv1.Route{
@@ -131,11 +129,11 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error {
}
}
proxy, err := cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Get(targetName, metav1.GetOptions{})
proxy, err := cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Get(apexName, metav1.GetOptions{})
if errors.IsNotFound(err) {
proxy = &contourv1.HTTPProxy{
ObjectMeta: metav1.ObjectMeta{
Name: targetName,
Name: apexName,
Namespace: canary.Namespace,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(canary, schema.GroupVersionKind{
@@ -154,7 +152,7 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error {
_, err = cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Create(proxy)
if err != nil {
return fmt.Errorf("HTTPProxy %s.%s create error %v", targetName, canary.Namespace, err)
return fmt.Errorf("HTTPProxy %s.%s create error %v", apexName, canary.Namespace, err)
}
cr.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("HTTPProxy %s.%s created", proxy.GetName(), canary.Namespace)
@@ -162,7 +160,7 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error {
}
if err != nil {
return fmt.Errorf("HTTPProxy %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("HTTPProxy %s.%s query error %v", apexName, canary.Namespace, err)
}
// update HTTPProxy but keep the original destination weights
@@ -177,7 +175,7 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error {
_, err = cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Update(clone)
if err != nil {
return fmt.Errorf("HTTPProxy %s.%s update error %v", targetName, canary.Namespace, err)
return fmt.Errorf("HTTPProxy %s.%s update error %v", apexName, canary.Namespace, err)
}
cr.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("HTTPProxy %s.%s updated", proxy.GetName(), canary.Namespace)
@@ -194,21 +192,20 @@ func (cr *ContourRouter) GetRoutes(canary *flaggerv1.Canary) (
mirrored bool,
err error,
) {
targetName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
apexName, primaryName, _ := canary.GetServiceNames()
proxy, err := cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Get(targetName, metav1.GetOptions{})
proxy, err := cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
err = fmt.Errorf("HTTPProxy %s.%s not found", targetName, canary.Namespace)
err = fmt.Errorf("HTTPProxy %s.%s not found", apexName, canary.Namespace)
return
}
err = fmt.Errorf("HTTPProxy %s.%s query error %v", targetName, canary.Namespace, err)
err = fmt.Errorf("HTTPProxy %s.%s query error %v", apexName, canary.Namespace, err)
return
}
if len(proxy.Spec.Routes) < 1 || len(proxy.Spec.Routes[0].Services) < 2 {
err = fmt.Errorf("HTTPProxy %s.%s services not found", targetName, canary.Namespace)
err = fmt.Errorf("HTTPProxy %s.%s services not found", apexName, canary.Namespace)
return
}
@@ -230,21 +227,19 @@ func (cr *ContourRouter) SetRoutes(
canaryWeight int,
mirrored bool,
) error {
targetName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
canaryName := fmt.Sprintf("%s-canary", targetName)
apexName, primaryName, canaryName := canary.GetServiceNames()
if primaryWeight == 0 && canaryWeight == 0 {
return fmt.Errorf("HTTPProxy %s.%s update failed: no valid weights", targetName, canary.Namespace)
return fmt.Errorf("HTTPProxy %s.%s update failed: no valid weights", apexName, canary.Namespace)
}
proxy, err := cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Get(targetName, metav1.GetOptions{})
proxy, err := cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("HTTPProxy %s.%s not found", targetName, canary.Namespace)
return fmt.Errorf("HTTPProxy %s.%s not found", apexName, canary.Namespace)
}
return fmt.Errorf("HTTPProxy %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("HTTPProxy %s.%s query error %v", apexName, canary.Namespace, err)
}
proxy.Spec = contourv1.HTTPProxySpec{
@@ -349,7 +344,7 @@ func (cr *ContourRouter) SetRoutes(
_, err = cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Update(proxy)
if err != nil {
return fmt.Errorf("HTTPProxy %s.%s update error %v", targetName, canary.Namespace, err)
return fmt.Errorf("HTTPProxy %s.%s update error %v", apexName, canary.Namespace, err)
}
return nil
}
+21 -21
View File
@@ -27,9 +27,9 @@ type GlooRouter struct {
// Reconcile creates or updates the Istio virtual service
func (gr *GlooRouter) Reconcile(canary *flaggerv1.Canary) error {
targetName := canary.Spec.TargetRef.Name
canaryName := fmt.Sprintf("%s-%s-canary-%v", canary.Namespace, canary.Spec.TargetRef.Name, canary.Spec.Service.Port)
primaryName := fmt.Sprintf("%s-%s-primary-%v", canary.Namespace, canary.Spec.TargetRef.Name, canary.Spec.Service.Port)
apexName, _, _ := canary.GetServiceNames()
canaryName := fmt.Sprintf("%s-%s-canary-%v", canary.Namespace, apexName, canary.Spec.Service.Port)
primaryName := fmt.Sprintf("%s-%s-primary-%v", canary.Namespace, apexName, canary.Spec.Service.Port)
newSpec := gloov1.UpstreamGroupSpec{
Destinations: []gloov1.WeightedDestination{
@@ -54,11 +54,11 @@ func (gr *GlooRouter) Reconcile(canary *flaggerv1.Canary) error {
},
}
upstreamGroup, err := gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Get(targetName, metav1.GetOptions{})
upstreamGroup, err := gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Get(apexName, metav1.GetOptions{})
if errors.IsNotFound(err) {
upstreamGroup = &gloov1.UpstreamGroup{
ObjectMeta: metav1.ObjectMeta{
Name: targetName,
Name: apexName,
Namespace: canary.Namespace,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(canary, schema.GroupVersionKind{
@@ -73,7 +73,7 @@ func (gr *GlooRouter) Reconcile(canary *flaggerv1.Canary) error {
_, err = gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Create(upstreamGroup)
if err != nil {
return fmt.Errorf("UpstreamGroup %s.%s create error %v", targetName, canary.Namespace, err)
return fmt.Errorf("UpstreamGroup %s.%s create error %v", apexName, canary.Namespace, err)
}
gr.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("UpstreamGroup %s.%s created", upstreamGroup.GetName(), canary.Namespace)
@@ -81,7 +81,7 @@ func (gr *GlooRouter) Reconcile(canary *flaggerv1.Canary) error {
}
if err != nil {
return fmt.Errorf("UpstreamGroup %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("UpstreamGroup %s.%s query error %v", apexName, canary.Namespace, err)
}
// update upstreamGroup but keep the original destination weights
@@ -96,7 +96,7 @@ func (gr *GlooRouter) Reconcile(canary *flaggerv1.Canary) error {
_, err = gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Update(clone)
if err != nil {
return fmt.Errorf("UpstreamGroup %s.%s update error %v", targetName, canary.Namespace, err)
return fmt.Errorf("UpstreamGroup %s.%s update error %v", apexName, canary.Namespace, err)
}
gr.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("UpstreamGroup %s.%s updated", upstreamGroup.GetName(), canary.Namespace)
@@ -113,21 +113,21 @@ func (gr *GlooRouter) GetRoutes(canary *flaggerv1.Canary) (
mirrored bool,
err error,
) {
targetName := canary.Spec.TargetRef.Name
apexName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-%s-primary-%v", canary.Namespace, canary.Spec.TargetRef.Name, canary.Spec.Service.Port)
upstreamGroup, err := gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Get(targetName, metav1.GetOptions{})
upstreamGroup, err := gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
err = fmt.Errorf("UpstreamGroup %s.%s not found", targetName, canary.Namespace)
err = fmt.Errorf("UpstreamGroup %s.%s not found", apexName, canary.Namespace)
return
}
err = fmt.Errorf("UpstreamGroup %s.%s query error %v", targetName, canary.Namespace, err)
err = fmt.Errorf("UpstreamGroup %s.%s query error %v", apexName, canary.Namespace, err)
return
}
if len(upstreamGroup.Spec.Destinations) < 2 {
err = fmt.Errorf("UpstreamGroup %s.%s destinations not found", targetName, canary.Namespace)
err = fmt.Errorf("UpstreamGroup %s.%s destinations not found", apexName, canary.Namespace)
return
}
@@ -149,21 +149,21 @@ func (gr *GlooRouter) SetRoutes(
canaryWeight int,
mirrored bool,
) error {
targetName := canary.Spec.TargetRef.Name
canaryName := fmt.Sprintf("%s-%s-canary-%v", canary.Namespace, canary.Spec.TargetRef.Name, canary.Spec.Service.Port)
primaryName := fmt.Sprintf("%s-%s-primary-%v", canary.Namespace, canary.Spec.TargetRef.Name, canary.Spec.Service.Port)
apexName, _, _ := canary.GetServiceNames()
canaryName := fmt.Sprintf("%s-%s-canary-%v", canary.Namespace, apexName, canary.Spec.Service.Port)
primaryName := fmt.Sprintf("%s-%s-primary-%v", canary.Namespace, apexName, canary.Spec.Service.Port)
if primaryWeight == 0 && canaryWeight == 0 {
return fmt.Errorf("RoutingRule %s.%s update failed: no valid weights", targetName, canary.Namespace)
return fmt.Errorf("RoutingRule %s.%s update failed: no valid weights", apexName, canary.Namespace)
}
upstreamGroup, err := gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Get(targetName, metav1.GetOptions{})
upstreamGroup, err := gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("UpstreamGroup %s.%s not found", targetName, canary.Namespace)
return fmt.Errorf("UpstreamGroup %s.%s not found", apexName, canary.Namespace)
}
return fmt.Errorf("UpstreamGroup %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("UpstreamGroup %s.%s query error %v", apexName, canary.Namespace, err)
}
upstreamGroup.Spec = gloov1.UpstreamGroupSpec{
@@ -191,7 +191,7 @@ func (gr *GlooRouter) SetRoutes(
_, err = gr.glooClient.GlooV1().UpstreamGroups(canary.Namespace).Update(upstreamGroup)
if err != nil {
return fmt.Errorf("UpstreamGroup %s.%s update error %v", targetName, canary.Namespace, err)
return fmt.Errorf("UpstreamGroup %s.%s update error %v", apexName, canary.Namespace, err)
}
return nil
}
+4 -4
View File
@@ -27,8 +27,8 @@ func (i *IngressRouter) Reconcile(canary *flaggerv1.Canary) error {
return fmt.Errorf("ingress selector is empty")
}
targetName := canary.Spec.TargetRef.Name
canaryName := fmt.Sprintf("%s-canary", targetName)
apexName, _, _ := canary.GetServiceNames()
canaryName := fmt.Sprintf("%s-canary", apexName)
canaryIngressName := fmt.Sprintf("%s-canary", canary.Spec.IngressRef.Name)
ingress, err := i.kubeClient.ExtensionsV1beta1().Ingresses(canary.Namespace).Get(canary.Spec.IngressRef.Name, metav1.GetOptions{})
@@ -42,7 +42,7 @@ func (i *IngressRouter) Reconcile(canary *flaggerv1.Canary) error {
backendExists := false
for k, v := range ingressClone.Spec.Rules {
for x, y := range v.HTTP.Paths {
if y.Backend.ServiceName == targetName {
if y.Backend.ServiceName == apexName {
ingressClone.Spec.Rules[k].HTTP.Paths[x].Backend.ServiceName = canaryName
backendExists = true
break
@@ -51,7 +51,7 @@ func (i *IngressRouter) Reconcile(canary *flaggerv1.Canary) error {
}
if !backendExists {
return fmt.Errorf("backend %s not found in ingress %s", targetName, canary.Spec.IngressRef.Name)
return fmt.Errorf("backend %s not found in ingress %s", apexName, canary.Spec.IngressRef.Name)
}
canaryIngress, err := i.kubeClient.ExtensionsV1beta1().Ingresses(canary.Namespace).Get(canaryIngressName, metav1.GetOptions{})
+22 -27
View File
@@ -26,8 +26,7 @@ type IstioRouter struct {
// Reconcile creates or updates the Istio virtual service and destination rules
func (ir *IstioRouter) Reconcile(canary *flaggerv1.Canary) error {
canaryName := fmt.Sprintf("%s-canary", canary.Spec.TargetRef.Name)
primaryName := fmt.Sprintf("%s-primary", canary.Spec.TargetRef.Name)
_, primaryName, canaryName := canary.GetServiceNames()
err := ir.reconcileDestinationRule(canary, canaryName)
if err != nil {
@@ -101,19 +100,19 @@ func (ir *IstioRouter) reconcileDestinationRule(canary *flaggerv1.Canary, name s
}
func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
targetName := canary.Spec.TargetRef.Name
apexName, primaryName, canaryName := canary.GetServiceNames()
// set hosts and add the ClusterIP service host if it doesn't exists
hosts := canary.Spec.Service.Hosts
var hasServiceHost bool
for _, h := range hosts {
if h == targetName || h == "*" {
if h == apexName || h == "*" {
hasServiceHost = true
break
}
}
if !hasServiceHost {
hosts = append(hosts, targetName)
hosts = append(hosts, apexName)
}
// set gateways and add the mesh gateway if it doesn't exists
@@ -132,8 +131,6 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}
// create destinations with primary weight 100% and canary weight 0%
primaryName := fmt.Sprintf("%s-primary", targetName)
canaryName := fmt.Sprintf("%s-canary", targetName)
canaryRoute := []istiov1alpha3.DestinationWeight{
makeDestination(canary, primaryName, 100),
makeDestination(canary, canaryName, 0),
@@ -181,12 +178,12 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}
}
virtualService, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(targetName, metav1.GetOptions{})
virtualService, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(apexName, metav1.GetOptions{})
// insert
if errors.IsNotFound(err) {
virtualService = &istiov1alpha3.VirtualService{
ObjectMeta: metav1.ObjectMeta{
Name: targetName,
Name: apexName,
Namespace: canary.Namespace,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(canary, schema.GroupVersionKind{
@@ -200,7 +197,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}
_, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Create(virtualService)
if err != nil {
return fmt.Errorf("VirtualService %s.%s create error %v", targetName, canary.Namespace, err)
return fmt.Errorf("VirtualService %s.%s create error %v", apexName, canary.Namespace, err)
}
ir.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("VirtualService %s.%s created", virtualService.GetName(), canary.Namespace)
@@ -208,7 +205,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}
if err != nil {
return fmt.Errorf("VirtualService %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("VirtualService %s.%s query error %v", apexName, canary.Namespace, err)
}
// update service but keep the original destination weights and mirror
@@ -224,7 +221,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
_, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(vtClone)
if err != nil {
return fmt.Errorf("VirtualService %s.%s update error %v", targetName, canary.Namespace, err)
return fmt.Errorf("VirtualService %s.%s update error %v", apexName, canary.Namespace, err)
}
ir.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("VirtualService %s.%s updated", virtualService.GetName(), canary.Namespace)
@@ -241,22 +238,22 @@ func (ir *IstioRouter) GetRoutes(canary *flaggerv1.Canary) (
mirrored bool,
err error,
) {
targetName := canary.Spec.TargetRef.Name
apexName, primaryName, canaryName := canary.GetServiceNames()
vs := &istiov1alpha3.VirtualService{}
vs, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(targetName, metav1.GetOptions{})
vs, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
err = fmt.Errorf("VirtualService %s.%s not found", targetName, canary.Namespace)
err = fmt.Errorf("VirtualService %s.%s not found", apexName, canary.Namespace)
return
}
err = fmt.Errorf("VirtualService %s.%s query error %v", targetName, canary.Namespace, err)
err = fmt.Errorf("VirtualService %s.%s query error %v", apexName, canary.Namespace, err)
return
}
var httpRoute istiov1alpha3.HTTPRoute
for _, http := range vs.Spec.Http {
for _, r := range http.Route {
if r.Destination.Host == fmt.Sprintf("%s-canary", targetName) {
if r.Destination.Host == canaryName {
httpRoute = http
break
}
@@ -264,10 +261,10 @@ func (ir *IstioRouter) GetRoutes(canary *flaggerv1.Canary) (
}
for _, route := range httpRoute.Route {
if route.Destination.Host == fmt.Sprintf("%s-primary", targetName) {
if route.Destination.Host == primaryName {
primaryWeight = route.Weight
}
if route.Destination.Host == fmt.Sprintf("%s-canary", targetName) {
if route.Destination.Host == canaryName {
canaryWeight = route.Weight
}
}
@@ -277,7 +274,7 @@ func (ir *IstioRouter) GetRoutes(canary *flaggerv1.Canary) (
if primaryWeight == 0 && canaryWeight == 0 {
err = fmt.Errorf("VirtualService %s.%s does not contain routes for %s-primary and %s-canary",
targetName, canary.Namespace, targetName, targetName)
apexName, canary.Namespace, apexName, apexName)
}
return
@@ -290,17 +287,15 @@ func (ir *IstioRouter) SetRoutes(
canaryWeight int,
mirrored bool,
) error {
targetName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
canaryName := fmt.Sprintf("%s-canary", targetName)
apexName, primaryName, canaryName := canary.GetServiceNames()
vs, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(targetName, metav1.GetOptions{})
vs, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("VirtualService %s.%s not found", targetName, canary.Namespace)
return fmt.Errorf("VirtualService %s.%s not found", apexName, canary.Namespace)
}
return fmt.Errorf("VirtualService %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("VirtualService %s.%s query error %v", apexName, canary.Namespace, err)
}
vsCopy := vs.DeepCopy()
@@ -360,7 +355,7 @@ func (ir *IstioRouter) SetRoutes(
vs, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(vsCopy)
if err != nil {
return fmt.Errorf("VirtualService %s.%s update failed: %v", targetName, canary.Namespace, err)
return fmt.Errorf("VirtualService %s.%s update failed: %v", apexName, canary.Namespace, err)
}
return nil
+4 -7
View File
@@ -29,12 +29,10 @@ type KubernetesDeploymentRouter struct {
// Initialize creates the primary and canary services
func (c *KubernetesDeploymentRouter) Initialize(canary *flaggerv1.Canary) error {
targetName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
canaryName := fmt.Sprintf("%s-canary", targetName)
apexName, primaryName, canaryName := canary.GetServiceNames()
// canary svc
err := c.reconcileService(canary, canaryName, targetName)
err := c.reconcileService(canary, canaryName, apexName)
if err != nil {
return err
}
@@ -50,11 +48,10 @@ func (c *KubernetesDeploymentRouter) Initialize(canary *flaggerv1.Canary) error
// Reconcile creates or updates the main service
func (c *KubernetesDeploymentRouter) Reconcile(canary *flaggerv1.Canary) error {
targetName := canary.Spec.TargetRef.Name
primaryName := fmt.Sprintf("%s-primary", targetName)
apexName, primaryName, _ := canary.GetServiceNames()
// main svc
err := c.reconcileService(canary, targetName, primaryName)
err := c.reconcileService(canary, apexName, primaryName)
if err != nil {
return err
}
+17 -23
View File
@@ -28,15 +28,13 @@ type SmiRouter struct {
// Reconcile creates or updates the SMI traffic split
func (sr *SmiRouter) Reconcile(canary *flaggerv1.Canary) error {
targetName := canary.Spec.TargetRef.Name
canaryName := fmt.Sprintf("%s-canary", targetName)
primaryName := fmt.Sprintf("%s-primary", targetName)
apexName, primaryName, canaryName := canary.GetServiceNames()
var host string
if len(canary.Spec.Service.Hosts) > 0 {
host = canary.Spec.Service.Hosts[0]
} else {
host = targetName
host = apexName
}
tsSpec := smiv1.TrafficSplitSpec{
@@ -53,12 +51,12 @@ func (sr *SmiRouter) Reconcile(canary *flaggerv1.Canary) error {
},
}
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(targetName, metav1.GetOptions{})
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(apexName, metav1.GetOptions{})
// create traffic split
if errors.IsNotFound(err) {
t := &smiv1.TrafficSplit{
ObjectMeta: metav1.ObjectMeta{
Name: targetName,
Name: apexName,
Namespace: canary.Namespace,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(canary, schema.GroupVersionKind{
@@ -83,7 +81,7 @@ func (sr *SmiRouter) Reconcile(canary *flaggerv1.Canary) error {
}
if err != nil {
return fmt.Errorf("traffic split %s query error %v", targetName, err)
return fmt.Errorf("traffic split %s query error %v", apexName, err)
}
// update traffic split
@@ -93,11 +91,11 @@ func (sr *SmiRouter) Reconcile(canary *flaggerv1.Canary) error {
_, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Update(tsClone)
if err != nil {
return fmt.Errorf("TrafficSplit %s update error %v", targetName, err)
return fmt.Errorf("TrafficSplit %s update error %v", apexName, err)
}
sr.logger.With("canary", fmt.Sprintf("%s.%s", canary.Name, canary.Namespace)).
Infof("TrafficSplit %s.%s updated", targetName, canary.Namespace)
Infof("TrafficSplit %s.%s updated", apexName, canary.Namespace)
return nil
}
@@ -111,16 +109,14 @@ func (sr *SmiRouter) GetRoutes(canary *flaggerv1.Canary) (
mirrored bool,
err error,
) {
targetName := canary.Spec.TargetRef.Name
canaryName := fmt.Sprintf("%s-canary", targetName)
primaryName := fmt.Sprintf("%s-primary", targetName)
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(targetName, metav1.GetOptions{})
apexName, primaryName, canaryName := canary.GetServiceNames()
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
err = fmt.Errorf("TrafficSplit %s.%s not found", targetName, canary.Namespace)
err = fmt.Errorf("TrafficSplit %s.%s not found", apexName, canary.Namespace)
return
}
err = fmt.Errorf("TrafficSplit %s.%s query error %v", targetName, canary.Namespace, err)
err = fmt.Errorf("TrafficSplit %s.%s query error %v", apexName, canary.Namespace, err)
return
}
@@ -136,7 +132,7 @@ func (sr *SmiRouter) GetRoutes(canary *flaggerv1.Canary) (
if primaryWeight == 0 && canaryWeight == 0 {
err = fmt.Errorf("TrafficSplit %s.%s does not contain routes for %s and %s",
targetName, canary.Namespace, primaryName, canaryName)
apexName, canary.Namespace, primaryName, canaryName)
}
mirrored = false
@@ -151,16 +147,14 @@ func (sr *SmiRouter) SetRoutes(
canaryWeight int,
mirrored bool,
) error {
targetName := canary.Spec.TargetRef.Name
canaryName := fmt.Sprintf("%s-canary", targetName)
primaryName := fmt.Sprintf("%s-primary", targetName)
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(targetName, metav1.GetOptions{})
apexName, primaryName, canaryName := canary.GetServiceNames()
ts, err := sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Get(apexName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("TrafficSplit %s.%s not found", targetName, canary.Namespace)
return fmt.Errorf("TrafficSplit %s.%s not found", apexName, canary.Namespace)
}
return fmt.Errorf("TrafficSplit %s.%s query error %v", targetName, canary.Namespace, err)
return fmt.Errorf("TrafficSplit %s.%s query error %v", apexName, canary.Namespace, err)
}
backends := []smiv1.TrafficSplitBackend{
@@ -179,7 +173,7 @@ func (sr *SmiRouter) SetRoutes(
_, err = sr.smiClient.SplitV1alpha1().TrafficSplits(canary.Namespace).Update(tsClone)
if err != nil {
return fmt.Errorf("TrafficSplit %s update error %v", targetName, err)
return fmt.Errorf("TrafficSplit %s update error %v", apexName, err)
}
return nil