forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
strategy.go
136 lines (113 loc) · 4.23 KB
/
strategy.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
132
133
134
135
136
package route
import (
"fmt"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
"github.com/openshift/origin/pkg/route"
"github.com/openshift/origin/pkg/route/api"
"github.com/openshift/origin/pkg/route/api/validation"
)
// HostGeneratedAnnotationKey is the key for an annotation set to "true" if the route's host was generated
const HostGeneratedAnnotationKey = "openshift.io/host.generated"
type routeStrategy struct {
runtime.ObjectTyper
kapi.NameGenerator
route.RouteAllocator
}
// NewStrategy initializes the default logic that applies when creating and updating
// Route objects via the REST API.
func NewStrategy(allocator route.RouteAllocator) routeStrategy {
return routeStrategy{
kapi.Scheme,
kapi.SimpleNameGenerator,
allocator,
}
}
func (routeStrategy) NamespaceScoped() bool {
return true
}
func (s routeStrategy) PrepareForCreate(ctx kapi.Context, obj runtime.Object) {
route := obj.(*api.Route)
route.Status = api.RouteStatus{}
err := s.allocateHost(route)
if err != nil {
// TODO: this will be changed when moved to a controller
utilruntime.HandleError(errors.NewInternalError(fmt.Errorf("allocation error: %v for route: %#v", err, obj)))
}
}
func (s routeStrategy) PrepareForUpdate(ctx kapi.Context, obj, old runtime.Object) {
route := obj.(*api.Route)
oldRoute := old.(*api.Route)
route.Status = oldRoute.Status
// Ignore attempts to clear the spec Host
// Prevents "immutable field" errors when applying the same route definition used to create
if len(route.Spec.Host) == 0 {
route.Spec.Host = oldRoute.Spec.Host
}
}
// allocateHost allocates a host name ONLY if the route doesn't specify a subdomain wildcard policy and
// the host name on the route is empty and an allocator is configured.
// It must first allocate the shard and may return an error if shard allocation fails.
func (s routeStrategy) allocateHost(route *api.Route) error {
if route.Spec.WildcardPolicy == api.WildcardPolicySubdomain {
// Don't allocate a host if subdomain wildcard policy.
return nil
}
if len(route.Spec.Host) == 0 && s.RouteAllocator != nil {
// TODO: this does not belong here, and should be removed
shard, err := s.RouteAllocator.AllocateRouterShard(route)
if err != nil {
return errors.NewInternalError(fmt.Errorf("allocation error: %v for route: %#v", err, route))
}
route.Spec.Host = s.RouteAllocator.GenerateHostname(route, shard)
if route.Annotations == nil {
route.Annotations = map[string]string{}
}
route.Annotations[HostGeneratedAnnotationKey] = "true"
}
return nil
}
func (routeStrategy) Validate(ctx kapi.Context, obj runtime.Object) field.ErrorList {
route := obj.(*api.Route)
return validation.ValidateRoute(route)
}
func (routeStrategy) AllowCreateOnUpdate() bool {
return false
}
// Canonicalize normalizes the object after validation.
func (routeStrategy) Canonicalize(obj runtime.Object) {
}
func (routeStrategy) ValidateUpdate(ctx kapi.Context, obj, old runtime.Object) field.ErrorList {
oldRoute := old.(*api.Route)
objRoute := obj.(*api.Route)
return validation.ValidateRouteUpdate(objRoute, oldRoute)
}
func (routeStrategy) AllowUnconditionalUpdate() bool {
return true
}
type routeStatusStrategy struct {
routeStrategy
}
var StatusStrategy = routeStatusStrategy{NewStrategy(nil)}
func (routeStatusStrategy) PrepareForUpdate(ctx kapi.Context, obj, old runtime.Object) {
newRoute := obj.(*api.Route)
oldRoute := old.(*api.Route)
newRoute.Spec = oldRoute.Spec
}
func (routeStatusStrategy) ValidateUpdate(ctx kapi.Context, obj, old runtime.Object) field.ErrorList {
return validation.ValidateRouteStatusUpdate(obj.(*api.Route), old.(*api.Route))
}
// Matcher returns a matcher for a route
func Matcher(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
return storage.SelectionPredicate{Label: label, Field: field, GetAttrs: getAttrs}
}
func getAttrs(obj runtime.Object) (objLabels labels.Set, objFields fields.Set, err error) {
route := obj.(*api.Route)
return labels.Set(route.Labels), api.RouteToSelectableFields(route), nil
}