Skip to content

Commit

Permalink
Add check version for agent image (#4628)
Browse files Browse the repository at this point in the history
  • Loading branch information
huguesBouvier authored Mar 19, 2021
1 parent e1d3e4f commit deb8a62
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 86 deletions.
2 changes: 1 addition & 1 deletion edgelet/contrib/config/linux/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ name = "edgeAgent"
type = "docker"

[agent.config]
image = "mcr.microsoft.com/azureiotedge-agent:1.0"
image = "mcr.microsoft.com/azureiotedge-agent:1.2"

[connect]
workload_uri = "@connect_workload_uri@"
Expand Down
2 changes: 1 addition & 1 deletion edgelet/contrib/config/linux/template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
# imagePullPolicy = "..." # "on-create" or "never". Defaults to "on-create"

# [agent.config]
# image = "mcr.microsoft.com/azureiotedge-agent:1.0"
# image = "mcr.microsoft.com/azureiotedge-agent:1.2"
# createOptions = { } # Docker container create options, in TOML format.

# [agent.config.auth]
Expand Down
231 changes: 231 additions & 0 deletions edgelet/iotedge/src/check/checks/check_agent_image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
use crate::check::{checker::Checker, Check, CheckResult};
use edgelet_core::RuntimeSettings;
use failure::{Context, ResultExt};
use regex::Regex;

#[derive(Default, serde_derive::Serialize)]
pub(crate) struct CheckAgentImage {}

impl Checker for CheckAgentImage {
fn id(&self) -> &'static str {
"Check-Agent-image"
}
fn description(&self) -> &'static str {
"Agent image is valid and can be pulled from upstream"
}
fn execute(&mut self, check: &mut Check, _: &mut tokio::runtime::Runtime) -> CheckResult {
self.inner_execute(check)
.unwrap_or_else(CheckResult::Failed)
}
fn get_json(&self) -> serde_json::Value {
serde_json::to_value(self).unwrap()
}
}

impl CheckAgentImage {
#[allow(clippy::unused_self)]
fn inner_execute(&mut self, check: &mut Check) -> Result<CheckResult, failure::Error> {
let settings = if let Some(settings) = &check.settings {
settings
} else {
return Ok(CheckResult::Skipped);
};

let docker_host_arg = if let Some(docker_host_arg) = &check.docker_host_arg {
docker_host_arg
} else {
return Ok(CheckResult::Skipped);
};

let agent_image = settings.agent().config().image();

if settings.parent_hostname().is_some() {
match check_agent_image_version(&agent_image) {
Ok(CheckResult::Ok) => (),
error => return error,
};
}

if let (Some(username), Some(password), Some(server_address)) = (
&settings
.agent()
.config()
.auth()
.and_then(docker::models::AuthConfig::username),
&settings
.agent()
.config()
.auth()
.and_then(docker::models::AuthConfig::password),
&settings
.agent()
.config()
.auth()
.and_then(docker::models::AuthConfig::serveraddress),
) {
super::docker(
docker_host_arg,
vec![
"login",
server_address,
"-p",
password,
"--username",
username,
],
)
.map_err(|(_, err)| err)
.context(format!("Failed to login to {}", server_address))?;
}

super::docker(docker_host_arg, vec!["pull", &agent_image])
.map_err(|(_, err)| err)
.context("Failed to get edge Agent image")?;

Ok(CheckResult::Ok)
}
}

fn check_agent_image_version(agent_image: &str) -> Result<CheckResult, failure::Error> {
// We don't match the repo mcr.microsoft.com because in nested edge we expect the repo to be parent_hostname:443
let re = Regex::new(r".*?/azureiotedge-agent:(?P<Major>\d+).(?P<Minor>\d+).*")
.context("Failed to create regex")?;

if let Some(caps) = re.captures(&agent_image) {
let minor_version: i32 = caps
.name("Minor")
.expect("output does not match expected format")
.as_str()
.parse()
.expect("output does not match expected format");
let major_version: i32 = caps
.name("Major")
.expect("output does not match expected format")
.as_str()
.parse()
.expect("output does not match expected format");

if major_version < 1 {
return Ok(CheckResult::Failed(
Context::new("In nested edge, edgeAgent version need to be 1.2 or above").into(),
));
}

if (major_version == 1) && (minor_version < 2) {
return Ok(CheckResult::Failed(
Context::new("In nested edge, edgeAgent version need to be 1.2 or above").into(),
));
}
}

Ok(CheckResult::Ok)
}

#[cfg(test)]
mod tests {
use super::check_agent_image_version;
use crate::check::CheckResult;

#[test]
fn test_check_agent_image_version() {
let test_cases = &[
(
"mcr.microsoft.com/azureiotedge-agent:1.0.9.5-linux-amd64",
false,
),
(
"$upstream:4443/azureiotedge-agent:1.0.9.5-linux-arm32v7",
false,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.0.9.5-linux-arm64v8",
false,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.0.9.5-windows-amd64",
false,
),
("mcr.microsoft.com/azureiotedge-agent:1.1", false),
("mcr.microsoft.com/azureiotedge-agent:1.1.0", false),
(
"mcr.microsoft.com/azureiotedge-agent:1.1.0-linux-amd64",
false,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.1.0-linux-arm32v7",
false,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.1.0-linux-arm64v8",
false,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.1.0-windows-amd64",
false,
),
("mcr.microsoft.com/azureiotedge-agent:1.2.0-rc1", true),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc1-linux-amd64",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc1-linux-arm32v7",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc1-linux-arm64v8",
true,
),
("mcr.microsoft.com/azureiotedge-agent:1.2.0-rc2", true),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc2-linux-amd64",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc2-linux-arm32v7",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc2-linux-arm64v8",
true,
),
("mcr.microsoft.com/azureiotedge-agent:1.2.0-rc3", true),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc3-linux-amd64",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc3-linux-arm32v7",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc3-linux-arm64v8",
true,
),
("mcr.microsoft.com/azureiotedge-agent:1.2.0-rc4", true),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc4-linux-amd64",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc4-linux-arm32v7",
true,
),
(
"mcr.microsoft.com/azureiotedge-agent:1.2.0-rc4-linux-arm64v8",
true,
),
(
"$upstream:4443/azureiotedge-agent:3.0.9.5-linux-arm32v7",
true,
),
("randomImage/randomImage:1.0", true),
];

for (agent_image, expected_is_valid) in test_cases {
let actual_is_valid =
matches!(check_agent_image_version(agent_image), Ok(CheckResult::Ok));
assert_eq!(*expected_is_valid, actual_is_valid);
}
}
}
6 changes: 3 additions & 3 deletions edgelet/iotedge/src/check/checks/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod aziot_edged_version;
mod check_agent_image;
mod connect_management_uri;
mod container_connect_upstream;
mod container_engine_dns;
Expand All @@ -10,12 +11,12 @@ mod container_local_time;
mod container_resolve_parent_hostname;
mod hostname;
mod parent_hostname;
mod pull_agent_from_upstream;
mod storage_mounted_from_host;
mod up_to_date_config;
mod well_formed_config;

pub(crate) use self::aziot_edged_version::AziotEdgedVersion;
pub(crate) use self::check_agent_image::CheckAgentImage;
pub(crate) use self::connect_management_uri::ConnectManagementUri;
pub(crate) use self::container_connect_upstream::get_host_container_upstream_tests;
pub(crate) use self::container_engine_dns::ContainerEngineDns;
Expand All @@ -27,7 +28,6 @@ pub(crate) use self::container_local_time::ContainerLocalTime;
pub(crate) use self::container_resolve_parent_hostname::ContainerResolveParentHostname;
pub(crate) use self::hostname::Hostname;
pub(crate) use self::parent_hostname::ParentHostname;
pub(crate) use self::pull_agent_from_upstream::PullAgentFromUpstream;
pub(crate) use self::storage_mounted_from_host::{EdgeAgentStorageMounted, EdgeHubStorageMounted};
pub(crate) use self::up_to_date_config::UpToDateConfig;
pub(crate) use self::well_formed_config::WellFormedConfig;
Expand Down Expand Up @@ -95,7 +95,7 @@ pub(crate) fn built_in_checks() -> [(&'static str, Vec<Box<dyn Checker>>); 2] {
Box::new(ContainerEngineLogrotate::default()),
Box::new(EdgeAgentStorageMounted::default()),
Box::new(EdgeHubStorageMounted::default()),
Box::new(PullAgentFromUpstream::default()),
Box::new(CheckAgentImage::default()),
],
),
("Connectivity checks", {
Expand Down
80 changes: 0 additions & 80 deletions edgelet/iotedge/src/check/checks/pull_agent_from_upstream.rs

This file was deleted.

2 changes: 1 addition & 1 deletion edgelet/iotedge/src/config/super_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(super) fn default_agent() -> edgelet_core::ModuleSpec<edgelet_docker::Docker
type_: "docker".to_owned(),
image_pull_policy: Default::default(),
config: edgelet_docker::DockerConfig {
image: "mcr.microsoft.com/azureiotedge-agent:1.0".to_owned(),
image: "mcr.microsoft.com/azureiotedge-agent:1.2".to_owned(),
image_id: None,
create_options: docker::models::ContainerCreateBody::new(),
digest: None,
Expand Down

0 comments on commit deb8a62

Please sign in to comment.