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

Merge distributive and goss #113

Open
eirslett opened this issue Nov 2, 2015 · 15 comments
Open

Merge distributive and goss #113

eirslett opened this issue Nov 2, 2015 · 15 comments

Comments

@eirslett
Copy link

eirslett commented Nov 2, 2015

https://github.com/aelsabbahy/goss

Looks like goss does (almost) exactly the same thing as distributive. Would it be possible to merge the two projects? Instead of reimplementing every feature/reinventing the wheel, they could combine efforts and build more features.

@aelsabbahy

@langston-barrett
Copy link
Contributor

Technically, this probably wouldn't be too complex. Distributive has a lot more aspects that it can examine, but is separated into packages that could just as easily be used as part of goss. What do you think @aelsabbahy?

@aelsabbahy
Copy link

Just found out about Distributive this morning and https://github.com/milosgajdos83/servpeek by @milosgajdos83 a few days earlier.

Perhaps we can all agree to a shared interface for probing system resources and have that be maintained as a separate package/repo, much like specinfra is a separate gem from serverspec? I haven't looked at the Distributive code yet, but would be interesting to see what checks are there and how each of us approached the problem.

@stevendborrelli
Copy link

I like the idea of a shared interface library.

Maybe create a new top-level project that provides a standard way of checking resources on servers that is easy to embed in other go programs.

@langston-barrett
Copy link
Contributor

@aelsabbahy Here's Distributive's interface:

// Check is a unified interface for health checks, it defines only the minimal
// necessary behaviors, while allowing each check to parse and store type-safe
// parameters.
type Check interface {
    // ID is a uniquely identifying check name, like "running" or "temp"
    ID() string
    // New both validates the JSON-provided parameters (list of strings),
    // and parses and stores them in an internal, typed field for later access.
    New(parameters []string) (Check, error)
    // Status returns the status of the check at the instant it is called.
    //
    // msg is a descriptive, human-readable description of the status.
    //
    // code is exit code defining whether or not this check is passing.  0 is
    // considered passing, 1 is failing, with other values reserved for later
    // use.
    Status() (code int, msg string, err error)
}

This is less than ideal, because each check has to parse its arguments from a string if they are actually of a different type (e.g. Port parses its argument to a uint16). The big question for our interface is probably how to maintain both a generic interface and type safety.

@aelsabbahy
Copy link

