Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge current v1.3 to master (rc3) #1666

Merged
merged 9 commits into from
May 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Change Log

## [v1.3.0-rc3](https://github.com/containous/traefik/tree/v1.3.0-rc3) (2017-05-24)
[All Commits](https://github.com/containous/traefik/compare/v1.3.0-rc2...v1.3.0-rc3)

**Enhancements:**
- [#1658](https://api.github.com/repos/containous/traefik/issues/1658) Get testify/require dependency. ([timoreimann](https://api.github.com/users/timoreimann))

**Bug fixes:**
- [#1507](https://api.github.com/repos/containous/traefik/issues/1507) Create log folder if not present ([tanyadegurechaff](https://api.github.com/users/tanyadegurechaff))
- [#1604](https://api.github.com/repos/containous/traefik/issues/1604) [k8s] Ignore Ingresses with empty Endpoint subsets. ([timoreimann](https://api.github.com/users/timoreimann))
- [#1630](https://api.github.com/repos/containous/traefik/issues/1630) [k8s] Remove rule type path list. ([timoreimann](https://api.github.com/users/timoreimann))
- [#1635](https://api.github.com/repos/containous/traefik/issues/1635) Upgrade go-marathon to 15ea23e. ([timoreimann](https://api.github.com/users/timoreimann))
- [#1638](https://api.github.com/repos/containous/traefik/issues/1638) Fix behavior for PathPrefixStrip ([seryl](https://api.github.com/users/seryl))
- [#1654](https://api.github.com/repos/containous/traefik/issues/1654) fix: Empty Rancher Service Labels. ([ldez](https://api.github.com/users/ldez))

**Documentation:**
- [#1578](https://api.github.com/repos/containous/traefik/issues/1578) Add Marathon guide. ([Stibbons](https://api.github.com/users/Stibbons))
- [#1602](https://api.github.com/repos/containous/traefik/issues/1602) Re Orginise k8s docs to make 1.6 usage easier ([errm](https://api.github.com/users/errm))
- [#1642](https://api.github.com/repos/containous/traefik/issues/1642) Update changelog ([ldez](https://api.github.com/users/ldez))

## [v1.3.0-rc2](https://github.com/containous/traefik/tree/v1.3.0-rc2) (2017-05-16)
[All Commits](https://github.com/containous/traefik/compare/v1.3.0-rc1...v1.3.0-rc2)

Expand Down
4 changes: 2 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 17 additions & 5 deletions middlewares/stripPrefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,29 @@ type StripPrefix struct {

func (s *StripPrefix) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, prefix := range s.Prefixes {
if p := strings.TrimPrefix(r.URL.Path, strings.TrimSpace(prefix)); len(p) < len(r.URL.Path) {
r.URL.Path = p
r.Header[forwardedPrefixHeader] = []string{prefix}
r.RequestURI = r.URL.RequestURI()
s.Handler.ServeHTTP(w, r)
origPrefix := strings.TrimSpace(prefix)
if origPrefix == r.URL.Path {
r.URL.Path = "/"
s.serveRequest(w, r, origPrefix)
return
}

prefix = strings.TrimSuffix(origPrefix, "/") + "/"
if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
r.URL.Path = "/" + strings.TrimPrefix(p, "/")
s.serveRequest(w, r, origPrefix)
return
}
}
http.NotFound(w, r)
}

func (s *StripPrefix) serveRequest(w http.ResponseWriter, r *http.Request, prefix string) {
r.Header[forwardedPrefixHeader] = []string{prefix}
r.RequestURI = r.URL.RequestURI()
s.Handler.ServeHTTP(w, r)
}

// SetHandler sets handler
func (s *StripPrefix) SetHandler(Handler http.Handler) {
s.Handler = Handler
Expand Down
103 changes: 103 additions & 0 deletions middlewares/stripPrefix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package middlewares

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestStripPrefix(t *testing.T) {
tests := []struct {
desc string
prefixes []string
path string
expectedStatusCode int
expectedPath string
}{
{
desc: "no prefixes configured",
prefixes: []string{},
path: "/noprefixes",
expectedStatusCode: http.StatusNotFound,
},
{
desc: "wildcard (.*) requests",
prefixes: []string{"/"},
path: "/",
expectedStatusCode: http.StatusOK,
expectedPath: "/",
},
{
desc: "prefix and path matching",
prefixes: []string{"/stat"},
path: "/stat",
expectedStatusCode: http.StatusOK,
expectedPath: "/",
},
{
desc: "path prefix on exactly matching path",
prefixes: []string{"/stat/"},
path: "/stat/",
expectedStatusCode: http.StatusOK,
expectedPath: "/",
},
{
desc: "path prefix on matching longer path",
prefixes: []string{"/stat/"},
path: "/stat/us",
expectedStatusCode: http.StatusOK,
expectedPath: "/us",
},
{
desc: "path prefix on mismatching path",
prefixes: []string{"/stat/"},
path: "/status",
expectedStatusCode: http.StatusNotFound,
},
{
desc: "general prefix on matching path",
prefixes: []string{"/stat"},
path: "/stat/",
expectedStatusCode: http.StatusOK,
expectedPath: "/",
},
{
desc: "earlier prefix matching",
prefixes: []string{"/stat", "/stat/us"},
path: "/stat/us",
expectedStatusCode: http.StatusOK,
expectedPath: "/us",
},
{
desc: "later prefix matching",
prefixes: []string{"/mismatch", "/stat"},
path: "/stat",
expectedStatusCode: http.StatusOK,
expectedPath: "/",
},
}

for _, test := range tests {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
var gotPath string
server := httptest.NewServer(&StripPrefix{
Prefixes: test.prefixes,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotPath = r.URL.Path
}),
})
defer server.Close()

resp, err := http.Get(server.URL + test.path)
require.NoError(t, err, "Failed to send GET request")
assert.Equal(t, test.expectedStatusCode, resp.StatusCode, "Unexpected status code")

assert.Equal(t, test.expectedPath, gotPath, "Unexpected path")
})
}
}
67 changes: 18 additions & 49 deletions provider/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ var _ provider.Provider = (*Provider)(nil)

const (
annotationFrontendRuleType = "traefik.frontend.rule.type"
ruleTypePathPrefixStrip = "PathPrefixStrip"
ruleTypePathStrip = "PathStrip"
ruleTypePath = "Path"
ruleTypePathPrefix = "PathPrefix"

annotationKubernetesWhitelistSourceRange = "ingress.kubernetes.io/whitelist-source-range"
Expand Down Expand Up @@ -205,12 +202,8 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
}

if len(pa.Path) > 0 {
ruleType, unknown := getRuleTypeFromAnnotation(i.Annotations)
switch {
case unknown:
log.Warnf("Unknown RuleType '%s' for Ingress %s/%s, falling back to PathPrefix", ruleType, i.ObjectMeta.Namespace, i.ObjectMeta.Name)
fallthrough
case ruleType == "":
ruleType := i.Annotations[annotationFrontendRuleType]
if ruleType == "" {
ruleType = ruleTypePathPrefix
}

Expand Down Expand Up @@ -265,28 +258,25 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
}

if !exists {
log.Errorf("Endpoints not found for %s/%s", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
continue
log.Warnf("Endpoints not found for %s/%s", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
break
}

if len(endpoints.Subsets) == 0 {
log.Warnf("Service endpoints not found for %s/%s, falling back to Service ClusterIP", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{
URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(int(port.Port)),
Weight: 1,
}
} else {
for _, subset := range endpoints.Subsets {
for _, address := range subset.Addresses {
url := protocol + "://" + address.IP + ":" + strconv.Itoa(endpointPortNumber(port, subset.Ports))
name := url
if address.TargetRef != nil && address.TargetRef.Name != "" {
name = address.TargetRef.Name
}
templateObjects.Backends[r.Host+pa.Path].Servers[name] = types.Server{
URL: url,
Weight: 1,
}
log.Warnf("Endpoints not available for %s/%s", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
break
}

for _, subset := range endpoints.Subsets {
for _, address := range subset.Addresses {
url := protocol + "://" + address.IP + ":" + strconv.Itoa(endpointPortNumber(port, subset.Ports))
name := url
if address.TargetRef != nil && address.TargetRef.Name != "" {
name = address.TargetRef.Name
}
templateObjects.Backends[r.Host+pa.Path].Servers[name] = types.Server{
URL: url,
Weight: 1,
}
}
}
Expand Down Expand Up @@ -398,24 +388,3 @@ func (p *Provider) loadConfig(templateObjects types.Configuration) *types.Config
}
return configuration
}

func getRuleTypeFromAnnotation(annotations map[string]string) (ruleType string, unknown bool) {
ruleType = annotations[annotationFrontendRuleType]
for _, knownRuleType := range []string{
ruleTypePathPrefixStrip,
ruleTypePathStrip,
ruleTypePath,
ruleTypePathPrefix,
} {
if strings.ToLower(ruleType) == strings.ToLower(knownRuleType) {
return knownRuleType, false
}
}

if ruleType != "" {
// Annotation is set but does not match anything we know.
unknown = true
}

return ruleType, unknown
}
Loading