-
Notifications
You must be signed in to change notification settings - Fork 129
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
feat: add support to validate via Kong API #502
Conversation
So the goal of #190 is to do validation of data within the yaml file. For example, the following is a valid input as per
But if you try to do
The goal here is to take the entities in the file and then validate them against Kong's Admin API. |
@hbagdi thanks for the feedbacks and tips! I just pushed some changes. Sample input:
Sample output:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The approach is correct here. We know need to polish the code to get to merge.
cmd/validate.go
Outdated
validateEntities(ctx, ks.Routes, kongClient, "routes") | ||
validateEntities(ctx, ks.SNIs, kongClient, "snis") | ||
validateEntities(ctx, ks.Targets, kongClient, "targets") | ||
validateEntities(ctx, ks.Upstreams, kongClient, "upstreams") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RBAC resources are missing here. Can you include those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ops, missed this...what is/are the db entities associated to RBAC resources? I couldn't find them :\
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Roles and endpoint permissions (there are some others, but we lack support for them).
Lines 221 to 240 in 02208b2
func getEnterpriseRBACConfiguration(ctx context.Context, group *errgroup.Group, | |
client *kong.Client, state *utils.KongRawState) { | |
group.Go(func() error { | |
roles, err := GetAllRBACRoles(ctx, client) | |
if err != nil { | |
return fmt.Errorf("roles: %w", err) | |
} | |
state.RBACRoles = roles | |
return nil | |
}) | |
group.Go(func() error { | |
eps, err := GetAllRBACREndpointPermissions(ctx, client) | |
if err != nil { | |
return fmt.Errorf("eps: %w", err) | |
} | |
state.RBACEndpointPermissions = eps | |
return nil | |
}) | |
} |
https://docs.konghq.com/enterprise/2.5.x/admin-api/rbac/reference/#add-a-role
https://docs.konghq.com/enterprise/2.5.x/admin-api/rbac/reference/#add-a-role-endpoint-permission
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the pointers!
cmd/validate.go
Outdated
defer wg.Done() | ||
output := validate(ctx, values.Index(i).Interface(), kongClient, entityType) | ||
if output != "" { | ||
fmt.Println(output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't print to stdout but instead collect all of these as errors and bubble up all the way and then print them in the RunE fn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure my last change is what you were envisioning, but let me know otherwise!
cmd/validate.go
Outdated
func validateEntities(ctx context.Context, obj interface{}, kongClient *kong.Client, entityType string) { | ||
// call GetAll on entity | ||
method := reflect.ValueOf(obj).MethodByName("GetAll") | ||
entities := method.Call([]reflect.Value{})[0].Interface() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there are no tests, we will need to figure out a way to catch an error here.
Can you use init()
function to invoke code like this to ensure that it doesn't error/panic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I got you here, can you elaborate a bit please?
We can also do a bit more of checks like this:
method := reflect.ValueOf(obj).MethodByName("GetAll")
if !method.IsValid() {
// bla
}
entities := method.Call([]reflect.Value{})[0].Interface()
values := reflect.ValueOf(entities)
if values.Kind() != reflect.Slice {
// bla
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goal here is to statically ensure that all these state structs have the GetAll method (cause otherwise the code will panic at runtime).
One way to do that is to call all these reflect functions within an init function and then keep the references to the method in an array/map. Now, if there is a panic, it will happen on every call to main(). The likelihood of us catching that is much higher this way (until we have extensive testing happening for this project).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you mean something like this?
func callGetAll(obj interface{}) reflect.Value {
// call GetAll method on entity
method := reflect.ValueOf(obj).MethodByName("GetAll")
entities := method.Call([]reflect.Value{})[0].Interface()
return reflect.ValueOf(entities)
}
func validateGetAllMethod() {
dummyEmptyState, _ := state.NewKongState()
callGetAll(dummyEmptyState.Services)
callGetAll(dummyEmptyState.ACLGroups)
...
}
func init() {
rootCmd.AddCommand(validateCmd)
...
validateGetAllMethod()
}
I haven't found a nice way to store the method reference and call it later at validation time though :\ (without having to create a proper state at init time)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(without having to create a proper state at init time)
Why not do that?
So Something like this:
var store := map[string]somestruct{}
func init(){
// get a reference to the right method, throw a panic if the method doesn't exist
method:=getMethod()
store[entityType]= somestruct{ method:method, other: releavant-info}
}
And then at runtime, use the store to call the methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah initially I modelled exactly that, but this is going to implicitly add validation on the configuration file for all commands, right? I mean, if that's fine to you, that's fine to me :P
Also, in order to render the state, I was reusing the code of the initial validate..this would mean that the current validate
behaviour will become implicit at runtime, and maybe the --online
mode proposed here should become the "new default" for validate
.
Or am I missing something?
cmd/validate.go
Outdated
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
validateCmdKongStateFile []string | ||
validateCmdRBACResourcesOnly bool | ||
validateOnline bool | ||
validateOnlineErrors []error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please avoid a global state like this. Instead, change the function signatures to return []error
where needed.
cmd/validate.go
Outdated
func validateEntities(ctx context.Context, obj interface{}, kongClient *kong.Client, entityType string) { | ||
// call GetAll on entity | ||
method := reflect.ValueOf(obj).MethodByName("GetAll") | ||
entities := method.Call([]reflect.Value{})[0].Interface() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goal here is to statically ensure that all these state structs have the GetAll method (cause otherwise the code will panic at runtime).
One way to do that is to call all these reflect functions within an init function and then keep the references to the method in an array/map. Now, if there is a panic, it will happen on every call to main(). The likelihood of us catching that is much higher this way (until we have extensive testing happening for this project).
cmd/validate.go
Outdated
go func(i int) { | ||
defer wg.Done() | ||
if err := validate(ctx, values.Index(i).Interface(), kongClient, entityType); err != nil { | ||
validateOnlineErrors = append(validateOnlineErrors, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please returns errors from this function instead of collecting these in a global variable.
cmd/validate.go
Outdated
return err | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get rid off this function and call validateEntity from validateEntities directly.
cmd/validate.go
Outdated
return reflect.ValueOf(entities) | ||
} | ||
|
||
func validateGetAllMethod() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func validateGetAllMethod() { | |
// ensureGetAllMethod ensures at init time that `GetAll()` method exists on the relevant structs. | |
// If the method doesn't exist, the code will panic. This increases the likelihood of catching such an | |
// error during manual testing. | |
func ensureGetAllMethods() { |
cmd/validate.go
Outdated
if validateOnline { | ||
if err := validateWithKong(cmd, ks); err != nil { | ||
for _, e := range err { | ||
cprint.DeletePrintln(e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do a print without any colors. I don't think we use colors for errors anywhere else in the code-base.
cmd/validate.go
Outdated
No communication takes places between decK and Kong during the execution of | ||
this command. | ||
|
||
When ran with the --online flag, it also uses the 'validate' endpoint in Kong |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When ran with the --online flag, it also uses the 'validate' endpoint in Kong | |
No communication takes places between decK and Kong during the execution of | |
this command unless --online flag is used. |
cmd/validate.go
Outdated
if err != nil { | ||
return err | ||
} | ||
|
||
if validateOnline { | ||
if err := validateWithKong(cmd, ks); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if err := validateWithKong(cmd, ks); err != nil { | |
if errs := validateWithKong(cmd, ks); errs != nil { |
For readability
cmd/validate.go
Outdated
) | ||
|
||
var maxConcurrency = 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hbagdi what value you think would be most appropriate here? For now I pseudo-randomly set it to 100
, which is slightly lower than the nginx default of 128
.
Another option would be to have a default value but make it configurable with a CLI flag.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make it configurable from the get-go. Add a --parallelism
flag to the validate command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One small addition and we are ready to merge. Good work.
allErr := []error{} | ||
if err != nil { | ||
return []error{err} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a call to fetchKongVersion
using this client here? See cmd/ping.go for example.
This is to ensure that there is connectivity (network-level + authn) with Kong before we start throwing requests.
We will hold for a review from @rainest for merge as well. |
Fully implementing the For Lines 154 to 156 in 02208b2
decK's RBAC token handling is implemented globally, so nothing further is needed there: https://docs.konghq.com/deck/1.8.x/guides/kong-enterprise/#rbac |
cmd/common.go
Outdated
@@ -58,13 +58,22 @@ func workspaceExists(ctx context.Context, config utils.KongClientConfig, workspa | |||
return false, err | |||
} | |||
|
|||
exists, err := rootClient.Workspaces.ExistsByName(ctx, &workspaceName) | |||
exists, err := rootClient.Workspaces.Exists(ctx, &workspaceName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rainest I think the ExistsByName
method is not behaving as we expected here. I did create a teamA
workspace in Kong, but this method was still returning false
when checking it.
I think the Exists
method is the one we are looking for, but wanted to check it with you.
$ http :8001/workspaces
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 391
Content-Type: application/json; charset=utf-8
Date: Thu, 14 Oct 2021 07:54:08 GMT
Server: kong/2.5.1
X-Kong-Admin-Latency: 1
{
"data": [
{
"comment": null,
"config": {},
"created_at": 1634196302,
"id": "a8cf1f50-e9bd-40a6-a3ec-7477abca297a",
"meta": {},
"name": "teamA"
},
{
"comment": null,
"config": {},
"created_at": 1633083360,
"id": "b16c7d76-e917-47b2-9449-489be71b13cf",
"meta": {},
"name": "default"
}
],
"next": null
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep this out of scope from this PR. Can you open an issue to track this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it uses workspaceExists
as well, should we leave out from this PR the implementation of the --workspace
flag entirely then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, let's do that. We can have a follow-up PR to add support for workspaces. cc @rainest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to change this back to Exists()
. Exists()
only works if you have access to the default workspace. Most workspace existence checks should use ExistsByName()
: Exists()
is only still around to avoid breaking legacy code and because ExistsByName()
cannot take IDs as input.
If you're passing the name in you should be fine. Can you double-check that the workspace is in fact available? If so, and you're getting errors, can you show us what you're seeing in your admin API access log?
For me, after changing it back to ExistsByName()
:
11:20:57-0700 yagody $ /tmp/bdeck validate --online
validate entity 'services': HTTP status 400 (message: "schema violation (host: must not have a port)")
11:20:59-0700 yagody $ /tmp/bdeck validate --online --workspace foo
Warning: Workspace 'foo' specified via --workspace flag is different from workspace '' found in state file(s).
workspace doesn't exist: foo
11:21:15-0700 yagody $ http localhost:8001/workspaces name=foo
HTTP/1.1 201 Created
11:22:15-0700 yagody $ /tmp/bdeck validate --online --workspace foo
Warning: Workspace 'foo' specified via --workspace flag is different from workspace '' found in state file(s).
validate entity 'services': HTTP status 400 (message: "schema violation (host: must not have a port)")
# tail -3 /kong/servroot/logs/admin_access.log
172.23.0.1 - - [18/Oct/2021:18:22:20 +0000] "GET /foo/workspaces/foo HTTP/1.1" 200 692 "-" "Go-http-client/1.1"
172.23.0.1 - - [18/Oct/2021:18:22:20 +0000] "POST /foo/schemas/services/validate HTTP/1.1" 400 135 "-" "Go-http-client/1.1"
172.23.0.1 - - [18/Oct/2021:18:22:20 +0000] "POST /foo/schemas/routes/validate HTTP/1.1" 200 42 "-" "Go-http-client/1.1"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something is wrong with my environment (running it from docker-kong/compose
)? I switched back to use ExistsByName()
and following your steps doesn't work for me.
$ deck validate --online --workspace randomWS
Warning: Workspace 'randomWS' specified via --workspace flag is different from workspace '' found in state file(s).
workspace doesn't exist: randomWS
exit status 1
$ http localhost:8001/workspaces name=randomWS
HTTP/1.1 201 Created
$ deck validate --online --workspace randomWS
Warning: Workspace 'randomWS' specified via --workspace flag is different from workspace '' found in state file(s).
workspace doesn't exist: randomWS
exit status 1
I see the backend failing here:
kong_1 | 192.168.112.1 - - [19/Oct/2021:12:50:36 +0000] "POST /workspaces HTTP/1.1" 201 124 "-" "HTTPie/2.4.0"
kong_1 | 192.168.112.1 - - [19/Oct/2021:12:50:40 +0000] "GET / HTTP/1.1" 200 9967 "-" "Go-http-client/1.1"
kong_1 | 192.168.112.1 - - [19/Oct/2021:12:50:40 +0000] "GET /randomWS/workspaces/randomWS HTTP/1.1" 404 23 "-" "Go-http-client/1.1"
Kong version is:
$ http localhost:8001 | jq '.version'
"2.5.1"
Meanwhile, I reverted the ExistsByName
change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hbagdi are you able to replicate this 404 with ExistsByName()
? I can't fathom what would cause this in Gabriele's environment, but we do want to keep this as-is, else it'll require access to default.
Absent any obvious cause, I tried to see if this happened with workspaces whose name contained capitals or if it was something that happened in free mode, but neither results in a 404 for me.
The endpoint in question doesn't have any special logic in the API Lua source, it's just auto-generated. There could be something that explains it in the workspace entity lookup code, but I can't say where to look without replication. Asked FTT but they may not have any ideas either.
If you can't replicate, I'd recommend we leave this with ExistsByName()
and chalk up the observed issue as a fluke pending reports from others. If you can replicate, I suppose we then get to go dig through Lua source to see exactly where the lookup fails.
Upstream tests of the function are in place and don't fail, so as far as we know it works in general and this issue has to be some edge case we don't account for. If we can figure out what that is, we should address it in the upstream implementation.
cmd/common.go
Outdated
@@ -51,6 +65,15 @@ func workspaceExists(ctx context.Context, config utils.KongClientConfig, workspa | |||
return exists, nil | |||
} | |||
|
|||
func getWorkspaceName(workspace string, targetContent *file.Content) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func getWorkspaceName(workspace string, targetContent *file.Content) string { | |
func getWorkspaceName(workspaceFlag string, targetContent *file.Content) string { |
More self-documenting code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :)
cmd/validate.go
Outdated
method := reflect.ValueOf(obj).MethodByName("GetAll") | ||
entities := method.Call([]reflect.Value{})[0].Interface() | ||
return reflect.ValueOf(entities) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A further improvement to this function would be to add error as the second return value and check that in ensureGetAllMethod. An error should be returned if there is an error in looking up the method or calling the method (if any).
In the init()
then, print the error and exit rather than a panic. This is to make the UX a bit better.
Printing a helpful error and exiting is a better user experience than a CLI that does a stack dump on the user.
Even better, an error that is actionable. If the method lookup fails, then inform the user in the output that they should file a bug with Kong Inc.
This is not a blocker for merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I totally agree an obscure fail will not help users. I implemented this (example by forcing a fail):
$ deck validate --online
GetAll() method not found for *state.ServicesCollection. Please file a bug with Kong Inc.
exit status 1
Let me know what you think!
} | ||
if !workspaceExists { | ||
return []error{fmt.Errorf("workspace doesn't exist: %s", workspaceName)} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My one last product review comment: it must be possible for the user to validate their configuration without the existence of a workspace. It is usual for our users to validate their configuration before applying. This is a blocker for merging.
cc @rainest can help figure out alternative solutions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some workspace has to exist for you to check :)
You could have this fall back to trying against default if the workspace requested isn't available. It may fail, as you may not have permissions--using --workspace
here implies you don't, since otherwise you could omit the flag and check against default fine.
Users may try and just always supply --workspace
if that's their intended target for lack of understanding that it's only needed here to work around RBAC issues, since that's a fairly nuanced point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rainest Can we open a Github issue with the relevant context to track this problem? We must improve this later if not in this PR.
The PR can be merged after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So deck
already assumes the default workspace always exists: https://github.com/Kong/deck/blob/main/cmd/common.go#L31-L35
What we can do is simply overwriting the user input from --workspace
and set it to the default while printing a warning:
if !workspaceExists {
cprint.DeletePrintf("Warning: Workspace '%v' specified via --workspace flag "+
"doesn't exist. Validating against default workspace instead.\n", workspaceName)
workspaceName = ""
}
$ deck validate --online
validate entity 'services': HTTP status 400 (message: "schema violation (host: must not have a port)")
$ deck validate --online --workspace randomWS
Warning: Workspace 'randomWS' specified via --workspace flag is different from workspace '' found in state file(s).
Warning: Workspace 'randomWS' specified via --workspace flag doesn't exist. Validating against default workspace instead.
validate entity 'services': HTTP status 400 (message: "schema violation (host: must not have a port)")
If that is fine to you, I can push the changes, so that we don't have to open a different issue and tackle it at a different time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GGabriele Please open an issue to track this problem. Can skip for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cmd/validate.go
Outdated
) | ||
|
||
var maxConcurrency = 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make it configurable from the get-go. Add a --parallelism
flag to the validate command.
} | ||
os.Exit(1) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, we don't print errors, we return the error from this command and cobra prints and exists appropriately.
You will need to implement an error type that can hold multiple errors and print those.
Similar to t
cmd/validate.go
Outdated
@@ -74,4 +291,14 @@ func init() { | |||
"state", "s", []string{"kong.yaml"}, "file(s) containing Kong's configuration.\n"+ | |||
"This flag can be specified multiple times for multiple files.\n"+ | |||
"Use '-' to read from stdin.") | |||
validateCmd.Flags().BoolVar(&validateOnline, "online", | |||
false, "perform schema validation against Kong API.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
false, "perform schema validation against Kong API.") | |
false, "perform validations against Kong API. When this flag is used, validation is done via communication with Kong. This increases the time for validation but catches significant errors. No resource is created in Kong.") |
cmd/validate.go
Outdated
@@ -66,6 +84,205 @@ this command. | |||
}, | |||
} | |||
|
|||
func validateEntities(ctx context.Context, obj interface{}, kongClient *kong.Client, entityType string) []error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the functions that have been added in this PR should belong to either the util package or a new kong/validation
package. cmd
package must not have such business logic within itself.
Please move these functions.
} | ||
if !workspaceExists { | ||
return []error{fmt.Errorf("workspace doesn't exist: %s", workspaceName)} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@GGabriele Please open an issue to track this problem. Can skip for now.
cmd/validate.go
Outdated
if err != nil { | ||
return []error{err} | ||
} | ||
if !workspaceExists { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if decK is used against the open-source version of Kong (which has no concept of workspace)?
All workspace specific code must be executed only when the user supplies a workspace.
Codecov Report
@@ Coverage Diff @@
## main #502 +/- ##
==========================================
+ Coverage 50.42% 51.31% +0.89%
==========================================
Files 72 73 +1
Lines 7856 7857 +1
==========================================
+ Hits 3961 4032 +71
+ Misses 3546 3456 -90
- Partials 349 369 +20
Continue to review full report at Codecov.
|
@hbagdi I believe I addressed all your comments. Let me know what you think or if I missed something! |
utils/utils.go
Outdated
return result, fmt.Errorf("GetAll() method not found for %v. "+ | ||
"Please file a bug with Kong Inc", reflect.ValueOf(obj).Type()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return result, fmt.Errorf("GetAll() method not found for %v. "+ | |
"Please file a bug with Kong Inc", reflect.ValueOf(obj).Type()) | |
return result, fmt.Errorf("GetAll() method not found for type '%v'. "+ | |
"Please file a bug with Kong Inc", reflect.ValueOf(obj).Type()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
cmd/validate.go
Outdated
fmt.Println(err) | ||
os.Exit(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fmt.Println(err) | |
os.Exit(1) | |
panic(err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
validate/validate.go
Outdated
ctx context.Context, | ||
ks *state.KongState, | ||
client *kong.Client, | ||
parallelism int, | ||
rbacResourcesOnly bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead create a ValidaterOpt struct and then take that struct as input.
type ValidatorOpts struct {
.
.
}
func NewValidator(opt ValidatorOpt) {
.
.
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
validate/validate.go
Outdated
func (v ErrorsWrapper) Error() string { | ||
var errStr string | ||
for _, e := range v.Errors { | ||
errStr += fmt.Sprintf("%s\n", e.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not add a print after the last error in the array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Hi! In order to get more familiarity with the tool and the codebase, I decided to give it a try and work on the proposal discussed in #190
Sample usage:
Sample input:
Sample output:
Let me know what you think! :)