Skip to content
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

launcher doctor subcommand #1197

Merged
merged 28 commits into from
May 26, 2023
Merged

launcher doctor subcommand #1197

merged 28 commits into from
May 26, 2023

Conversation

seejdev
Copy link
Contributor

@seejdev seejdev commented May 16, 2023

Fixed #1145

This PR adds a launcher doctor subcommand which runs several checkups to verify launcher installation health.

Notable things in this change:

  • Doctor can be used with standard launcher options, since it's using the same underlying parseOption function.
  • It can also fallback to reasonable defaults, even if a launcher installation, or config file, doesn't exist.
  • Checkups are run sequentially and results outputted in a consistent manner via writers; this enables the output to easily be directed to stdout or a file or whatever.
  • When run via CLI, the output will be colorized with a black background.
  • Adding new checkups and modifying existing ones is straightforward and the underlying reporting/outputting can interact with arbitrary diagnostic functionality.
  • Flare will now invoke doctor and pipe the output to the flare log file. Flare needs more work, but this is a start, and makes it more valuable.

cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Show resolved Hide resolved
cmd/launcher/doctor.go Show resolved Hide resolved
version.PrintFull()
cRunning.Println("\nRunning Kolide launcher checkups...")

checkups := []*checkup{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want to also check for --

  • Launcher process exists?
  • Launcher desktop process exists?
  • Is there anything we could check for osquery?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add osquery binary and logs checks next.

A launcher process report could be useful info

Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good

}
}

func (c *checkPointer) logConnections() {
func (c *checkPointer) Connections() map[string]string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine. Another route would be to take a logger in.

cmd/launcher/paths.go Outdated Show resolved Hide resolved
// checkup encapsulates a launcher health checkup
type checkup struct {
name string
check func() (string, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This signature feels very simple, maybe a good enough start. But I think there are a couple things I don't know how to do. (but maybe they don't matter)

First, I don't think we can differentiate between an unexpected failure in code, vs code works but a broken condition. Like, if we failed to open a boltdb connection that feels different than if some piece of data isn't what we need. Both are the same failure to the user, but one feels like a protocol error, and the other feels like the correct reporting of data.

Second, I'm not sure how to represent warnings here.

If I combine those, I wonder about func() (info string, status enum, error)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that suggestion makes it hard to differentiate the output for flare vs doctor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see now. It's in the check's run call. hmmmmm

cmd/launcher/doctor.go Outdated Show resolved Hide resolved
Comment on lines +97 to +100
name: "Root directory contents",
check: func() (string, error) {
return checkupRootDir(getFilepaths(k.RootDirectory(), "*"))
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't run this, but thinking aloud I see a difference in doctor and flare.

For doctor, I think this would just want to check if the directory exists. Maybe permissions. But flare would want to display the contents. I suspect with reasonable clever callers and signatures, this is supportable by the same underlying checkup function

cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
Copy link
Contributor

@James-Pickett James-Pickett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work! I like the overall approach and the UX. Looks like it will be straight forward to add new checkups in the future. like the other comments, I think we should get smart about consolidating flags and preventing drift between what launcher needs and what doctor thinks it needs

cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
cmd/launcher/doctor.go Outdated Show resolved Hide resolved
directionless
directionless previously approved these changes May 25, 2023
Copy link
Contributor

@directionless directionless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has value as it is, and I think it's isolated enough to be safe to merge.

I kinda want to quibble over:

  • how the output looks -- I really like the grouping, but not the forced colors
  • flare's internals
  • checkup interfaces

But I think we can iterate.

Comment on lines +28 to +29
// When launcher proper runs, it's expected that these defaults are their zero values
// However, special launcher subcommands such as launcher doctor can override these
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, this is an interesting way to do this.

directionless
directionless previously approved these changes May 25, 2023
Copy link
Contributor

@James-Pickett James-Pickett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

@directionless directionless merged commit 7a926d0 into kolide:main May 26, 2023
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a launcher doctor command
4 participants