-
Notifications
You must be signed in to change notification settings - Fork 204
Allow agent to override fleet settings #11524
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
base: main
Are you sure you want to change the base?
Changes from 5 commits
e2eb13a
df77bf7
4ae51b3
1929087
1651558
3a5a76f
58a2557
d80817c
cb7fe0c
34717c0
a8f379c
cfb47b3
7ff467c
aa22ec2
feb9132
b13ce20
a34fd86
7bc72a1
4e8cf1b
baf469b
a2709d9
9822981
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| agent: | ||
| monitoring: | ||
| enabled: true | ||
| use_output: default | ||
| logs: false | ||
| metrics: true | ||
| http: | ||
| port: 6774 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| // or more contributor license agreements. Licensed under the Elastic License 2.0; | ||
| // you may not use this file except in compliance with the Elastic License 2.0. | ||
|
|
||
| package application | ||
|
|
||
| import ( | ||
| "github.com/elastic/elastic-agent/internal/pkg/agent/application/coordinator" | ||
| "github.com/elastic/elastic-agent/internal/pkg/capabilities" | ||
| "github.com/elastic/elastic-agent/internal/pkg/config" | ||
| "github.com/elastic/elastic-agent/pkg/core/logger" | ||
| ) | ||
|
|
||
| func PatchFleetConfig(log *logger.Logger, | ||
| rawConfig *config.Config, // original config from fleet, this one won't reload | ||
| caps capabilities.Capabilities, | ||
| isManaged bool, | ||
| ) func(change coordinator.ConfigChange) coordinator.ConfigChange { | ||
| if !isManaged || // no need to override fleet config when not managed | ||
| caps == nil || !caps.AllowFleetOverride() { | ||
| return noop | ||
| } | ||
|
|
||
| return func(change coordinator.ConfigChange) coordinator.ConfigChange { | ||
| newConfig := change.Config() | ||
| if err := newConfig.Merge(rawConfig); err != nil { | ||
| log.Errorf("error merging fleet config into config change: %v", err) | ||
|
||
| } | ||
|
|
||
| return change | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| // or more contributor license agreements. Licensed under the Elastic License 2.0; | ||
| // you may not use this file except in compliance with the Elastic License 2.0. | ||
|
|
||
| package application | ||
|
|
||
| import ( | ||
| "os" | ||
| "path/filepath" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/mock" | ||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/elastic/elastic-agent/internal/pkg/agent/configuration" | ||
| "github.com/elastic/elastic-agent/internal/pkg/config" | ||
| "github.com/elastic/elastic-agent/pkg/core/logger/loggertest" | ||
| ) | ||
|
|
||
| func Test_FleetPatcher(t *testing.T) { | ||
| configFile := filepath.Join(".", "coordinator", "testdata", "overrides.yml") | ||
|
|
||
| testCases := []struct { | ||
| name string | ||
| isManaged bool | ||
| featureEnable bool | ||
| expectedLogs bool | ||
| }{ | ||
| {name: "managed - enabled", isManaged: true, featureEnable: true, expectedLogs: false}, | ||
| {name: "managed - disabled", isManaged: true, featureEnable: false, expectedLogs: true}, | ||
| {name: "not managed - enabled", isManaged: false, featureEnable: true, expectedLogs: true}, | ||
| {name: "not managed - disabled", isManaged: false, featureEnable: false, expectedLogs: true}, | ||
| } | ||
|
|
||
| overridesFile, err := os.OpenFile(configFile, os.O_RDONLY, 0) | ||
| require.NoError(t, err) | ||
| defer overridesFile.Close() | ||
|
|
||
| rawConfig, err := config.NewConfigFrom(overridesFile) | ||
| require.NoError(t, err) | ||
|
|
||
| for _, tc := range testCases { | ||
| t.Run(tc.name, func(t *testing.T) { | ||
| caps := &mockCapabilities{} | ||
| caps.On("AllowFleetOverride").Return(tc.featureEnable) | ||
|
|
||
| log, _ := loggertest.New(t.Name()) | ||
|
|
||
| cfg, err := config.LoadFile(filepath.Join(".", "coordinator", "testdata", "config.yaml")) | ||
| require.NoError(t, err) | ||
|
|
||
| configChange := &mockConfigChange{ | ||
| c: cfg, | ||
| } | ||
|
|
||
| patcher := PatchFleetConfig(log, rawConfig, caps, tc.isManaged) | ||
| patcher(configChange) | ||
|
|
||
| c := &configuration.Configuration{} | ||
| require.NoError(t, cfg.Agent.Unpack(&c)) | ||
| assert.Equal(t, tc.expectedLogs, c.Settings.MonitoringConfig.MonitorLogs) | ||
| require.True(t, c.Settings.MonitoringConfig.MonitorMetrics) | ||
| require.True(t, c.Settings.MonitoringConfig.Enabled) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| type mockCapabilities struct { | ||
| mock.Mock | ||
| } | ||
|
|
||
| func (m *mockCapabilities) AllowUpgrade(version string, sourceURI string) bool { | ||
| args := m.Called(version, sourceURI) | ||
| return args.Bool(0) | ||
| } | ||
|
|
||
| func (m *mockCapabilities) AllowInput(name string) bool { | ||
| args := m.Called() | ||
| return args.Bool(0) | ||
| } | ||
|
|
||
| func (m *mockCapabilities) AllowOutput(name string) bool { | ||
| args := m.Called() | ||
| return args.Bool(0) | ||
| } | ||
|
|
||
| func (m *mockCapabilities) AllowFleetOverride() bool { | ||
| args := m.Called() | ||
| return args.Bool(0) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| // Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| // or more contributor license agreements. Licensed under the Elastic License 2.0; | ||
| // you may not use this file except in compliance with the Elastic License 2.0. | ||
|
|
||
| package capabilities | ||
|
|
||
| import "github.com/elastic/elastic-agent/pkg/core/logger" | ||
|
|
||
| type fleetOverrideCapability struct { | ||
| // Whether a successful condition check lets an upgrade proceed or blocks it | ||
| rule allowOrDeny | ||
| } | ||
|
|
||
| func newFleetOverrideCapability(rule allowOrDeny) *fleetOverrideCapability { | ||
| return &fleetOverrideCapability{ | ||
| rule: rule, | ||
| } | ||
| } | ||
|
|
||
| func allowFleetOverride( | ||
| log *logger.Logger, | ||
| fleetOverrideCaps []*fleetOverrideCapability, | ||
| ) bool { | ||
| // first match wins | ||
| for _, cap := range fleetOverrideCaps { | ||
| if cap == nil { | ||
| // being defensive here, should not happen | ||
| continue | ||
| } | ||
|
|
||
| switch cap.rule { | ||
| case ruleTypeAllow: | ||
| log.Debugf("Fleet override allowed by capability") | ||
| return true | ||
| case ruleTypeDeny: | ||
| log.Debugf("Fleet override denied by capability") | ||
| return false | ||
| } | ||
| } | ||
| // No matching capability found, disable by default | ||
| return false | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.