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
client,daemon,features: expose feature flags supported/enabled info #13681
client,daemon,features: expose feature flags supported/enabled info #13681
Conversation
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #13681 +/- ##
=======================================
Coverage 78.88% 78.89%
=======================================
Files 1040 1040
Lines 134088 134126 +38
=======================================
+ Hits 105782 105816 +34
- Misses 21698 21701 +3
- Partials 6608 6609 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
0eb480f
to
daed63b
Compare
Force-pushed to fix conflict with NEWS.md |
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, some comments about possibly extending the feature info we return
const featuresKey = "features" | ||
resultFeatures := rsp.Result.(map[string]interface{})[featuresKey] | ||
c.Check(resultFeatures, check.Not(check.Equals), "") | ||
delete(rsp.Result.(map[string]interface{}), featuresKey) |
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 add those to the expected
value above?
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 could, but it should include an entry for every experimental feature, and I don't want adjusting features to require tweaking this test all the time. I'd rather check a few values from this manually (as is done later in the test).
type FeatureInfo struct { | ||
Supported bool `json:"supported"` | ||
Enabled bool `json:"enabled"` | ||
} |
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 a string field eg. UnsupportedReason
which would carry information why a given feature is not supported?
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 like this idea a lot, thanks!
features/features.go
Outdated
// Features implicitly supported if no callback exists | ||
supported := true | ||
if callback, exists := featuresSupportedCallbacks[feature]; exists { | ||
supported = callback() |
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.
in which case the callback would need to return more than a bool
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.
It could either return (bool, error)
where a false
value must always be accompanied by a non-nil
error. Or we could simply return error
where nil
means supported and non-nil
means supported. The former is redundant but clearer, while the latter is not redundant (and matches usage of GetMaybe()
in Flag()
), but is slightly less clear on its own. Any preference between these two approaches?
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 implemented (bool, error)
for now. Feel free to suggest otherwise if you'd prefer.
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.
Actually, (bool, string)
, since it's really a description rather than an error.
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.
overall lgtm
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.
LGTM
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, comments about the feature unsupported reasons
features/features.go
Outdated
UserDaemons: release.SystemctlSupportsUserUnits, | ||
UserDaemons: func() (bool, string) { | ||
if !release.SystemctlSupportsUserUnits() { | ||
return false, "user session daemons are not supported on this release" |
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/release/system/ or s /release/distribution version/
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 like that "system" suggests host system, rather than version of snapd, so I think I'll go with "this system's distribution version". Thank you!
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.
lgtm, with a suggestion for a test change (maybe for a follow-up?)
@@ -216,3 +217,66 @@ func (s *featureSuite) TestFlag(c *C) { | |||
_, err = features.Flag(tr, features.Layouts) | |||
c.Assert(err, ErrorMatches, `layouts can only be set to 'true' or 'false', got "banana"`) | |||
} | |||
|
|||
func (s *featureSuite) TestAll(c *C) { |
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 won't block the PR for it as it is tested but it would be better if this test didn't depend on the inner workings of specific flags like QuotaGroups since it might be broken by changing/adding callbacks. We could export featuresSupportedCallbacks
through export_test.go
and then set custom callbacks to test whatever we want (enabled but unsupported, support but disabled, etc) and check All
's output
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, and good idea, I'll add a task for myself to improve these tests in the future.
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.
thank you
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.
LGTM, Thank you!
Now that #13693 is merged, I can add a callback to this PR for the "apparmor-prompting" feature, then this can be merged. |
2d9777b
to
1c85159
Compare
Force pushed after rebasing on master to get As part of rebase, also added a feature supported callback for |
Add `All()` function, which returns a map of feature names to `FeatureInfo` structs. `FeatureInfo` contains boolean values for whether the feature is supported and whether it is enabled. A new map is defined from feature flags to callback functions which return true if the feature is supported and false if it is unsupported. Any feature for which no callback function is defined is assumed to be supported. Currently, callback functions are defined for `QuotaGroups` (check that systemd version >= 230), `UserDaemons` (check that user units are supported), and `AppArmorPrompting` (always return false, for now). Since some components of prompting are not yet merged into snapd master, the experimental "apparmor-prompting" feature is not yet supported. This commit adds a callback for "apparmor-prompting" which returns false and states that it requires a newer version of snapd. Once the rest of the prompting system is ready, the callback for AppArmorPrompting should be modified to instead check that the installed AppArmor has kernel and parser support for prompting, and that the notify socket for communicating with the kernel exists. Any features which are set to values other than true or false are omitted from the map returned by `All()`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> features: add unsupported reason when feature not supported Signed-off-by: Oliver Calder <oliver.calder@canonical.com> features: improved docstrings for `All()` and `FeatureInfo` Signed-off-by: Oliver Calder <oliver.calder@canonical.com> features: adjusted callback feature unsupported reasons Signed-off-by: Oliver Calder <oliver.calder@canonical.com> features: add supported callback for apparmor prompting Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Add a "features" field containing a map of feature flag names to boolean subfields for whether the feature is "supported" and/or "enabled", along with an "unsupported-reason" if the feature is not supported. Feature flags which are not set to true or false are omitted from this map. Feature flags may be unsupported but nonetheless enabled. This indicates that the feature flag has been set to true, but the backing feature itself is not currently supported. Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
1c85159
to
370eec0
Compare
And force-pushed again to rebase on master with test fixes from #13685 |
Adds
features.All()
to return a map from feature flag names to a struct indicating whether that feature is supported and/or enabled. A callback functions may be defined for a feature flag which returnstrue
if that feature flag is supported by the system, otherwisefalse
.Features which are set to a value other than
true
orfalse
are not included in the map, as these are not feature flags.If no callback function is defined for a given feature flag, it is assumed that that feature flag is supported. Currently, callbacks are defined for
QuotaGroups
(check that systemd version >= 230) andUserDaemons
(check that user units are supported).Features may be enabled but not supported. In this case, the feature flag has been set to true, but the underlying feature is not supported by the system.
This information is now included in the response to the
/v2/system-info
endpoint under a new"features"
field. This lets clients get information about which features are supported and/or enabled without querying/v2/snaps/system/conf
, which requires authentication.