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

systemd: add AtLeast() method, add mocking in systemdtest #10748

Merged
merged 6 commits into from Sep 13, 2021

Conversation

mardy
Copy link
Contributor

@mardy mardy commented Sep 7, 2021

Allow the systemd.Version() method to be mocked, and add a new AtLeast() method, as per the TODO.

@codecov-commenter
Copy link

codecov-commenter commented Sep 7, 2021

Codecov Report

Merging #10748 (973ab87) into master (10588fd) will decrease coverage by 0.01%.
The diff coverage is 77.27%.

❗ Current head 973ab87 differs from pull request most recent head 2a1c3c1. Consider uploading reports for the commit 2a1c3c1 to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master   #10748      +/-   ##
==========================================
- Coverage   78.36%   78.34%   -0.02%     
==========================================
  Files         888      888              
  Lines      100091   100109      +18     
==========================================
- Hits        78433    78432       -1     
- Misses      16743    16762      +19     
  Partials     4915     4915              
Flag Coverage Δ
unittests 78.34% <77.27%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
overlord/configstate/configcore/journal.go 60.29% <40.00%> (+1.56%) ⬆️
usersession/userd/privileged_desktop_launcher.go 85.44% <60.00%> (+0.37%) ⬆️
systemd/systemd.go 85.97% <87.50%> (+0.02%) ⬆️
overlord/servicestate/quota_control.go 86.47% <100.00%> (+1.85%) ⬆️
osutil/synctree.go 76.41% <0.00%> (-2.84%) ⬇️
store/cache.go 69.23% <0.00%> (-1.93%) ⬇️
daemon/api_connections.go 91.97% <0.00%> (-1.61%) ⬇️
daemon/daemon.go 76.40% <0.00%> (-1.52%) ⬇️
overlord/hookstate/hookmgr.go 74.17% <0.00%> (-0.67%) ⬇️
overlord/ifacestate/helpers.go 77.02% <0.00%> (-0.50%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 10588fd...2a1c3c1. Read the comment docs.

Copy link
Contributor

@stolowski stolowski left a comment

Choose a reason for hiding this comment

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

Looks nice, thank you! A few remarks/suggestions to consider

}

func quotaGroupsAvailable(st *state.State) error {
// check if the systemd version is too old
if systemdVersion < 230 {
return fmt.Errorf("systemd version too old: snap quotas requires systemd 230 and newer (currently have %d)", systemdVersion)
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if not showing the detected version could bite us (e.g. if we suddenly encounter a version string we don't parse properly).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I restored it, though I had to refactor things a bit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the changes, I think they look good. Still a bit unsure about the placement of mocking per my other comment (but feel free to object ;)).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, I simply didn't get to it yet :-)

@@ -59,3 +60,14 @@ Type=simple
}
return output
}

func MockSystemdVersion(version int) (restore func()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we typically put such functions in the respective package (systemd in this case), and then systemd.Version doesn't have to be exported?

Also, I would make it possible to mock the function with complete return value (int, error), not just hardcode one that returns (version, nil).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! :-)

// false.
func AtLeast(requiredVersion int) bool {
version, err := Version()
return err == nil && version >= requiredVersion
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should log the error somewhere like we did before this change, otherwise we won't know if something went wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I reowrked this a little, please have another look.

return err
}
if version < requiredVersion {
return fmt.Errorf(`installed version %d is too old`, version)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be a separate error type? eg.

type systemdTooOldError struct {
    expected int
    got int
}

func (e *systemdTooOldError) Error() string {
    return fmt.Sprintf("systemd version %d is too old (expected at least %d)", e.got, e.expected)
}

Then here:

return &systemdTooOld{got: version, expected: requiredVersion}

then in quotas code you can just return:

return fmt.Errorf("cannot use quotas with incompatible systemd: %v", err)

which would produce eg. cannot use quotas with incompatible systemd: systemd version 123 is too old (expected 345)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice suggestion, done!

@mardy mardy added the Squash-merge Please squash this PR when merging. label Sep 9, 2021
Copy link
Contributor

@mvo5 mvo5 left a comment

Choose a reason for hiding this comment

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

Looks fine, a suggestion about a test inline but with that I think this is a 👍

@@ -118,6 +121,17 @@ var systemctlCmd = func(args ...string) ([]byte, error) {
return bs, nil
}

func MockSystemdVersion(version int, injectedError error) (restore func()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The injectedError is not used yet AFAICT but AIUI this will be used in a followup PR(?). Maybe a trivial test that ithe mocking works as expected? in systemd_test.go or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, I don't have a plan to use it, but I might :-) It was actually Pavel who suggested to add the error, and I think it can help to test some corner cases.

I've now added a unit test for it, so it won't appear to be unused anymore :-)

Copy link
Collaborator

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

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

LGTM

systemd/systemd.go Show resolved Hide resolved
Comment on lines +124 to +132
func MockSystemdVersion(version int, injectedError error) (restore func()) {
osutil.MustBeTestBinary("cannot mock systemd version outside of tests")
old := Version
Version = func() (int, error) {
return version, injectedError
}
return func() {
Version = old
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I had the usual MockSystemdVersion(f func() (int, err)) (restore .... in mind, but that's fine too and maybe even more handy.

Comment on lines +217 to +228
func EnsureAtLeast(requiredVersion int) error {
version, err := Version()
if err != nil {
return err
}
if version < requiredVersion {
return &systemdTooOldError{got: version, expected: requiredVersion}
}
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This should probably have a simple test now in systemd_test.go.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added!

Copy link
Contributor

@stolowski stolowski left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

@mardy mardy removed the Squash-merge Please squash this PR when merging. label Sep 13, 2021
@mvo5 mvo5 merged commit 6151af3 into snapcore:master Sep 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants