Skip to content

Commit ac8961e

Browse files
committed
feat: implement dynamic defaulting feature
- file/codegen/main.go and corresponding schema change This is to relax the schema of kong entities that are used as input for defaults. The relaxation is necessary as otherwise the user will have to specify a name in default values. This doesn't have any side-effects because the *kong.Type is not used anywhere else in Content. - file/builder.go file/reader.go - defaulter instantiation has been moved inside builder, this feels natural, defaulter being instantiated outside the builder seems odd and the only explanation is that I simply didn't think through when implementing defaulter - other changes override the default values that are registered Fix #89
1 parent 4de30cf commit ac8961e

File tree

6 files changed

+394
-22
lines changed

6 files changed

+394
-22
lines changed

file/builder.go

+38
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ func (b *stateBuilder) build() (*utils.KongRawState, *utils.KonnectRawState, err
4747
return nil, nil, err
4848
}
4949

50+
// defaulter
51+
var kongDefaults KongDefaults
52+
if b.targetContent.Info != nil {
53+
kongDefaults = b.targetContent.Info.Defaults
54+
}
55+
b.defaulter, err = defaulter(kongDefaults)
56+
if err != nil {
57+
return nil, nil, fmt.Errorf("creating defaulter: %w", err)
58+
}
59+
5060
// build
5161
b.certificates()
5262
b.caCertificates()
@@ -828,3 +838,31 @@ func pluginRelations(plugin *kong.Plugin) (cID, rID, sID string) {
828838
}
829839
return
830840
}
841+
842+
func defaulter(defaults KongDefaults) (*utils.Defaulter, error) {
843+
d, err := utils.GetKongDefaulter()
844+
if err != nil {
845+
return nil, err
846+
}
847+
if defaults.Route != nil {
848+
if err = d.Register(defaults.Route); err != nil {
849+
return nil, err
850+
}
851+
}
852+
if defaults.Service != nil {
853+
if err = d.Register(defaults.Service); err != nil {
854+
return nil, err
855+
}
856+
}
857+
if defaults.Upstream != nil {
858+
if err = d.Register(defaults.Upstream); err != nil {
859+
return nil, err
860+
}
861+
}
862+
if defaults.Target != nil {
863+
if err = d.Register(defaults.Target); err != nil {
864+
return nil, err
865+
}
866+
}
867+
return d, nil
868+
}

file/builder_test.go

+306-3
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,6 @@ func Test_stateBuilder_services(t *testing.T) {
372372
targetContent: tt.fields.targetContent,
373373
currentState: tt.fields.currentState,
374374
}
375-
d, _ := utils.GetKongDefaulter()
376-
b.defaulter = d
377375
b.build()
378376
assert.Equal(tt.want, b.rawState)
379377
})
@@ -1845,7 +1843,6 @@ func Test_stateBuilder_documents(t *testing.T) {
18451843

18461844
func Test_stateBuilder(t *testing.T) {
18471845
assert := assert.New(t)
1848-
rand.Seed(42)
18491846
type fields struct {
18501847
targetContent *Content
18511848
currentState *state.KongState
@@ -2091,9 +2088,315 @@ func Test_stateBuilder(t *testing.T) {
20912088
},
20922089
},
20932090
},
2091+
{
2092+
name: "entities with configurable defaults",
2093+
fields: fields{
2094+
targetContent: &Content{
2095+
Info: &Info{
2096+
SelectorTags: []string{"tag1"},
2097+
Defaults: KongDefaults{
2098+
Route: &kong.Route{
2099+
PathHandling: kong.String("v0"),
2100+
PreserveHost: kong.Bool(false),
2101+
RegexPriority: kong.Int(0),
2102+
StripPath: kong.Bool(false),
2103+
Protocols: kong.StringSlice("http", "https"),
2104+
RequestBuffering: kong.Bool(false),
2105+
},
2106+
Service: &kong.Service{
2107+
Port: kong.Int(443),
2108+
Protocol: kong.String("https"),
2109+
ConnectTimeout: kong.Int(5000),
2110+
WriteTimeout: kong.Int(5000),
2111+
ReadTimeout: kong.Int(5000),
2112+
},
2113+
Upstream: &kong.Upstream{
2114+
Slots: kong.Int(100),
2115+
Healthchecks: &kong.Healthcheck{
2116+
Active: &kong.ActiveHealthcheck{
2117+
Concurrency: kong.Int(5),
2118+
Healthy: &kong.Healthy{
2119+
HTTPStatuses: []int{200, 302},
2120+
Interval: kong.Int(0),
2121+
Successes: kong.Int(0),
2122+
},
2123+
HTTPPath: kong.String("/"),
2124+
Type: kong.String("http"),
2125+
Timeout: kong.Int(1),
2126+
Unhealthy: &kong.Unhealthy{
2127+
HTTPFailures: kong.Int(0),
2128+
TCPFailures: kong.Int(0),
2129+
Timeouts: kong.Int(0),
2130+
Interval: kong.Int(0),
2131+
HTTPStatuses: []int{429, 404, 500, 501, 502, 503, 504, 505},
2132+
},
2133+
},
2134+
Passive: &kong.PassiveHealthcheck{
2135+
Healthy: &kong.Healthy{
2136+
HTTPStatuses: []int{
2137+
200, 201, 202, 203, 204, 205,
2138+
206, 207, 208, 226, 300, 301, 302, 303, 304, 305,
2139+
306, 307, 308,
2140+
},
2141+
Successes: kong.Int(0),
2142+
},
2143+
Unhealthy: &kong.Unhealthy{
2144+
HTTPFailures: kong.Int(0),
2145+
TCPFailures: kong.Int(0),
2146+
Timeouts: kong.Int(0),
2147+
HTTPStatuses: []int{429, 500, 503},
2148+
},
2149+
},
2150+
},
2151+
HashOn: kong.String("none"),
2152+
HashFallback: kong.String("none"),
2153+
HashOnCookiePath: kong.String("/"),
2154+
},
2155+
},
2156+
},
2157+
Services: []FService{
2158+
{
2159+
Service: kong.Service{
2160+
Name: kong.String("foo-service"),
2161+
},
2162+
Routes: []*FRoute{
2163+
{
2164+
Route: kong.Route{
2165+
Name: kong.String("foo-route1"),
2166+
},
2167+
},
2168+
{
2169+
Route: kong.Route{
2170+
ID: kong.String("d125e79a-297c-414b-bc00-ad3a87be6c2b"),
2171+
Name: kong.String("foo-route2"),
2172+
},
2173+
},
2174+
},
2175+
},
2176+
{
2177+
Service: kong.Service{
2178+
Name: kong.String("bar-service"),
2179+
},
2180+
Routes: []*FRoute{
2181+
{
2182+
Route: kong.Route{
2183+
Name: kong.String("bar-route1"),
2184+
},
2185+
},
2186+
{
2187+
Route: kong.Route{
2188+
Name: kong.String("bar-route2"),
2189+
},
2190+
},
2191+
},
2192+
},
2193+
{
2194+
Service: kong.Service{
2195+
Name: kong.String("large-payload-service"),
2196+
},
2197+
Routes: []*FRoute{
2198+
{
2199+
Route: kong.Route{
2200+
Name: kong.String("dont-buffer-these"),
2201+
RequestBuffering: kong.Bool(false),
2202+
ResponseBuffering: kong.Bool(false),
2203+
},
2204+
},
2205+
{
2206+
Route: kong.Route{
2207+
Name: kong.String("buffer-these"),
2208+
RequestBuffering: kong.Bool(true),
2209+
ResponseBuffering: kong.Bool(true),
2210+
},
2211+
},
2212+
},
2213+
},
2214+
},
2215+
Upstreams: []FUpstream{
2216+
{
2217+
Upstream: kong.Upstream{
2218+
Name: kong.String("foo"),
2219+
Slots: kong.Int(42),
2220+
},
2221+
},
2222+
},
2223+
},
2224+
currentState: existingServiceState(),
2225+
},
2226+
want: &utils.KongRawState{
2227+
Services: []*kong.Service{
2228+
{
2229+
ID: kong.String("538c7f96-b164-4f1b-97bb-9f4bb472e89f"),
2230+
Name: kong.String("foo-service"),
2231+
Port: kong.Int(443),
2232+
Protocol: kong.String("https"),
2233+
ConnectTimeout: kong.Int(5000),
2234+
WriteTimeout: kong.Int(5000),
2235+
ReadTimeout: kong.Int(5000),
2236+
Tags: kong.StringSlice("tag1"),
2237+
},
2238+
{
2239+
ID: kong.String("dfd79b4d-7642-4b61-ba0c-9f9f0d3ba55b"),
2240+
Name: kong.String("bar-service"),
2241+
Port: kong.Int(443),
2242+
Protocol: kong.String("https"),
2243+
ConnectTimeout: kong.Int(5000),
2244+
WriteTimeout: kong.Int(5000),
2245+
ReadTimeout: kong.Int(5000),
2246+
Tags: kong.StringSlice("tag1"),
2247+
},
2248+
{
2249+
ID: kong.String("9e6f82e5-4e74-4e81-a79e-4bbd6fe34cdc"),
2250+
Name: kong.String("large-payload-service"),
2251+
Port: kong.Int(443),
2252+
Protocol: kong.String("https"),
2253+
ConnectTimeout: kong.Int(5000),
2254+
WriteTimeout: kong.Int(5000),
2255+
ReadTimeout: kong.Int(5000),
2256+
Tags: kong.StringSlice("tag1"),
2257+
},
2258+
},
2259+
Routes: []*kong.Route{
2260+
{
2261+
ID: kong.String("5b1484f2-5209-49d9-b43e-92ba09dd9d52"),
2262+
Name: kong.String("foo-route1"),
2263+
PreserveHost: kong.Bool(false),
2264+
RegexPriority: kong.Int(0),
2265+
StripPath: kong.Bool(false),
2266+
Protocols: kong.StringSlice("http", "https"),
2267+
RequestBuffering: kong.Bool(false),
2268+
PathHandling: kong.String("v0"),
2269+
Service: &kong.Service{
2270+
ID: kong.String("538c7f96-b164-4f1b-97bb-9f4bb472e89f"),
2271+
},
2272+
Tags: kong.StringSlice("tag1"),
2273+
},
2274+
{
2275+
ID: kong.String("d125e79a-297c-414b-bc00-ad3a87be6c2b"),
2276+
Name: kong.String("foo-route2"),
2277+
PreserveHost: kong.Bool(false),
2278+
RegexPriority: kong.Int(0),
2279+
StripPath: kong.Bool(false),
2280+
Protocols: kong.StringSlice("http", "https"),
2281+
RequestBuffering: kong.Bool(false),
2282+
PathHandling: kong.String("v0"),
2283+
Service: &kong.Service{
2284+
ID: kong.String("538c7f96-b164-4f1b-97bb-9f4bb472e89f"),
2285+
},
2286+
Tags: kong.StringSlice("tag1"),
2287+
},
2288+
{
2289+
ID: kong.String("0cc0d614-4c88-4535-841a-cbe0709b0758"),
2290+
Name: kong.String("bar-route1"),
2291+
PreserveHost: kong.Bool(false),
2292+
RegexPriority: kong.Int(0),
2293+
StripPath: kong.Bool(false),
2294+
Protocols: kong.StringSlice("http", "https"),
2295+
RequestBuffering: kong.Bool(false),
2296+
PathHandling: kong.String("v0"),
2297+
Service: &kong.Service{
2298+
ID: kong.String("dfd79b4d-7642-4b61-ba0c-9f9f0d3ba55b"),
2299+
},
2300+
Tags: kong.StringSlice("tag1"),
2301+
},
2302+
{
2303+
ID: kong.String("083f61d3-75bc-42b4-9df4-f91929e18fda"),
2304+
Name: kong.String("bar-route2"),
2305+
PreserveHost: kong.Bool(false),
2306+
RegexPriority: kong.Int(0),
2307+
StripPath: kong.Bool(false),
2308+
Protocols: kong.StringSlice("http", "https"),
2309+
RequestBuffering: kong.Bool(false),
2310+
PathHandling: kong.String("v0"),
2311+
Service: &kong.Service{
2312+
ID: kong.String("dfd79b4d-7642-4b61-ba0c-9f9f0d3ba55b"),
2313+
},
2314+
Tags: kong.StringSlice("tag1"),
2315+
},
2316+
{
2317+
ID: kong.String("ba843ee8-d63e-4c4f-be1c-ebea546d8fac"),
2318+
Name: kong.String("dont-buffer-these"),
2319+
PreserveHost: kong.Bool(false),
2320+
RegexPriority: kong.Int(0),
2321+
StripPath: kong.Bool(false),
2322+
Protocols: kong.StringSlice("http", "https"),
2323+
PathHandling: kong.String("v0"),
2324+
Service: &kong.Service{
2325+
ID: kong.String("9e6f82e5-4e74-4e81-a79e-4bbd6fe34cdc"),
2326+
},
2327+
Tags: kong.StringSlice("tag1"),
2328+
RequestBuffering: kong.Bool(false),
2329+
ResponseBuffering: kong.Bool(false),
2330+
},
2331+
{
2332+
ID: kong.String("13dd1aac-04ce-4ea2-877c-5579cfa2c78e"),
2333+
Name: kong.String("buffer-these"),
2334+
PreserveHost: kong.Bool(false),
2335+
RegexPriority: kong.Int(0),
2336+
StripPath: kong.Bool(false),
2337+
Protocols: kong.StringSlice("http", "https"),
2338+
PathHandling: kong.String("v0"),
2339+
Service: &kong.Service{
2340+
ID: kong.String("9e6f82e5-4e74-4e81-a79e-4bbd6fe34cdc"),
2341+
},
2342+
Tags: kong.StringSlice("tag1"),
2343+
RequestBuffering: kong.Bool(true),
2344+
ResponseBuffering: kong.Bool(true),
2345+
},
2346+
},
2347+
Upstreams: []*kong.Upstream{
2348+
{
2349+
ID: kong.String("1b0bafae-881b-42a7-9110-8a42ed3c903c"),
2350+
Name: kong.String("foo"),
2351+
Slots: kong.Int(42),
2352+
Healthchecks: &kong.Healthcheck{
2353+
Active: &kong.ActiveHealthcheck{
2354+
Concurrency: kong.Int(5),
2355+
Healthy: &kong.Healthy{
2356+
HTTPStatuses: []int{200, 302},
2357+
Interval: kong.Int(0),
2358+
Successes: kong.Int(0),
2359+
},
2360+
HTTPPath: kong.String("/"),
2361+
Type: kong.String("http"),
2362+
Timeout: kong.Int(1),
2363+
Unhealthy: &kong.Unhealthy{
2364+
HTTPFailures: kong.Int(0),
2365+
TCPFailures: kong.Int(0),
2366+
Timeouts: kong.Int(0),
2367+
Interval: kong.Int(0),
2368+
HTTPStatuses: []int{429, 404, 500, 501, 502, 503, 504, 505},
2369+
},
2370+
},
2371+
Passive: &kong.PassiveHealthcheck{
2372+
Healthy: &kong.Healthy{
2373+
HTTPStatuses: []int{
2374+
200, 201, 202, 203, 204, 205,
2375+
206, 207, 208, 226, 300, 301, 302, 303, 304, 305,
2376+
306, 307, 308,
2377+
},
2378+
Successes: kong.Int(0),
2379+
},
2380+
Unhealthy: &kong.Unhealthy{
2381+
HTTPFailures: kong.Int(0),
2382+
TCPFailures: kong.Int(0),
2383+
Timeouts: kong.Int(0),
2384+
HTTPStatuses: []int{429, 500, 503},
2385+
},
2386+
},
2387+
},
2388+
HashOn: kong.String("none"),
2389+
HashFallback: kong.String("none"),
2390+
HashOnCookiePath: kong.String("/"),
2391+
Tags: kong.StringSlice("tag1"),
2392+
},
2393+
},
2394+
},
2395+
},
20942396
}
20952397
for _, tt := range tests {
20962398
t.Run(tt.name, func(t *testing.T) {
2399+
rand.Seed(42)
20972400
b := &stateBuilder{
20982401
targetContent: tt.fields.targetContent,
20992402
currentState: tt.fields.currentState,

file/codegen/main.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,13 @@ func main() {
4747
return nil
4848
}
4949
schema := reflector.Reflect(file.Content{})
50-
schema.Definitions["Service"].AnyOf = anyOfNameOrID
50+
5151
schema.Definitions["FService"].AnyOf = anyOfNameOrID
5252

53-
schema.Definitions["Route"].AnyOf = anyOfNameOrID
5453
schema.Definitions["FRoute"].AnyOf = anyOfNameOrID
5554

56-
schema.Definitions["Consumer"].AnyOf = anyOfUsernameOrID
5755
schema.Definitions["FConsumer"].AnyOf = anyOfUsernameOrID
5856

59-
schema.Definitions["Upstream"].Required = []string{"name"}
6057
schema.Definitions["FUpstream"].Required = []string{"name"}
6158

6259
schema.Definitions["FTarget"].Required = []string{"target"}

0 commit comments

Comments
 (0)