Skip to content

Commit

Permalink
Sort settings env variables serialization (#689)
Browse files Browse the repository at this point in the history
  • Loading branch information
ancaantochi authored Jan 9, 2019
1 parent d9b12c9 commit 0e6a402
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 5 deletions.
3 changes: 2 additions & 1 deletion edgelet/edgelet-core/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use futures::{Future, Stream};
use pid::Pid;
use serde_json;

use edgelet_utils::ensure_not_empty_with_context;
use edgelet_utils::{ensure_not_empty_with_context, serialize_ordered};

use error::{Error, ErrorKind, Result};

Expand Down Expand Up @@ -144,6 +144,7 @@ pub struct ModuleSpec<T> {
type_: String,
config: T,
#[serde(default = "HashMap::new")]
#[serde(serialize_with = "serialize_ordered")]
env: HashMap<String, String>,
}

Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use std::collections::HashMap;
pub use error::{Error, ErrorKind};
pub use logging::log_failure;
pub use macros::ensure_not_empty_with_context;
pub use ser_de::{serde_clone, string_or_struct};
pub use ser_de::{serde_clone, serialize_ordered, string_or_struct};

pub fn parse_query(query: &str) -> HashMap<&str, &str> {
query
Expand Down
44 changes: 43 additions & 1 deletion edgelet/edgelet-utils/src/ser_de.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright (c) Microsoft. All rights reserved.

use std::collections::{BTreeMap, HashMap};
use std::fmt;
use std::hash::BuildHasher;
use std::marker::PhantomData;
use std::result::Result as StdResult;
use std::str::FromStr;

use failure::ResultExt;
use serde::de::{self, Deserialize, DeserializeOwned, Deserializer, MapAccess, Visitor};
use serde::ser::Serialize;
use serde::ser::{Serialize, Serializer};
use serde_json;

use error::{ErrorKind, Result};
Expand Down Expand Up @@ -67,6 +69,18 @@ where
.context(ErrorKind::SerdeClone)?)
}

pub fn serialize_ordered<S, T>(
x: &HashMap<String, String, T>,
serializer: S,
) -> StdResult<S::Ok, S::Error>
where
S: Serializer,
T: BuildHasher,
{
let sorted_map: BTreeMap<_, _> = x.into_iter().collect();
sorted_map.serialize(serializer)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -94,6 +108,12 @@ mod tests {
options: Options,
}

#[derive(Debug, Serialize)]
struct Setting {
#[serde(serialize_with = "serialize_ordered")]
map: HashMap<String, String>,
}

#[test]
fn deser_from_map() {
let container_json = json!({
Expand Down Expand Up @@ -151,4 +171,26 @@ mod tests {
assert_eq!(c1.name, c2.name);
assert_eq!(c1.age, c2.age);
}

#[test]
fn serde_serialize_map() {
let setting_json = json!({
"map": {
"a": "val1",
"b": "val2",
"c": "val3"
}
})
.to_string();

let mut map = HashMap::new();
map.insert("b".to_string(), "val2".to_string());
map.insert("a".to_string(), "val1".to_string());
map.insert("c".to_string(), "val3".to_string());

let map_container = Setting { map };

let s = serde_json::to_string(&map_container).unwrap();
assert_eq!(s, setting_json);
}
}
20 changes: 20 additions & 0 deletions edgelet/iotedged/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ mod tests {
#[cfg(unix)]
static GOOD_SETTINGS1: &str = "test/linux/sample_settings1.yaml";
#[cfg(unix)]
static GOOD_SETTINGS2: &str = "test/linux/sample_settings2.yaml";
#[cfg(unix)]
static BAD_SETTINGS: &str = "test/linux/bad_sample_settings.yaml";
#[cfg(unix)]
static GOOD_SETTINGS_TG: &str = "test/linux/sample_settings.tg.yaml";
Expand All @@ -277,6 +279,8 @@ mod tests {
#[cfg(windows)]
static GOOD_SETTINGS1: &str = "test/windows/sample_settings1.yaml";
#[cfg(windows)]
static GOOD_SETTINGS2: &str = "test/windows/sample_settings2.yaml";
#[cfg(windows)]
static BAD_SETTINGS: &str = "test/windows/bad_sample_settings.yaml";
#[cfg(windows)]
static GOOD_SETTINGS_TG: &str = "test/windows/sample_settings.tg.yaml";
Expand Down Expand Up @@ -364,6 +368,22 @@ mod tests {
assert_eq!(settings.diff_with_cached(path).unwrap(), false);
}

#[test]
fn diff_with_same_cached_env_var_unordered_returns_false() {
let tmp_dir = TempDir::new("blah").unwrap();
let path = tmp_dir.path().join("cache");
let settings1 = Settings::<DockerConfig>::new(Some(GOOD_SETTINGS2)).unwrap();
let settings_to_write = serde_json::to_string(&settings1).unwrap();
let sha_to_write = Sha256::digest_str(&settings_to_write);
let base64_to_write = base64::encode(&sha_to_write);
FsFile::create(path.clone())
.unwrap()
.write_all(base64_to_write.as_bytes())
.unwrap();
let settings = Settings::<DockerConfig>::new(Some(GOOD_SETTINGS)).unwrap();
assert_eq!(settings.diff_with_cached(path).unwrap(), false);
}

#[test]
fn diff_with_different_cached_returns_true() {
let tmp_dir = TempDir::new("blah").unwrap();
Expand Down
4 changes: 3 additions & 1 deletion edgelet/iotedged/test/linux/sample_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ provisioning:
agent:
name: "edgeAgent"
type: "docker"
env: {}
env:
abc: "value1"
acd: "value2"
config:
image: "microsoft/azureiotedge-agent:1.0"
auth: {}
Expand Down
31 changes: 31 additions & 0 deletions edgelet/iotedged/test/linux/sample_settings2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

# Configures the provisioning mode
provisioning:
source: "manual"
device_connection_string: "HostName=something.something.com;DeviceId=something;SharedAccessKey=something"
agent:
name: "edgeAgent"
type: "docker"
env:
acd: "value2"
abc: "value1"
config:
image: "microsoft/azureiotedge-agent:1.0"
auth: {}
hostname: "localhost"

# Sets the connection uris for clients
connect:
workload_uri: "http://localhost:8081"
management_uri: "http://localhost:8080"

# Sets the uris to listen on
# These can be different than the connect uris.
# For instance, when using the fd:// scheme for systemd
listen:
workload_uri: "http://0.0.0.0:8081"
management_uri: "http://0.0.0.0:8080"
homedir: "/tmp"
moby_runtime:
uri: "http://localhost:2375"
network: "azure-iot-edge"
4 changes: 3 additions & 1 deletion edgelet/iotedged/test/windows/sample_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ provisioning:
agent:
name: "edgeAgent"
type: "docker"
env: {}
env:
abc: "value1"
acd: "value2"
config:
image: "microsoft/azureiotedge-agent:1.0"
auth: {}
Expand Down
31 changes: 31 additions & 0 deletions edgelet/iotedged/test/windows/sample_settings2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

# Configures the provisioning mode
provisioning:
source: "manual"
device_connection_string: "HostName=something.something.com;DeviceId=something;SharedAccessKey=something"
agent:
name: "edgeAgent"
type: "docker"
env:
acd: "value2"
abc: "value1"
config:
image: "microsoft/azureiotedge-agent:1.0"
auth: {}
hostname: "localhost"

# Sets the connection uris for clients
connect:
workload_uri: "http://localhost:8081"
management_uri: "http://localhost:8080"

# Sets the uris to listen on
# These can be different than the connect uris.
# For instance, when using the fd:// scheme for systemd
listen:
workload_uri: "http://0.0.0.0:8081"
management_uri: "http://0.0.0.0:8080"
homedir: "C:\\Temp"
moby_runtime:
uri: "http://localhost:2375"
network: "azure-iot-edge"

0 comments on commit 0e6a402

Please sign in to comment.