Skip to content

Support Entrypoint command for Host and Bootstrap containers#4636

Merged
KCSesh merged 2 commits intobottlerocket-os:developfrom
ytsssun:host-bootstrap-container-entry-command
Sep 10, 2025
Merged

Support Entrypoint command for Host and Bootstrap containers#4636
KCSesh merged 2 commits intobottlerocket-os:developfrom
ytsssun:host-bootstrap-container-entry-command

Conversation

@ytsssun
Copy link
Contributor

@ytsssun ytsssun commented Sep 9, 2025

Issue number:

Closes bottlerocket-os/bottlerocket-core-kit#593

Description of changes:
This PR adds migration support for the new command setting in

  • settings.host-containers.<name>.command
  • settings.bootstrap-containers.<name>.command

Key changes:

  • Added AddPrefixSuffixMigration helper for migrations that needs both prefix and suffix matches.
  • Added the actual migration for the settings.{host,bootstrap}-containers.<name>.command settings.

The migration helper uses prefix/suffix patterns to identify and remove settings during downgrades:

AddPrefixSuffixMigration(vec![
   PrefixSuffix {
       prefix: "settings.host-containers.",
       suffix: ".command",
   },
   PrefixSuffix {
       prefix: "settings.bootstrap-containers.",
       suffix: ".command",
   },
])

Testing done:

Click to expand testing details

Initial Setup and Upgrade Testing

1. Pre-upgrade validation (expected failure)

apiclient set -j '{
 "settings": {
   "bootstrap-containers": {
     "test-bootstrap": {
       "source": "328549459982.dkr.ecr.us-west-2.amazonaws.com/bottlerocket-bootstrap:v0.2.5",
       "mode": "once",
       "command": ["echo", "Message from bootstrap container command"],
       "user-data": "ZWNobyAnTWVzc2FnZSBmcm9tIGJvb3RzdHJhcCBjb250YWluZXIgdXNlci1kYXRhJwo="
     }
   },
   "host-containers": {
     "test-host": {
       "enabled": true,
       "source": "public.ecr.aws/amazonlinux/amazonlinux:2023",
       "command": ["sleep", "infinity"],
       "user-data": "ZWNobyAnTWVzc2FnZSBmcm9tIGhvc3QgY29udGFpbmVyIHVzZXItZGF0YScK"
     }
   }
 }
}'

Result: Failed as expected with error: unknown field 'command', expected one of 'source', 'mode', 'user-data', 'essential'

2. Post-upgrade to v1.47.0
Applied the same configuration successfully. Verified settings were properly stored:

# Host container verification
apiclient get settings.host-containers.test-host
{
 "settings": {
   "host-containers": {
     "test-host": {
       "command": ["sleep", "infinity"],
       "enabled": true,
       "source": "public.ecr.aws/amazonlinux/amazonlinux:2023",
       "user-data": "ZWNobyAnTWVzc2FnZSBmcm9tIGhvc3QgY29udGFpbmVyIHVzZXItZGF0YScK"
     }
   }
 }
}

# Bootstrap container verification
apiclient get settings.bootstrap-containers.test-bootstrap
{
 "settings": {
   "bootstrap-containers": {
     "test-bootstrap": {
       "command": ["echo", "Message from bootstrap container command"],
       "mode": "once",
       "source": "328549459982.dkr.ecr.us-west-2.amazonaws.com/bottlerocket-bootstrap:v0.2.5",
       "user-data": "ZWNobyAnTWVzc2FnZSBmcm9tIGJvb3RzdHJhcCBjb250YWluZXIgdXNlci1kYXRhJwo="
     }
   }
 }
}

Downgrade Migration Testing

3. Downgrade migration validation
After downgrading from v1.47.0, verified that the command field was properly removed:

# Host container - command field removed
apiclient get settings.host-containers.test-host
{
 "settings": {
   "host-containers": {
     "test-host": {
       "enabled": true,
       "source": "public.ecr.aws/amazonlinux/amazonlinux:2023",
       "user-data": "ZWNobyAnTWVzc2FnZSBmcm9tIGhvc3QgY29udGFpbmVyIHVzZXItZGF0YScK"
     }
   }
 }
}

# Bootstrap container - command field removed
apiclient get settings.bootstrap-containers.test-bootstrap
{
 "settings": {
   "bootstrap-containers": {
     "test-bootstrap": {
       "mode": "off",
       "source": "328549459982.dkr.ecr.us-west-2.amazonaws.com/bottlerocket-bootstrap:v0.2.5",
       "user-data": "ZWNobyAnTWVzc2FnZSBmcm9tIGJvb3RzdHJhcCBjb250YWluZXIgdXNlci1kYXRhJwo="
     }
   }
 }
}

Runtime Verification

After applying the new settings in step 2, reboot the node to verify both bootstrap and host containers pick up the settings.
4. Container runtime validation

# Verified custom host container is running
ctr -a /run/host-containerd/containerd.sock c ls
CONTAINER    IMAGE                                                                                RUNTIME
admin        ecr.aws/arn:aws:ecr:us-west-2:328549459982:repository/bottlerocket-admin:v0.12.2
io.containerd.runc.v2
...
test-host    public.ecr.aws/amazonlinux/amazonlinux:2023
io.containerd.runc.v2

5. Container execution validation
The custom host-container has entry point ["sleep", "infinity"], so we can exec into it for some extra testing.

# Verified apiclient exec works
apiclient exec test-host sh
sh-5.2# cat /etc/os-release
NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
# ... (output truncated)

6. Host container logs

journalctl -u host-containers@test-host
Sep 08 22:29:13 ip-10-0-9-132.us-west-2.compute.internal host-containers@test-host[2583]: time="2025-09-08T22:29:
13Z" level=info msg="Image does not exist, proceeding to pull image from source."
Sep 08 22:29:16 ip-10-0-9-132.us-west-2.compute.internal host-containers@test-host[2583]: time="2025-09-08T22:29:
16Z" level=info msg="successfully started container task"

7. Bootstrap container logs and command execution

journalctl -b -u bootstrap-containers@test-bootstrap
Sep 08 22:39:21 ip-10-0-9-132.us-west-2.compute.internal bootstrap-containers@test-bootstrap[1674]: Message from
bootstrap container command
Sep 08 22:39:21 ip-10-0-9-132.us-west-2.compute.internal bootstrap-containers@test-bootstrap[1674]: time="2025-09-
08T22:39:21Z" level=info msg="container task exited" code=0
Sep 08 22:39:21 ip-10-0-9-132.us-west-2.compute.internal bootstrap-containers@test-bootstrap[1762]: 22:39:21 [INFO]
Mode for 'test-bootstrap' is 'once'

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.

@ytsssun ytsssun force-pushed the host-bootstrap-container-entry-command branch from 786f6f4 to d1fb200 Compare September 9, 2025 21:13
@ytsssun
Copy link
Contributor Author

ytsssun commented Sep 9, 2025

Add unit test case for compound suffix per @KCSesh

@ytsssun ytsssun force-pushed the host-bootstrap-container-entry-command branch 3 times, most recently from 5b0b0e7 to 7e0c99f Compare September 9, 2025 22:18
@ytsssun
Copy link
Contributor Author

ytsssun commented Sep 9, 2025

Tighten the matching implementation so that it uses regex pattern to match the settings.

The regex pattern would be "^<prefix>\.(.+)\.<suffix>$". Per @bcressey

Comment on lines +180 to +193
let mut compiled_patterns = Vec::new();
for pattern in &self.0 {
let regex_pattern = format!(
r"^{}\.(.+)\.{}$",
regex::escape(pattern.prefix),
regex::escape(pattern.suffix)
);
let regex =
Regex::new(&regex_pattern).context(error::InvalidPrefixSuffixPatternSnafu {
prefix: pattern.prefix,
suffix: pattern.suffix,
})?;
compiled_patterns.push(regex);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have to compile the regex patterns at runtime because it depends on the prefix and suffix. But this way we only still compile it once for the backward() call.

Copy link
Contributor

@koooosh koooosh left a comment

Choose a reason for hiding this comment

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

LGTM, assuming new migration tests pass

Signed-off-by: Yutong Sun <yutongsu@amazon.com>
Signed-off-by: Yutong Sun <yutongsu@amazon.com>
@ytsssun ytsssun force-pushed the host-bootstrap-container-entry-command branch from 7e0c99f to 23a27fb Compare September 9, 2025 22:50
@ytsssun
Copy link
Contributor Author

ytsssun commented Sep 9, 2025

Force push to rebase changes from develop

}

#[test]
fn tight_matching() {
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 more test cases here with real settings - for the more strict regex matching.

let mut compiled_patterns = Vec::new();
for pattern in &self.0 {
let regex_pattern = format!(
r"^{}\.(.+)\.{}$",
Copy link
Contributor

Choose a reason for hiding this comment

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

The migration's regex (.+) captures any characters, which is more than we allow in host/bootstrap containers today.

But this makes sense to make it more extensible for future situations, since this is in common

@ytsssun
Copy link
Contributor Author

ytsssun commented Sep 9, 2025

I reran the migration tests to just confirm the behavior. And it passed!

@ytsssun ytsssun requested a review from bcressey September 9, 2025 23:26
@KCSesh KCSesh merged commit e6e30ba into bottlerocket-os:develop Sep 10, 2025
2 checks passed
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.

allow overriding {host,bootstrap}-containers entrypoint command

6 participants