|
| 1 | +/* |
| 2 | +Copyright 2016 The Kubernetes Authors. |
| 3 | +
|
| 4 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +you may not use this file except in compliance with the License. |
| 6 | +You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +See the License for the specific language governing permissions and |
| 14 | +limitations under the License. |
| 15 | +*/ |
| 16 | + |
| 17 | +package sessionaffinity |
| 18 | + |
| 19 | +import ( |
| 20 | + "regexp" |
| 21 | + |
| 22 | + "github.com/golang/glog" |
| 23 | + |
| 24 | + "k8s.io/kubernetes/pkg/apis/extensions" |
| 25 | + |
| 26 | + "k8s.io/ingress/core/pkg/ingress/annotations/parser" |
| 27 | +) |
| 28 | + |
| 29 | +const ( |
| 30 | + annotationAffinityType = "ingress.kubernetes.io/affinity" |
| 31 | + // If a cookie with this name exists, |
| 32 | + // its value is used as an index into the list of available backends. |
| 33 | + annotationAffinityCookieName = "ingress.kubernetes.io/session-cookie-name" |
| 34 | + defaultAffinityCookieName = "INGRESSCOOKIE" |
| 35 | + // This is the algorithm used by nginx to generate a value for the session cookie, if |
| 36 | + // one isn't supplied and affintiy is set to "cookie". |
| 37 | + annotationAffinityCookieHash = "ingress.kubernetes.io/session-cookie-hash" |
| 38 | + defaultAffinityCookieHash = "md5" |
| 39 | +) |
| 40 | + |
| 41 | +var ( |
| 42 | + affinityCookieHashRegex = regexp.MustCompile(`^(index|md5|sha1)$`) |
| 43 | +) |
| 44 | + |
| 45 | +// AffinityConfig describes the per ingress session affinity config |
| 46 | +type AffinityConfig struct { |
| 47 | + // The type of affinity that will be used |
| 48 | + AffinityType string `json:"type"` |
| 49 | + CookieConfig |
| 50 | +} |
| 51 | + |
| 52 | +// CookieConfig describes the Config of cookie type affinity |
| 53 | +type CookieConfig struct { |
| 54 | + // The name of the cookie that will be used in case of cookie affinity type. |
| 55 | + Name string `json:"name"` |
| 56 | + // The hash that will be used to encode the cookie in case of cookie affinity type |
| 57 | + Hash string `json:"hash"` |
| 58 | +} |
| 59 | + |
| 60 | +// CookieAffinityParse gets the annotation values related to Cookie Affinity |
| 61 | +// It also sets default values when no value or incorrect value is found |
| 62 | +func CookieAffinityParse(ing *extensions.Ingress) *CookieConfig { |
| 63 | + |
| 64 | + sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing) |
| 65 | + |
| 66 | + if err != nil || sn == "" { |
| 67 | + glog.V(3).Infof("Ingress %v: No value found in annotation %v. Using the default %v", ing.Name, annotationAffinityCookieName, defaultAffinityCookieName) |
| 68 | + sn = defaultAffinityCookieName |
| 69 | + } |
| 70 | + |
| 71 | + sh, err := parser.GetStringAnnotation(annotationAffinityCookieHash, ing) |
| 72 | + |
| 73 | + if err != nil || !affinityCookieHashRegex.MatchString(sh) { |
| 74 | + glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Setting it to default %v", ing.Name, annotationAffinityCookieHash, defaultAffinityCookieHash) |
| 75 | + sh = defaultAffinityCookieHash |
| 76 | + } |
| 77 | + |
| 78 | + return &CookieConfig{ |
| 79 | + Name: sn, |
| 80 | + Hash: sh, |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +// NewParser creates a new Affinity annotation parser |
| 85 | +func NewParser() parser.IngressAnnotation { |
| 86 | + return affinity{} |
| 87 | +} |
| 88 | + |
| 89 | +type affinity struct { |
| 90 | +} |
| 91 | + |
| 92 | +// ParseAnnotations parses the annotations contained in the ingress |
| 93 | +// rule used to configure the affinity directives |
| 94 | +func (a affinity) Parse(ing *extensions.Ingress) (interface{}, error) { |
| 95 | + |
| 96 | + var cookieAffinityConfig *CookieConfig |
| 97 | + cookieAffinityConfig = &CookieConfig{} |
| 98 | + |
| 99 | + // Check the type of affinity that will be used |
| 100 | + at, err := parser.GetStringAnnotation(annotationAffinityType, ing) |
| 101 | + if err != nil { |
| 102 | + at = "" |
| 103 | + } |
| 104 | + |
| 105 | + switch at { |
| 106 | + case "cookie": |
| 107 | + cookieAffinityConfig = CookieAffinityParse(ing) |
| 108 | + |
| 109 | + default: |
| 110 | + glog.V(3).Infof("No default affinity was found for Ingress %v", ing.Name) |
| 111 | + |
| 112 | + } |
| 113 | + return &AffinityConfig{ |
| 114 | + AffinityType: at, |
| 115 | + CookieConfig: *cookieAffinityConfig, |
| 116 | + }, nil |
| 117 | + |
| 118 | +} |
0 commit comments