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

Slimmer /api package #5213

Merged
merged 5 commits into from
Jan 19, 2019
Merged

Slimmer /api package #5213

merged 5 commits into from
Jan 19, 2019

Conversation

notnoop
Copy link
Contributor

@notnoop notnoop commented Jan 18, 2019

Reduces api dependency footprint to ease client depedency management, specially in preparation to using go mod.

Following some internal conversation about nomad API, I noticed that the /api package surprisingly depends on many packages such as hashicorp's raft, lru, immutable-radix packages, and github.com/ugorji/go/codec library. github.com/ugorji/go/codec dependency causes pain to developers as it henders them from using a recent version, given that revision dates back to 2017-06-20.

With these changes, api package removes 30 dependencies, keeping dependency on 5 only. The difference in non-std dependencies from v0.8.7:

-github.com/armon/go-metrics
 github.com/gorhill/cronexpr
-github.com/hashicorp/consul/api
-github.com/hashicorp/errwrap
 github.com/hashicorp/go-cleanhttp
-github.com/hashicorp/go-immutable-radix
-github.com/hashicorp/go-msgpack/codec
-github.com/hashicorp/go-multierror
 github.com/hashicorp/go-rootcerts
-github.com/hashicorp/go-version
-github.com/hashicorp/golang-lru
-github.com/hashicorp/golang-lru/simplelru
-github.com/hashicorp/hcl
-github.com/hashicorp/hcl/hcl/ast
-github.com/hashicorp/hcl/hcl/parser
-github.com/hashicorp/hcl/hcl/scanner
-github.com/hashicorp/hcl/hcl/strconv
-github.com/hashicorp/hcl/hcl/token
-github.com/hashicorp/hcl/json/parser
-github.com/hashicorp/hcl/json/scanner
-github.com/hashicorp/hcl/json/token
-github.com/hashicorp/nomad/acl
 github.com/hashicorp/nomad/api/contexts
-github.com/hashicorp/nomad/helper
-github.com/hashicorp/nomad/helper/args
-github.com/hashicorp/nomad/helper/flatmap
-github.com/hashicorp/nomad/helper/uuid
-github.com/hashicorp/nomad/nomad/structs
-github.com/hashicorp/raft
-github.com/hashicorp/serf/coordinate
-github.com/mitchellh/copystructure
 github.com/mitchellh/go-homedir
-github.com/mitchellh/hashstructure
-github.com/mitchellh/reflectwalk
-github.com/ugorji/go/codec

fyi @blalor @jefferai

Mahmood Ali added 4 commits January 18, 2019 14:51
nomad/structs is an internal package and imports many libraries (e.g.
raft, codec) that are not relevant to api clients, and may cause
unnecessary dependency pain (e.g. `github.com/ugorji/go/codec`
version is very old now).

Here, we add a code generator that imports the relevant constants from
`nomad/structs`.

I considered using this approach for other structs, but didn't find a
quick viable way to reduce duplication.  `nomad/structs` use values as
struct fields (e.g. `string`), while `api` uses value pointer (e.g.
`*string`) instead.  Also, sometimes, `api` structs contain deprecated
fields or additional documentation, so simple copy-paste doesn't work.
For these reasons, I opt to keep the status quo.
`api.MockJob` is a test utility, that's only used by `command/agent`
package.  This moves it to the package and removes it from the public
API.
Embed pointer conversion functions in the API package to avoid
unnecessary package dependency.  `helper` package imports more
dependencies relevant for internal use (e.g. `hcl`).
`helpers.FormatFloat` function is only used in `api`.  Moving it and
marking it as private.  We can re-export it if we find value later.
@hashicorp-cla
Copy link

hashicorp-cla commented Jan 18, 2019

CLA assistant check
All committers have signed the CLA.

@@ -224,7 +221,7 @@ func (n *Nodes) monitorDrainNode(ctx context.Context, nodeID string,
return
}

if node.Status == structs.NodeStatusDown {
if node.Status == NodeStatusDown {
Copy link
Member

Choose a reason for hiding this comment

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

Ah! I see what you meant the other day when you said linters could help. This should have never happened, but thanks to the magic of goimports and human muscle memory it happens very easily!

Thanks for catching it!

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, interesting! How would a linter have helped here?

Copy link
Member

Choose a reason for hiding this comment

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

In the past api/ should never have imported from nomad/structs, so something like go list -f {{ .Deps }} | grep nomad/structs finding a match could work as a linter.

I think the idea now is that api/ shouldn't import anything from anywhere else in Nomad at all, so a similar linter that inspects api/'s deps on commit would be helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nomad few packages (e.g. plugins, api) that represent public "stable" API, and we have some opinions about the graph of package dependencies and layout. I proposed in a meeting formalizing it and adding a linter to enforce them.

nomad/structs/structs.go Outdated Show resolved Hide resolved
Given that the values will rarely change, specially considering that any
changes would be backward incompatible change.  As such, it's simpler to
keep syncing manually in the rare occasion and avoid the syncing code
overhead.
@notnoop notnoop merged commit f7e7b99 into master Jan 19, 2019
@notnoop notnoop deleted the b-api-separate branch January 19, 2019 02:04
@@ -6,7 +6,6 @@ import (
"testing"
"time"

"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/nomad/structs"
Copy link
Member

Choose a reason for hiding this comment

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

Having tests depend on the structs package and use the same constants (e.g DefaultBatchReschedulePolicy) but having the api package copy the values over so that they have to be manually synced seems wrong to me. What were we trying to optimize for here?

Copy link
Contributor Author

@notnoop notnoop Jan 19, 2019

Choose a reason for hiding this comment

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

I opted to have the tests check that api package have the same values as structs version, so tests fail if they are out of sync.

Given that vendoring tools (e.g. govendor) prune out test files, by default, the dependency on structs package wouldn't leak into clients of this package.

Does this make sense?

@github-actions
Copy link

I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants