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

ntp: Add setting to configure options #3852

Merged
merged 1 commit into from
Apr 5, 2024

Conversation

domgoodwin
Copy link
Contributor

@domgoodwin domgoodwin commented Mar 25, 2024

Description of changes:

Adds the ability to configure further options for the NTP servers. We would like to set maxpoll to a lower value so I've added the ability to specify options which get added to the servers too. I've removed the default option iburst and added it to this setting default instead.

Testing done:

  • Ran unit tests locally

Edit: Sam did the testing with Bottlerocket including migration testing, see comment below.

Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

Copy link
Contributor

@sam-berning sam-berning left a comment

Choose a reason for hiding this comment

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

Thank you for the contribution! Overall this approach makes sense, left a few comments on implementation details.

Probably the toughest bit will be the migration, but you can just adapt the commit I shared to work for this case, keeping in mind that the migration will be for version 1.20.0 instead of 1.19.2. Feel free to reach out if you run into any problems with this, I'm happy to help!

@@ -2,7 +2,7 @@
ntp = "v1"
+++
{{#each settings.ntp.time-servers}}
pool {{this}} iburst
pool {{this}} {{#each settings.ntp.options}}{{this}} {{/each}}
Copy link
Contributor

Choose a reason for hiding this comment

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

minor, but this will avoid any additional whitespace:

Suggested change
pool {{this}} {{#each settings.ntp.options}}{{this}} {{/each}}
pool {{this}}{{#each settings.ntp.options}} {{this}}{{/each}}

@@ -119,6 +119,7 @@ template-path = "/usr/share/templates/hosts"

[settings.ntp]
time-servers = ["169.254.169.123", "2.amazon.pool.ntp.org"]
options = ["iburst"]
Copy link
Contributor

Choose a reason for hiding this comment

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

this will require a migration so that on downgrade to an older version of bottlerocket this setting will be removed. here's an example commit that should be very similar to the migration needed here: 83b3e6a

Copy link
Contributor

Choose a reason for hiding this comment

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

You will also need to add the migration to Release.toml, reference the above commit for an example.

@@ -8,6 +8,7 @@ use std::convert::Infallible;
#[model(impl_default = true)]
pub struct NtpSettingsV1 {
time_servers: Vec<Url>,
options: Vec<str>,
Copy link
Contributor

Choose a reason for hiding this comment

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

You'll need to use an owned string here:

Suggested change
options: Vec<str>,
options: Vec<String>,

Comment on lines 98 to 100
Url::try_from("minpool").unwrap(),
Url::try_from("1").unwrap(),
Url::try_from("maxpool").unwrap(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Url::try_from("minpool").unwrap(),
Url::try_from("1").unwrap(),
Url::try_from("maxpool").unwrap(),
Url::try_from("minpoll").unwrap(),
Url::try_from("1").unwrap(),
Url::try_from("maxpoll").unwrap(),

@domgoodwin
Copy link
Contributor Author

domgoodwin commented Apr 1, 2024

@sam-berning Thanks for the review, I've address them and added the migration - I think how I've done it is right

Copy link
Contributor

@sam-berning sam-berning left a comment

Choose a reason for hiding this comment

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

Hey @domgoodwin, thanks for following up! The migration looks good for the most part. Just have a couple more comments, noticed a few things I missed in my first review.

@@ -2,7 +2,7 @@
ntp = "v1"
+++
{{#each settings.ntp.time-servers}}
pool {{this}} iburst
pool {{this}} {{#each settings.ntp.options}}{{this}}{{/each}}
Copy link
Contributor

Choose a reason for hiding this comment

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

we still need a space within the {{#each}} so that each option is separated by a space, it should look like this:

Suggested change
pool {{this}} {{#each settings.ntp.options}}{{this}}{{/each}}
pool {{this}}{{#each settings.ntp.options}} {{this}}{{/each}}

@@ -119,6 +119,7 @@ template-path = "/usr/share/templates/hosts"

[settings.ntp]
time-servers = ["169.254.169.123", "2.amazon.pool.ntp.org"]
options = ["iburst"]
Copy link
Contributor

Choose a reason for hiding this comment

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

You will also need to add the migration to Release.toml, reference the above commit for an example.

Comment on lines 68 to 69
time_servers: None
options: None
Copy link
Contributor

Choose a reason for hiding this comment

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

need commas after each of these items:

Suggested change
time_servers: None
options: None
time_servers: None,
options: None,

@@ -85,4 +87,22 @@ mod test {
let results = serde_json::to_string(&ntp).unwrap();
assert_eq!(results, test_json);
}

fn test_options_ntp() {
let test_json = r#"{"time-servers":["https://example.net","http://www.example.com"],"options": ["minpoll", "1", "maxpoll", "2"]}"#;
Copy link
Contributor

Choose a reason for hiding this comment

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

For testing serde_json::to_string() at the end of this test, you'll need to remove all of the extra whitespace from this string:

Suggested change
let test_json = r#"{"time-servers":["https://example.net","http://www.example.com"],"options": ["minpoll", "1", "maxpoll", "2"]}"#;
let test_json = r#"{"time-servers":["https://example.net","http://www.example.com"],"options":["minpoll","1","maxpoll","2"]}"#;

@@ -85,4 +87,22 @@ mod test {
let results = serde_json::to_string(&ntp).unwrap();
assert_eq!(results, test_json);
}

fn test_options_ntp() {
Copy link
Contributor

Choose a reason for hiding this comment

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

In order for Rust to recognize this as a unit test, you need to provide the #[test] macro here:

Suggested change
fn test_options_ntp() {
#[test]
fn test_options_ntp() {

Comment on lines 98 to 101
Url::try_from("minpoll").unwrap(),
Url::try_from("1").unwrap(),
Url::try_from("maxpoll").unwrap(),
Url::try_from("2").unwrap(),
Copy link
Contributor

Choose a reason for hiding this comment

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

These should be Strings, not Urls:

Suggested change
Url::try_from("minpoll").unwrap(),
Url::try_from("1").unwrap(),
Url::try_from("maxpoll").unwrap(),
Url::try_from("2").unwrap(),
String::from("minpoll"),
String::from("1"),
String::from("maxpoll"),
String::from("2"),

@@ -0,0 +1,10 @@
[package]
name = "add-ntp-default-options"
Copy link
Contributor

Choose a reason for hiding this comment

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

the package name in Cargo.toml needs to be the same as the directory name or the build won't be able to find the package:

Suggested change
name = "add-ntp-default-options"
name = "add-ntp-default-options-v0-1-0"

@domgoodwin
Copy link
Contributor Author

Comments addressed @sam-berning 🙏 , looks like the test is actually running now and passing - I had to remove the try_from stuff but I think that's fine as it's not a URL 🤦

running 3 tests
test test::test_generate_ntp_settings ... ok
test test::test_options_ntp ... ok
test test::test_serde_ntp ... ok

Makefile.toml Outdated
@@ -24,7 +24,7 @@ TWOLITER_ALLOW_BINARY_INSTALL="true"

# Allow Twoliter to be installed by building from sourcecode.
TWOLITER_ALLOW_SOURCE_INSTALL="true"

TARGET_CC="x86_64-unknown-linux-gnu"
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this doing?

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 didn't mean to add this, should be removed with the latest commit

@sam-berning
Copy link
Contributor

CI is failing on check-fmt, can you reformat sources/api/migration/migrations/v1.20.0/add-ntp-default-options-v0-1-0/src/main.rs and sources/settings-extensions/ntp/src/lib.rs with rustfmt?

Copy link
Contributor

@sam-berning sam-berning left a comment

Choose a reason for hiding this comment

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

nice, thanks for updating it @domgoodwin. CI is now passing! I built this locally and tested on an EC2 instance and /etc/chrony.conf is not getting generated correctly:

Apr 02 23:14:28 ip-172-31-23-40.us-west-2.compute.internal apiserver[1791]: Configuration file 'chrony-conf' failed to render: Failed to render template file ('/usr/share/templates/chrony-conf'): Failed to render template 'Template { frontmatter: TemplateFrontmatter { required_extensions: {"ntp": Version("v1")} }, body: "{{#each settings.ntp.time-servers}}\npool {{this}}{{#each settings.ntp.options}} {{this}}{{/each}}\n{{/each}}\ndriftfile /var/lib/chrony/drift\nmakestep 1.0 3\ndumponexit\ndumpdir /var/lib/chrony\nuser chrony\nrtcsync\n" }': Error rendering "Unnamed template" line 2, col 14: Variable "settings.ntp.options" not found in strict mode.

Turns out within the each loop, you need to use ../ to access a variable outside of the scope of the loop. I've left a comment with the suggested change, but after that this should work as expected.

packages/chrony/chrony-conf Outdated Show resolved Hide resolved
@sam-berning
Copy link
Contributor

Thanks @domgoodwin, this is looking really good. Now I'll just need to test that the migrations are working as expected, I'll update you when I finish with that.

In the meantime, can you squash your commits into one?

@domgoodwin
Copy link
Contributor Author

Thanks @sam-berning, commits squashed into 1 🙇

@sam-berning
Copy link
Contributor

Tested the migration, it works as expected:

Started an instance:

bash-5.1# cat /etc/os-release                                                                                      
...                                                                                            
VERSION="1.20.0 (aws-dev)"                                                                                         
...                                                                                               
BUILD_ID=cfcc095e
...
bash-5.1# apiclient get settings.ntp
{
  "settings": {
    "ntp": {
      "options": [
        "iburst"
      ],
      "time-servers": [
        "169.254.169.123",
        "2.amazon.pool.ntp.org"
      ]
    }
  }
}
bash-5.1# cat /etc/chrony.conf 
pool 169.254.169.123 iburst
pool 2.amazon.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
dumponexit
dumpdir /var/lib/chrony
user chrony
rtcsync
bash-5.1# updog update -i 1.19.3 -r -n                                                                             
Starting update to 1.19.3                                                                                          
Reboot scheduled for Thu 2024-04-04 23:07:29 UTC, use 'shutdown -c' to cancel.                                     
Update applied: aws-dev 1.19.3

after downgrade:

bash-5.1# cat /etc/os-release                                                                                      
...                                                                                                  
VERSION="1.19.3 (aws-dev)"                                                                                         
...
bash-5.1# apiclient get settings.ntp                                                                               
{                                                                                                                  
  "settings": {                                                                                                    
    "ntp": {
      "time-servers": [
        "169.254.169.123",
        "2.amazon.pool.ntp.org"
      ]
    }
  }
}
bash-5.1# ls /etc/chrony.conf                                                                                      
/etc/chrony.conf                                                                                                   
bash-5.1# cat /etc/chrony.conf                                                                                     
pool 169.254.169.123 iburst                                                                                        
pool 2.amazon.pool.ntp.org iburst                                                                                  
driftfile /var/lib/chrony/drift                                                                                    
makestep 1.0 3                                                                                                     
dumponexit                                                                                                         
dumpdir /var/lib/chrony                                                                                            
user chrony                                                                                                        
rtcsync
bash-5.1# updog update -i 1.20.0 -r -n
Starting update to 1.20.0
Reboot scheduled for Thu 2024-04-04 23:10:56 UTC, use 'shutdown -c' to cancel.
Update applied: aws-dev 1.20.0

after upgrade:

bash-5.1# cat /etc/os-release 
...
VERSION="1.20.0 (aws-dev)"
...
bash-5.1# apiclient get settings.ntp
{
  "settings": {
    "ntp": {
      "options": [
        "iburst"
      ],
      "time-servers": [
        "169.254.169.123",
        "2.amazon.pool.ntp.org"
      ]
    }
  }
}
bash-5.1# cat /etc/chrony.conf      
pool 169.254.169.123 iburst
pool 2.amazon.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
dumponexit
dumpdir /var/lib/chrony
user chrony
rtcsync

Copy link
Contributor

@webern webern left a comment

Choose a reason for hiding this comment

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

This looks correct to me. @yeazelm can you take a look to confirm? Thanks.

@@ -119,6 +119,7 @@ template-path = "/usr/share/templates/hosts"

[settings.ntp]
time-servers = ["169.254.169.123", "2.amazon.pool.ntp.org"]
options = ["iburst"]
Copy link
Contributor

Choose a reason for hiding this comment

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

@yeazelm, this looks correct to me. The options setting is added by the migration and the defaults file will now include "iburst" such that behavior does not change on upgrade.

Copy link
Contributor

Choose a reason for hiding this comment

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

This looks right to me!

@sam-berning
Copy link
Contributor

@domgoodwin this needs a rebase

@domgoodwin
Copy link
Contributor Author

@sam-berning done ✅

@sam-berning sam-berning merged commit 91b3b2d into bottlerocket-os:develop Apr 5, 2024
35 checks passed
@ginglis13 ginglis13 mentioned this pull request May 7, 2024
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants