forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
strategy.go
131 lines (110 loc) · 4.08 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
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/registry/generic"
"k8s.io/kubernetes/pkg/runtime"
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(obj runtime.Object) {
route := obj.(*api.Route)
route.Status = api.RouteStatus{}
// Limit to kind/name
// TODO: convert to LocalObjectReference
route.Spec.To = kapi.ObjectReference{Kind: route.Spec.To.Kind, Name: route.Spec.To.Name}
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(obj, old runtime.Object) {
route := obj.(*api.Route)
oldRoute := old.(*api.Route)
route.Status = oldRoute.Status
// Limit to kind/name
// TODO: convert to LocalObjectReference
route.Spec.To = kapi.ObjectReference{Kind: route.Spec.To.Kind, Name: route.Spec.To.Name}
}
// allocateHost allocates a host name ONLY if 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 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(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) generic.Matcher {
return &generic.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
}