feat: initial implementation of coder-doctor#3
Conversation
|
This pull request has been linked to Clubhouse Story #15961: Initial implementation of coder-doctor framework. |
|
Such a massive fan of this! We can use this package to validate clusters are properly configured when being added too. 🥳🥳🥳 |
| }, | ||
| } | ||
|
|
||
| for _, test := range tests { |
There was a problem hiding this comment.
you should autogenerate some tests (with dummy data for version fields we don't care about) for all of our supported versions
5fb3b2b to
f2f9988
Compare
|
|
||
| var _ = fmt.Stringer(StatePassed) | ||
|
|
||
| type CheckState int |
There was a problem hiding this comment.
Is there a reason we make these integers rather than strings?
That way we could eliminate the string function, and set the values to the const names.
There was a problem hiding this comment.
There wasn't a particular reason, no! I thought that integers were just the common way to do enums like this in Go.
A nice benefit of this is that the filtering can be done with bitwise operations (to determine whether to log each level), but of course we could do that with a set of bools or something too: https://github.com/cdr/coder-doctor/blob/31cb1c565fc42be9b40d9c68e634625287086b0b/internal/filterwriter/filter.go#L42-L60
I suppose another benefit is that comparisons should be faster with integers, because then it's just a numeric equality instead of string comparison
There was a problem hiding this comment.
Neato. Appreciate the context, and I'd agree with you here!
|
@johnstcn I wanted to get this initial version merged, can you take another look? I think you'd be the perfect reviewer for this since you've been working with the CLI more lately. It's not complete and just checks the version for now, but it's going to be harder to iterate on this with the existing PR due to the size. If you want to test locally, you should be able to clone the branch and run: This will use your current kubectl context (or you can also specify flags like --context) |
| emoji, err := state.Emoji() | ||
| assert.Success(t, "state.Emoji() error non-nil", err) | ||
| assert.True(t, "state.Emoji() is non-empty", len(emoji) > 0) | ||
| _ = state.MustEmoji() |
|
|
||
| type CoderVersionRequirement struct { | ||
| CoderVersion *semver.Version | ||
| KubernetesVersionMin *semver.Version |
There was a problem hiding this comment.
nit: we can probably use a semver.Constraint instead of specifying new versions, but this works for now.
https://pkg.go.dev/github.com/Masterminds/semver#hdr-Checking_Version_Constraints
There was a problem hiding this comment.
We can, but that API is a little more annoying to use because there's no Must variant. I suppose we could specify all of these as strings and parse at runtime?
There was a problem hiding this comment.
We're probably better off doing as much as possible at compile-time!
|
|
||
| // TODO: this is pretty arbitrary, use a defined verbosity similar to | ||
| // kubectl | ||
| if verbosity > 5 { |
There was a problem hiding this comment.
Ha, I usually set --verbosity=99 or something if I see something like that and want to be extra-verbose.
There was a problem hiding this comment.
kubectl has a really nicely-defined list, with criteria for what goes where -- I think we should adopt similar definitions, because otherwise (as a developer), it's difficult to know what level to log things, and it makes the level kinda useless for users: https://kubernetes.io/docs/reference/kubectl/_print/#kubectl-output-verbosity-and-debugging
johnstcn
left a comment
There was a problem hiding this comment.
Nice one!
./main check kubernetes --verbosity 9999
2021-08-16 15:23:50.681 [DEBUG] <version.go:67> selected coder version {"requested": "1.21.0", "selected": "1.21.0"}
PASS Coder 1.21.0 supports Kubernetes 1.19.0 to 1.22.0 (server version 1.20.8-gke.900)
internal/checks/kube/kubernetes.go
Outdated
| func (k *KubernetesChecker) Run(ctx context.Context) error { | ||
| err := k.writer.WriteResult(k.CheckVersion(ctx)) | ||
| if err != nil { | ||
| return err |
There was a problem hiding this comment.
Can we add more xerrors.Errorf(... about the place?
|
|
||
| kubernetesVersion, err := semver.NewVersion(versionInfo.GitVersion) | ||
| if err != nil { | ||
| return api.ErrorResult(checkName, "failed to parse server version", err) |
There was a problem hiding this comment.
Can we return a different message here than line 63 e.g. failed to parse git version info from server? Exact wording chef's choice.
There was a problem hiding this comment.
excellent catch! changed the error on line 63 to read: failed to unmarshal version info instead, to clarify what it's actually doing
|
|
||
| overrides.CurrentContext, err = cmd.Flags().GetString(clientcmd.FlagContext) | ||
| if err != nil { | ||
| return nil, err |
| var expected string | ||
| switch mode { | ||
| case humanwriter.OutputModeEmoji: | ||
| expected = "👍 human writer check test\n" + |
There was a problem hiding this comment.
nit: the pass and fail emoji are easy to confuse at a glance, suggest ✅ and ❌ for maximum distinguishability.
There was a problem hiding this comment.
hmm, I don't feel strongly about it and suggest we try it as it is for a bit to see what we think -- we can always change it later
|
|
||
| // This uses the RESTClient rather than Discovery().ServerVersion() | ||
| // because the latter does not accept a context. | ||
| body, err := k.client.Discovery().RESTClient().Get().AbsPath("/version").Do(ctx).Raw() |
There was a problem hiding this comment.
on second thought, I think splitting this into a KubernetesVersionChecker struct might be useful, it could use a DiscoveryClient interface or RESTClient as its arg instead of a kubernetes.Interface -- that would make it easier to unit test https://pkg.go.dev/k8s.io/[email protected]/kubernetes/typed/discovery/v1#DiscoveryV1Interface
but I think that's something for later
No description provided.