From bc3256e1c5a49db21613639df21aeb8a8355b4ba Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Thu, 16 Jan 2020 11:08:55 +0200 Subject: [PATCH 1/2] Update Contour to v1.1 --- pkg/apis/projectcontour/v1/httpproxy.go | 52 +++++++++++--- .../v1/zz_generated.deepcopy.go | 71 ++++++++++++++++++- test/e2e-contour.sh | 4 +- 3 files changed, 116 insertions(+), 11 deletions(-) diff --git a/pkg/apis/projectcontour/v1/httpproxy.go b/pkg/apis/projectcontour/v1/httpproxy.go index 752e3db1c..59ad2e682 100644 --- a/pkg/apis/projectcontour/v1/httpproxy.go +++ b/pkg/apis/projectcontour/v1/httpproxy.go @@ -11,7 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// source: https://github.com/projectcontour/contour/blob/master/apis/projectcontour/v1/httpproxy.go package v1 import ( @@ -151,15 +150,20 @@ type Route struct { // The policy for rewriting the path of the request URL // after the request has been routed to a Service. // - // +kubebuilder:validation:Optional - PathRewrite *PathRewritePolicy `json:"pathRewritePolicy,omitempty"` + // +optional + PathRewritePolicy *PathRewritePolicy `json:"pathRewritePolicy,omitempty"` + // The policy for managing request headers during proxying + // +optional + RequestHeadersPolicy *HeadersPolicy `json:"requestHeadersPolicy,omitempty"` + // The policy for managing response headers during proxying + // +optional + ResponseHeadersPolicy *HeadersPolicy `json:"responseHeadersPolicy,omitempty"` } func (r *Route) GetPrefixReplacements() []ReplacePrefix { - if r.PathRewrite != nil { - return r.PathRewrite.ReplacePrefix + if r.PathRewritePolicy != nil { + return r.PathRewritePolicy.ReplacePrefix } - return nil } @@ -192,6 +196,10 @@ type Service struct { Name string `json:"name"` // Port (defined as Integer) to proxy traffic to since a service can have multiple defined. Port int `json:"port"` + // Protocol may be used to specify (or override) the protocol used to reach this Service. + // Values may be tls, h2, h2c. It ommitted protocol-selection falls back on Service annotations. + // +optional + Protocol *string `json:"protocol,omitempty"` // Weight defines percentage of traffic to balance traffic // +optional Weight uint32 `json:"weight,omitempty"` @@ -200,6 +208,12 @@ type Service struct { UpstreamValidation *UpstreamValidation `json:"validation,omitempty"` // If Mirror is true the Service will receive a read only mirror of the traffic for this route. Mirror bool `json:"mirror,omitempty"` + // The policy for managing request headers during proxying + // +optional + RequestHeadersPolicy *HeadersPolicy `json:"requestHeadersPolicy,omitempty"` + // The policy for managing response headers during proxying + // +optional + ResponseHeadersPolicy *HeadersPolicy `json:"responseHeadersPolicy,omitempty"` } // HTTPHealthCheckPolicy defines health checks on the upstream service. @@ -266,7 +280,7 @@ type ReplacePrefix struct { // If Prefix is not specified, all routing prefixes rendered // by the include chain will be replaced. // - // +kubebuilder:validation:Optional + // +optional // +kubebuilder:validation:MinLength=1 Prefix string `json:"prefix,omitempty"` @@ -286,7 +300,7 @@ type ReplacePrefix struct { // Exactly one field in this struct may be specified. type PathRewritePolicy struct { // ReplacePrefix describes how the path prefix should be replaced. - // +kubebuilder:validation:Optional + // +optional ReplacePrefix []ReplacePrefix `json:"replacePrefix,omitempty"` } @@ -295,6 +309,28 @@ type LoadBalancerPolicy struct { Strategy string `json:"strategy,omitempty"` } +// HeadersPolicy defines how headers are managed during forwarding +type HeadersPolicy struct { + // Set specifies a list of HTTP header values that will be set in the HTTP header + // +optional + Set []HeaderValue `json:"set,omitempty"` + // Remove specifies a list of HTTP header names to remove + // +optional + Remove []string `json:"remove,omitempty"` +} + +// HeaderValue represents a header name/value pair +type HeaderValue struct { + // Name represents a key of a header + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + Name string `json:"name"` + // Value represents the value of a header specified by a key + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + Value string `json:"value"` +} + // UpstreamValidation defines how to verify the backend service's certificate type UpstreamValidation struct { // Name of the Kubernetes secret be used to validate the certificate presented by the backend diff --git a/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go b/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go index 2af21c89d..98f2dcb25 100644 --- a/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go +++ b/pkg/apis/projectcontour/v1/zz_generated.deepcopy.go @@ -178,6 +178,48 @@ func (in *HeaderCondition) DeepCopy() *HeaderCondition { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HeaderValue) DeepCopyInto(out *HeaderValue) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderValue. +func (in *HeaderValue) DeepCopy() *HeaderValue { + if in == nil { + return nil + } + out := new(HeaderValue) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HeadersPolicy) DeepCopyInto(out *HeadersPolicy) { + *out = *in + if in.Set != nil { + in, out := &in.Set, &out.Set + *out = make([]HeaderValue, len(*in)) + copy(*out, *in) + } + if in.Remove != nil { + in, out := &in.Remove, &out.Remove + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeadersPolicy. +func (in *HeadersPolicy) DeepCopy() *HeadersPolicy { + if in == nil { + return nil + } + out := new(HeadersPolicy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Include) DeepCopyInto(out *Include) { *out = *in @@ -307,11 +349,21 @@ func (in *Route) DeepCopyInto(out *Route) { *out = new(LoadBalancerPolicy) **out = **in } - if in.PathRewrite != nil { - in, out := &in.PathRewrite, &out.PathRewrite + if in.PathRewritePolicy != nil { + in, out := &in.PathRewritePolicy, &out.PathRewritePolicy *out = new(PathRewritePolicy) (*in).DeepCopyInto(*out) } + if in.RequestHeadersPolicy != nil { + in, out := &in.RequestHeadersPolicy, &out.RequestHeadersPolicy + *out = new(HeadersPolicy) + (*in).DeepCopyInto(*out) + } + if in.ResponseHeadersPolicy != nil { + in, out := &in.ResponseHeadersPolicy, &out.ResponseHeadersPolicy + *out = new(HeadersPolicy) + (*in).DeepCopyInto(*out) + } return } @@ -328,11 +380,26 @@ func (in *Route) DeepCopy() *Route { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service) DeepCopyInto(out *Service) { *out = *in + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(string) + **out = **in + } if in.UpstreamValidation != nil { in, out := &in.UpstreamValidation, &out.UpstreamValidation *out = new(UpstreamValidation) **out = **in } + if in.RequestHeadersPolicy != nil { + in, out := &in.RequestHeadersPolicy, &out.RequestHeadersPolicy + *out = new(HeadersPolicy) + (*in).DeepCopyInto(*out) + } + if in.ResponseHeadersPolicy != nil { + in, out := &in.ResponseHeadersPolicy, &out.ResponseHeadersPolicy + *out = new(HeadersPolicy) + (*in).DeepCopyInto(*out) + } return } diff --git a/test/e2e-contour.sh b/test/e2e-contour.sh index ed0613643..b4c5cb2da 100755 --- a/test/e2e-contour.sh +++ b/test/e2e-contour.sh @@ -4,8 +4,10 @@ set -o errexit REPO_ROOT=$(git rev-parse --show-toplevel) +CONTOUR_VER="release-1.1" + echo '>>> Installing Contour' -kubectl apply -f https://projectcontour.io/quickstart/contour.yaml +kubectl apply -f https://raw.githubusercontent.com/projectcontour/contour/${CONTOUR_VER}/examples/render/contour.yaml kubectl -n projectcontour rollout status deployment/contour kubectl -n projectcontour get all From 558a1fc6e646f64b4de2cb7b5a5eddb0388263d4 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Thu, 16 Jan 2020 11:26:02 +0200 Subject: [PATCH 2/2] Add Linkerd l5d-dst-override header to Contour routes --- pkg/router/contour.go | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/pkg/router/contour.go b/pkg/router/contour.go index 2b320ceee..1a0412109 100644 --- a/pkg/router/contour.go +++ b/pkg/router/contour.go @@ -45,11 +45,21 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error { Name: primaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(100), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, primaryName), + }, + }, }, { Name: canaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(0), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, canaryName), + }, + }, }, }, }, @@ -68,11 +78,21 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error { Name: primaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(100), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, primaryName), + }, + }, }, { Name: canaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(0), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, canaryName), + }, + }, }, }, }, @@ -89,11 +109,21 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error { Name: primaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(100), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, primaryName), + }, + }, }, { Name: canaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(0), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, canaryName), + }, + }, }, }, }, @@ -232,11 +262,21 @@ func (cr *ContourRouter) SetRoutes( Name: primaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(primaryWeight), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, primaryName), + }, + }, }, { Name: canaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(canaryWeight), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, canaryName), + }, + }, }, }}, }, @@ -254,11 +294,21 @@ func (cr *ContourRouter) SetRoutes( Name: primaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(primaryWeight), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, primaryName), + }, + }, }, { Name: canaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(canaryWeight), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, canaryName), + }, + }, }, }, }, @@ -275,11 +325,21 @@ func (cr *ContourRouter) SetRoutes( Name: primaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(100), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, primaryName), + }, + }, }, { Name: canaryName, Port: int(canary.Spec.Service.Port), Weight: uint32(0), + RequestHeadersPolicy: &contourv1.HeadersPolicy{ + Set: []contourv1.HeaderValue{ + cr.makeLinkerdHeaderValue(canary, canaryName), + }, + }, }, }, }, @@ -364,3 +424,11 @@ func (cr *ContourRouter) makeRetryPolicy(canary *flaggerv1.Canary) *contourv1.Re } return nil } + +func (cr *ContourRouter) makeLinkerdHeaderValue(canary *flaggerv1.Canary, serviceName string) contourv1.HeaderValue { + return contourv1.HeaderValue{ + Name: "l5d-dst-override", + Value: fmt.Sprintf("%s.%.s.svc.cluster.local:%v", serviceName, canary.Namespace, canary.Spec.Service.Port), + } + +}