Disributive and goss are almost exactly the same
Tried out at Distributive briefly this morning (but haven't looked at code yet) and it has more in common with goss than I originally thought:

  • Both use JSON as a configuration format to define checks
  • goss validate --format nagios has almost the same exact use-case as distributive (integration with monitoring tools and health checks)

Common interface
Regarding common interface, I was thinking it would be one level lower than checks (goss use-case is more than just checks). Was thinking something along the lines of how puppet/chef providers work. Checks can be built on top of that, but the library itself should be more generic so it can be leveraged in other ways. For example, package can be something like (full-disclosure, this is very similar to goss's package interface):

// Any package would have to implement this interface
type Package interface {
    // Name of the package
    Name() string
    // Whether the package is installed
    Installed() (bool, error)
    // Versions of the package that are installed
    Versions() ([]string, error)
}

At that point, one can build DebPackage, RpmPackage, GemPackage, or even NullPackage. And can leverage the information in any checking system they want.

From goss's perspective, here are the important requirements from a probing library:

  • That it derives system state (not limited to checks), goss and other tools can do whatever they want with that information
  • It relies as little as possible on external tools, user shouldn't have to install lsof or netcat
  • Library should be efficient. For example: looking up 1,000 different ports or pids should only parse /proc/net/tcp once

@langston-barrett
Copy link
Contributor

@aelsabbahy Agreed on all points. As a starting point, Distributive has subpackages memstatus, fsstatus, netstatus, systemdstatus, usrstatus, and dockerstatus. I'll email you and we can start a planning document.

@aelsabbahy
Copy link

Awesome! 👍

@langston-barrett
Copy link
Contributor

We're beginning collaboration on this document. Anybody can comment here (or on the doc) with input!

@eirslett
Copy link
Author

eirslett commented Nov 4, 2015

From the doc:

The only dependencies currently are package commands and service command which are guaranteed to be there.

In an OS with systemd (CentOS, future versions of Debian...) you don't have "service", you have "systemctl". There's no point in abstracting away the difference between them though, so it's maybe best to have one sysvinit package and one systemd package?

@eirslett
Copy link
Author

eirslett commented Nov 4, 2015

// Any package would have to implement this interface
type Package interface {
    // Name of the package
    Name() string
    // Whether the package is installed
    Installed() (bool, error)
    // Versions of the package that are installed
    Versions() ([]string, error)
}

This looks like a "fact" to me (similar to puppet/ansible facts). One type of check could be to evaluate the facts' values against some criteria. (But that can't model things like health checks based on http calls)

I'm sure this kind of library could be used from consul as well (@armon ?), I believe consul implements almost the same thing for HTTP checks today.

@aelsabbahy
Copy link

@eirslett

so it's maybe best to have one sysvinit package and one systemd package?

Agree, with a small modification s/package/systemd struct that implements Service interface/.

To clarify: service is the only external command being called explicitly in goss because dbus is used directly for systemctl, the intent of that sentence was to just highlight the importance limiting the reliance on external tools/commands as much as possible. Apologies if that wasn't clear. Ex:

Interface:

Implementations:

This looks like a "fact" to me (similar to puppet/ansible facts).

Looks more like a provider to me, take a look at the puppet provider for file. The owner, group, mode getters look like the above pseudo-code. Puppet providers also have setters, but I think that's out of scope for this library.

For this library to be compatible with goss I'm going to have to insist that it's not based on/limited to checks, but rather focused on the lower level of probing the system for state. Checks can be built upon that, but shouldn't be in the same library.

One type of check could be to evaluate the facts' values against some criteria. (But that can't model things like health checks based on http calls)

Not sure I follow.. couldn't a health check simply leverage the provider?

func HealthCheckUsingUrlProvider(url string) bool {
    // URLProvider being an example provider from the library in our discussion
    u := URLProvider.New(url)

    if u.Code() == "200" {
      return true
    }
    return false
}

@eirslett
Copy link
Author

eirslett commented Nov 4, 2015

Yes; a health check should be able to use a provider like that.

@eirslett
Copy link
Author

eirslett commented Nov 4, 2015

@siddharthist You've already done a great job on the distributive project, and it helps us a lot at FINN!

But how would you feel about merging every feature that distributive has, into goss (given it fits into goss' design?), and then adapt goss for the mantl project going forward? It doesn't look like there are any directly conflicting interests between the two projects; no use cases that distributive solves, but goss, on the other hand, is explicitly meant not to solve?

@langston-barrett
Copy link
Contributor

@eirslett That sounds just fine to me! I think maintaining a separate library would still be of interest for other projects. @stevendborrelli What do you think?

langston-barrett added a commit that referenced this issue Mar 27, 2016
Use goss's methods, relying on runc's library or goss itself
Fixes #119 (hopefully). If not, then it's a bug in runc.
Progress on #113
@langston-barrett
Copy link
Contributor

I'm in the process of beginning to use goss as a library for distributive where its resources align. I'll keep track of progress here:

  • addr
  • command
  • dns
  • file
  • group - PR is in!
  • package - branch created, waiting on Support Pacman package manager goss-org/goss#60
  • port - I prefer distributive's handling for right now. goss has a FIXME in its code.
  • process - using go-ps
  • user - PR is in!

langston-barrett added a commit that referenced this issue Mar 28, 2016
Use goss's methods, relying on runc's library or goss itself
Fixes #119 (hopefully). If not, then it's a bug in runc.
Progress on #113
@langston-barrett langston-barrett modified the milestone: v0.2.6 Mar 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants