-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Query a remote Elasticsearch for License and features #7946
Conversation
libbeat/licenser/elastic_fetcher.go
Outdated
// Fetch connect to the cluster and call the xpack api parses the data and return an Info object. | ||
func (f *ElasticFetcher) Fetch() (*License, error) { | ||
status, body, err := f.client.Request("GET", xPackURL, "", params, nil) | ||
if status != statusOK { |
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 the license is Apache, it will return a 405 here as the endpoint does not exist.
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, I was not sure of the behavior in the OSS world :)
A few questions ported from #7953 Open questions: |
a867016
to
e26b92c
Compare
This code is ready for review. |
🤦♂️ forgot to run the test with the data race on. |
libbeat/licenser/manager.go
Outdated
} | ||
|
||
// NewWithFetcher takes a fetcher and return a license manager. | ||
func NewWithFetcher(fetcher Fetcher, duration time.Duration, gracePeriod time.Duration) *Manager { |
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 think I should pass a Setting Object here so we can define the duration, grace period and anything related to the backoff.
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.
Are you thinking of config options that are also exposed to the user?
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 don't think we need to expose any options to the end users, they could put a really large refresh delay.. which is probably not what we want.
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.
- Could we add some integration tests with Elasticsearch search. Even if we only test if basic is enabled it will tell us very quickly in case something in the API endpoint for format changed on the ES side.
- How does this handle trial licenses? I wonder if that is something we should fetch and at least report in the logs. This could make debugging easier when we see in the logs it's a trial and the user tells us it was working and then stopped ...
I didn't check all the code in detail more functionality wise so would be good if someone else has a more detailed look.
libbeat/licenser/elastic_fetcher.go
Outdated
} | ||
s := string(b[1 : len(b)-1]) | ||
license, ok := licenseLookup[s] | ||
if ok { |
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.
Nit: Normally we check for the error an return the error inside the if clause and the flow to the end of the method is the non error flow.
libbeat/licenser/elastic_fetcher.go
Outdated
|
||
s := string(b[1 : len(b)-1]) | ||
state, ok := stateLookup[s] | ||
if ok { |
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.
See comment above
|
||
t.Run("200 response", func(t *testing.T) { | ||
h := func(w http.ResponseWriter, r *http.Request) { | ||
json, err := ioutil.ReadFile("data/xpack.json") |
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.
Could we make this data/xpack-6.4.1.json
(or whatever version it is) and then run a glob here? This makes it easy to add more test files for different versions in the future.
It allows us to also add files from older ES versions.
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.
++ love it.
libbeat/licenser/license.go
Outdated
Monitoring monitoring `json:"monitoring"` | ||
Rollup rollup `json:"rollup"` | ||
Security security `json:"security"` | ||
Watcher watcher `json:"watcher"` |
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.
Should we track in here all the features or only the ones that Beats actually uses / requires?
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've exposed the current features, only Graph isn't used is the less relevant for us, but we can revisit that when a new feature is exposed via elasticsearch.
libbeat/licenser/manager.go
Outdated
} | ||
|
||
// NewWithFetcher takes a fetcher and return a license manager. | ||
func NewWithFetcher(fetcher Fetcher, duration time.Duration, gracePeriod time.Duration) *Manager { |
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.
Are you thinking of config options that are also exposed to the user?
libbeat/licenser/manager.go
Outdated
// Stop terminates the license manager, the go routine will be stopped and the cached license will | ||
// be removed and no more checks can be done on the manager. | ||
func (m *Manager) Stop() { | ||
defer m.log.Info("license manager stopped") |
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.
Should we have a lock on stop to make sure it's not called in the middle of a worker starting for example?
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.
This is a valid case, let me make a 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.
I refactored Stop
so the shutdown is more explicit and sync with the worker, this makes the behavior of stopping the manager predictable and the callbacks are calling order is more sane.
libbeat/licenser/manager.go
Outdated
} | ||
|
||
func (m *Manager) worker() { | ||
m.log.Debug("starting periodic updater") |
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.
could you mention in the log line that this is the period license check
libbeat/licenser/manager.go
Outdated
func NewWithFetcher(fetcher Fetcher, duration time.Duration, gracePeriod time.Duration) *Manager { | ||
m := &Manager{ | ||
fetcher: fetcher, | ||
duration: duration, |
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 do you expect as a default duration?
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.
This is a good question, not sure what would be the best timing for that.
I've looked at Logstash and they refresh every 30sec, https://github.com/elastic/logstash/blob/master/x-pack/lib/license_checker/licensed.rb#L34-L42
Maybe every minute would be a good default, WDYT?
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.
30s sounds like a bit too much TBH. If we have 100'000 Beats that would mean 100'000 additional requests every 30s. In most cases I would not expect the license to change so I was more thinking of something like once a day.
If someone is having a trial license, we should probably check more often.
Perhaps we could do something like "check once per day" and but also check every time on reconnect. Alternative we could back off over time or make it more random?
One thing that would be nice if in the future with central management it could be triggered there that a license check should happen on all Beats.
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 believe the current monitoring elasticsearch reporter check every 30 seconds, I understand having a 100k beats could increase the load on the server.
A check every few hours should be fine because I find once a day a bit too infrequent, I will think about saner defaults
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.
monitoring only checks every 30s on init. After license is found it won't update license information. but then, for monitoring it's not a license check, but test if features+API endpoint is available in ES.
Some randomized backoff on initial check would be nice. Once license data are available, we don't need to check now. We could also cache license check results, so to reduce checks even between restarts. Maybe we can add a check to the ES output triggering a license checks once it finds the version is updated?
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 will add some initial jitter at startup.
Maybe we can add a check to the ES output triggering a license checks once it finds the version is updated?
I will create a followup issue for 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.
Is there a need to inspect licenses from OSS Beats? If not, then perhaps this belongs be in x-pack/
?
@andrewkroh It also check for features, so we can refactor the monitoring code to use the same license checker instead of using the onConnect handler from the elasticsearch client so we only have one way to check it. But this is will be mostly used by Beatless and config management at first. |
I have added a simple integration test for the '_xpack' endpoint, this is only a sanity check.
Do we still have a trial license type returned? I am not sure I will take a deeper look. |
I will need this feature to be in OSS for ILM. |
Adding Trial response for the |
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.
Change LGTM. Would be nice to have some go based integration tests (e.g. fetcher_integration_test.go
+ build tag integration
).
@urso we have a sanity check there https://github.com/elastic/beats/pull/7946/files#diff-52042abe2d3906a09d82626f97c7ab29R1 :) I was surprised how easy it was, it also catched one bug. |
libbeat/licenser/manager.go
Outdated
// Manager keeps tracks of license management, it uses a fetcher usually the ElasticFetcher to | ||
// retrieve a licence from a specific cluster. | ||
// | ||
// Starting the manager will starts a go routine to periodically query the license fetcher. |
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.
s/will starts/will start/
libbeat/licenser/manager.go
Outdated
// retrieve a licence from a specific cluster. | ||
// | ||
// Starting the manager will starts a go routine to periodically query the license fetcher. | ||
// if an error occur on the fetcher we will retries until we successfully |
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.
s/will retries/will retry/
Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
1384ec8
to
b0d4ca4
Compare
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
This adds support to Beats for index lifecycle management. The PR is currently work in progress. It works against a snapshot build of Elasticsearch from the ILM branch and the predefined configs in the metricbeat.yml file. *Blocked* This PR is currently blocked as the Elasticsearch ilm branch is not yet merged into master. Also the license checker in elastic#7946 needs to be merged first. *TODO* * [x] Add License Check elastic#7946 * [x] Add ES version check * [x] Finish implementation of setup command for policy and test it * [ ] Add tests * [x] Add docs * [x] Check all todos For more details see elastic#7935 To test this feature, Metricbeat can be run as following: `./metricbeat -e -E output.elasticsearch.ilm.enabled=true`. It currently also requires a version of Elasticsearch from the branch `index-lifecycle` to be running. The policy loaded looks as following: ``` { "policy": { "type": "timeseries", "phases": { "hot": { "actions": { "rollover": { "max_size": "25gb", "max_age": "30d" } } } } } } ```
* License manager Implements a License manager inside beats, as we development more features that depends on the licensing and the capabilities of a remote cluster we need a unique way to access that information. This commit implements the following: Add a License manager that can be started at the beginning of the beats instance initialization. The manager takes a fetcher, currently we only support Elasticsearch as the license backend but we could add support for an Logstash endpoint that could proxy the license. Notes: - By default when the manager is started, no license is available, calling `Get()` on the manager will return a license not found. - The manager will periodically retrieve the license from the fetcher. - When an error occurs on the periodic check, the license wont be invalidated right away but will enter a grace period, after this period the license will be invalidated and will replaced by the OSS license. - License and capabilities and be retrieved by calling `Get()` or registering a type implementing the `Watcher` interface.
Implements a License manager inside beats, as we development more
features that depends on the licensing and the capabilities of a remote
cluster we need a unique way to access that information. This commit
implements the following:
Add a License manager that can be started at the beginning of the beats
instance initialization. The manager takes a fetcher, currently we only
support Elasticsearch as the license backend but we could add support
for an Logstash endpoint that could proxy the license.
Notes:
By default when the manager is started, no license is available,
calling
Get()
on the manager will return a license not found.The manager will periodically retrieve the license from the fetcher.
When an error occurs on the periodic check, the license wont be
invalidated right away but will enter a grace period, after this period
the license will be invalidated and will replaced by the OSS license.
License and capabilities and be retrieved by calling
Get()
orregistering a type implementing the
Watcher
interface.