-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
route.go
131 lines (116 loc) · 4.62 KB
/
route.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
Copyright 2018 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// route.go provides methods to perform actions on the route resource.
package test
import (
"fmt"
"net/http"
"time"
pkgTest "github.com/knative/pkg/test"
"github.com/knative/pkg/test/logging"
"github.com/knative/pkg/test/spoof"
"github.com/knative/serving/pkg/apis/serving/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
// CreateRoute creates a route in the given namespace using the route name in names
func CreateRoute(logger *logging.BaseLogger, clients *Clients, names ResourceNames) error {
route := Route(ServingNamespace, names)
LogResourceObject(logger, ResourceObjects{Route: route})
_, err := clients.ServingClient.Routes.Create(route)
return err
}
// CreateBlueGreenRoute creates a route in the given namespace using the route name in names.
// Traffic is evenly split between the two routes specified by blue and green.
func CreateBlueGreenRoute(logger *logging.BaseLogger, clients *Clients, names, blue, green ResourceNames) error {
route := BlueGreenRoute(ServingNamespace, names, blue, green)
LogResourceObject(logger, ResourceObjects{Route: route})
_, err := clients.ServingClient.Routes.Create(route)
return err
}
// UpdateRoute updates a route in the given namespace using the route name in names
func UpdateBlueGreenRoute(logger *logging.BaseLogger, clients *Clients, names, blue, green ResourceNames) (*v1alpha1.Route, error) {
route, err := clients.ServingClient.Routes.Get(names.Route, metav1.GetOptions{})
if err != nil {
return nil, err
}
newRoute := BlueGreenRoute(ServingNamespace, names, blue, green)
newRoute.ObjectMeta.ResourceVersion = route.ObjectMeta.ResourceVersion
LogResourceObject(logger, ResourceObjects{Route: newRoute})
patchBytes, err := createPatch(route, newRoute)
if err != nil {
return nil, err
}
return clients.ServingClient.Routes.Patch(names.Route, types.JSONPatchType, patchBytes, "")
}
// ProbeDomain sends requests to a domain until we get a successful
// response. This ensures the domain is routable before we send it a
// bunch of traffic.
func ProbeDomain(logger *logging.BaseLogger, clients *Clients, domain string) error {
client, err := pkgTest.NewSpoofingClient(clients.KubeClient, logger, domain, ServingFlags.ResolvableDomain)
if err != nil {
return err
}
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s", domain), nil)
if err != nil {
return err
}
// TODO(tcnghia): Replace this probing with Status check when we have them.
_, err = client.Poll(req, pkgTest.Retrying(pkgTest.MatchesAny, http.StatusNotFound, http.StatusServiceUnavailable))
return err
}
// RunRouteProber creates and runs a prober as background goroutine to keep polling Route.
// It stops when getting an error response from Route.
func RunRouteProber(logger *logging.BaseLogger, clients *Clients, domain string) <-chan error {
logger.Infof("Starting Route prober for route domain %s.", domain)
errorChan := make(chan error, 1)
go func() {
client, err := pkgTest.NewSpoofingClient(clients.KubeClient, logger, domain, ServingFlags.ResolvableDomain)
if err != nil {
errorChan <- err
close(errorChan)
return
}
// ResquestTimeout is set to 0 to make the polling infinite.
client.RequestTimeout = 0 * time.Minute
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s", domain), nil)
if err != nil {
errorChan <- err
close(errorChan)
return
}
// We keep polling Route if the response status is OK.
// If the response status is not OK, we stop the prober and
// generate error based on the response.
_, err = client.Poll(req, pkgTest.Retrying(disallowsAny, http.StatusOK))
if err != nil {
errorChan <- err
close(errorChan)
return
}
}()
return errorChan
}
// GetRouteProberError gets the error of route prober.
func GetRouteProberError(errorChan <-chan error, logger *logging.BaseLogger) error {
select {
case err := <-errorChan:
return err
default:
logger.Info("No error happens in the Route prober.")
return nil
}
}
func disallowsAny(response *spoof.Response) (bool, error) {
return true, fmt.Errorf("Get unexpected response %v", response)
}