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

Support Unix domain sockets in IoT Edge on Windows #518

Merged
merged 26 commits into from
Nov 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fe8e946
Support Unix domain sockets in IoT Edge on Windows
damonbarry Nov 2, 2018
2c2ff08
Merge branch 'master' into windows-uds-2
damonbarry Nov 6, 2018
2b095a2
Don't configure workload/mgmt endpoints as HTTP in Windows installer
damonbarry Nov 6, 2018
1d17c51
In Windows installer, configure workload/mgmt endpoints as HTTP for RS4
damonbarry Nov 6, 2018
240d1f3
Address PR feedback
damonbarry Nov 6, 2018
be710f4
cargo fmt
damonbarry Nov 6, 2018
ea9704c
Fix compiler errors on Linux
damonbarry Nov 7, 2018
016596c
Merge remote-tracking branch 'upstream/master' into windows-uds-2
damonbarry Nov 7, 2018
bad01ba
Address pull request feedback
damonbarry Nov 7, 2018
2ef304b
Fix clippy errors
damonbarry Nov 7, 2018
9e829e1
cargo fmt
damonbarry Nov 7, 2018
e2278c1
Fix CombinedEdgeletConfigProvider test
damonbarry Nov 7, 2018
4d66059
Reduce dependency churn
damonbarry Nov 7, 2018
911c82c
Add requirements info to config.yaml for UDS
damonbarry Nov 9, 2018
07f3100
Replace unwrap with expect
damonbarry Nov 9, 2018
1d6375e
Merge branch 'master' into windows-uds-2
damonbarry Nov 9, 2018
184d6b7
Make tests build on Linux
damonbarry Nov 9, 2018
1e6ad84
Fix clippy errors for tests
damonbarry Nov 9, 2018
c599df4
Use dependencies from Azure repos
damonbarry Nov 12, 2018
aaa2eaa
Merge branch 'master' into windows-uds-2
damonbarry Nov 12, 2018
b5053bc
correct linux -> unix
damonbarry Nov 13, 2018
80c6881
Merge branch 'master' into windows-uds-2
damonbarry Nov 13, 2018
b238171
Temporarily ignore a test on Windows
damonbarry Nov 13, 2018
e9ac6af
Temporarily ignore two more UDS tests on Windows
damonbarry Nov 13, 2018
3bc1f95
Temporarily remove UDS support from Windows installer
damonbarry Nov 13, 2018
194a8f0
Address PR feedback
damonbarry Nov 13, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Edgelet.Docker
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using global::Docker.DotNet.Models;
using Microsoft.Azure.Devices.Edge.Agent.Core;
using Microsoft.Azure.Devices.Edge.Agent.Docker;
Expand Down Expand Up @@ -78,7 +80,7 @@ void MountSockets(IModule module, CreateContainerParameters createOptions)
SetMountOptions(createOptions, workloadUri);
}

// If Management URI is Unix domain socket, and the module is the EdgeAgent, then mount it ino the container.
// If Management URI is Unix domain socket, and the module is the EdgeAgent, then mount it into the container.
var managementUri = new Uri(this.configSource.Configuration.GetValue<string>(Constants.EdgeletManagementUriVariableName));
if (managementUri.Scheme == "unix"
&& module.Name.Equals(Constants.EdgeAgentModuleName, StringComparison.OrdinalIgnoreCase))
Expand All @@ -91,10 +93,20 @@ static void SetMountOptions(CreateContainerParameters createOptions, Uri uri)
{
HostConfig hostConfig = createOptions.HostConfig ?? new HostConfig();
IList<string> binds = hostConfig.Binds ?? new List<string>();
binds.Add($"{uri.AbsolutePath}:{uri.AbsolutePath}");
string path = BindPath(uri);
binds.Add($"{path}:{path}");

hostConfig.Binds = binds;
createOptions.HostConfig = hostConfig;
}

static String BindPath(Uri uri)
{
// On Windows we need to bind to the parent folder. We can't bind
// directly to the socket file.
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Path.GetDirectoryName(uri.LocalPath)
: uri.AbsolutePath;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Edgelet.Docker.Test
{
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using global::Docker.DotNet.Models;
using Microsoft.Azure.Devices.Edge.Agent.Core;
using Microsoft.Azure.Devices.Edge.Agent.Docker;
Expand Down Expand Up @@ -31,12 +32,21 @@ public void TestVolMount()
module.SetupGet(m => m.Config).Returns(new DockerConfig("nginx:latest"));
module.SetupGet(m => m.Name).Returns(Constants.EdgeAgentModuleName);

var unixUris = new Dictionary<string, string>
{
{Constants.EdgeletWorkloadUriVariableName, "unix:///path/to/workload.sock" },
{Constants.EdgeletManagementUriVariableName, "unix:///path/to/mgmt.sock" }
};

var windowsUris = new Dictionary<string, string>
{
{Constants.EdgeletWorkloadUriVariableName, "unix:///C:/path/to/workload/sock" },
{Constants.EdgeletManagementUriVariableName, "unix:///C:/path/to/mgmt/sock" }
};

IConfigurationRoot configRoot = new ConfigurationBuilder().AddInMemoryCollection(
new Dictionary<string, string>
{
{Constants.EdgeletWorkloadUriVariableName, "unix:///var/run/iotedgedworkload.sock" },
{Constants.EdgeletManagementUriVariableName, "unix:///var/run/iotedgedmgmt.sock" }
}).Build();
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? windowsUris : unixUris
).Build();
var configSource = Mock.Of<IConfigSource>(s => s.Configuration == configRoot);
ICombinedConfigProvider<CombinedDockerConfig> provider = new CombinedEdgeletConfigProvider(new[] { new AuthConfig() }, configSource);

Expand All @@ -48,8 +58,14 @@ public void TestVolMount()
Assert.NotNull(config.CreateOptions.HostConfig);
Assert.NotNull(config.CreateOptions.HostConfig.Binds);
Assert.Equal(2, config.CreateOptions.HostConfig.Binds.Count);
Assert.Equal("/var/run/iotedgedworkload.sock:/var/run/iotedgedworkload.sock", config.CreateOptions.HostConfig.Binds[0]);
Assert.Equal("/var/run/iotedgedmgmt.sock:/var/run/iotedgedmgmt.sock", config.CreateOptions.HostConfig.Binds[1]);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Assert.Equal("C:\\path\\to\\workload:C:\\path\\to\\workload", config.CreateOptions.HostConfig.Binds[0]);
Assert.Equal("C:\\path\\to\\mgmt:C:\\path\\to\\mgmt", config.CreateOptions.HostConfig.Binds[1]);
} else {
Assert.Equal("/path/to/workload.sock:/path/to/workload.sock", config.CreateOptions.HostConfig.Binds[0]);
Assert.Equal("/path/to/mgmt.sock:/path/to/mgmt.sock", config.CreateOptions.HostConfig.Binds[1]);
}
}

[Fact]
Expand Down
60 changes: 60 additions & 0 deletions edgelet/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 20 additions & 4 deletions edgelet/contrib/config/windows/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,20 @@ hostname: "<ADD HOSTNAME HERE>"
#
# The following uri schemes are supported:
# http - connect over TCP
# unix - connect over Unix domain socket
#
# If the 'unix' scheme is selected, the daemon expects that the parent
# directory of the specified socket file already exists, and that the Windows
# group 'NT AUTHORITY\Authenticated Users' has been given 'Modify' rights on
# the directory. For example, if the URI "unix:///C:/path/to/sock.file" is
# specified, then the directory "C:\path\to" must exist with the correct
# permissions.
#
###############################################################################

connect:
management_uri: "http://<GATEWAY_ADDRESS>:15580"
workload_uri: "http://<GATEWAY_ADDRESS>:15581"
management_uri: "unix:///C:/ProgramData/iotedge/mgmt/sock"
workload_uri: "unix:///C:/ProgramData/iotedge/workload/sock"

###############################################################################
# Listen settings
Expand All @@ -120,12 +128,20 @@ connect:
#
# The following uri schemes are supported:
# http - listen over TCP
# unix - listen over Unix domain socket
#
# If the 'unix' scheme is selected, the daemon expects that the parent
# directory of the specified socket file already exists, and that the Windows
# group 'NT AUTHORITY\Authenticated Users' has been given 'Modify' rights on
# the directory. For example, if the URI "unix:///C:/path/to/sock.file" is
# specified, then the directory "C:\path\to" must exist with the correct
# permissions.
#
###############################################################################

listen:
management_uri: "http://<GATEWAY_ADDRESS>:15580"
workload_uri: "http://<GATEWAY_ADDRESS>:15581"
management_uri: "unix:///C:/ProgramData/iotedge/mgmt/sock"
workload_uri: "unix:///C:/ProgramData/iotedge/workload/sock"

###############################################################################
# Home Directory
Expand Down
16 changes: 10 additions & 6 deletions edgelet/edgelet-docker/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::collections::HashMap;
use std::convert::From;
use std::ops::Deref;
use std::path::PathBuf;
use std::time::Duration;

use base64;
Expand All @@ -22,7 +23,7 @@ use edgelet_core::{
LogOptions, Module, ModuleRegistry, ModuleRuntime, ModuleRuntimeState, ModuleSpec,
SystemInfo as CoreSystemInfo,
};
use edgelet_http::UrlConnector;
use edgelet_http::{UrlConnector, UrlExt};
use edgelet_utils::log_failure;

use error::{Error, ErrorKind, Result};
Expand Down Expand Up @@ -53,9 +54,12 @@ impl DockerModuleRuntime {
let client = Client::builder().build(UrlConnector::new(docker_url)?);

// extract base path - the bit that comes after the scheme
let base_path = get_base_path(docker_url);
let base_path = get_base_path(docker_url)?;
let mut configuration = Configuration::new(client);
configuration.base_path = base_path.to_string();
configuration.base_path = base_path
.to_str()
.expect("URL points to a path that cannot be represented in UTF-8")
.to_string();

let scheme = docker_url.scheme().to_string();
configuration.uri_composer = Box::new(move |base_path, path| {
Expand Down Expand Up @@ -96,10 +100,10 @@ impl DockerModuleRuntime {
}
}

fn get_base_path(url: &Url) -> &str {
fn get_base_path(url: &Url) -> Result<PathBuf> {
match url.scheme() {
"unix" => url.path(),
_ => url.as_str(),
"unix" => Ok(url.to_uds_file_path()?),
_ => Ok(url.as_str().into()),
}
}

Expand Down
13 changes: 7 additions & 6 deletions edgelet/edgelet-http-mgmt/src/client/module.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Copyright (c) Microsoft. All rights reserved.

use std::fmt;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;

use edgelet_core::SystemInfo as CoreSystemInfo;
use edgelet_core::*;
use edgelet_docker::{self, DockerConfig};
use edgelet_http::{UrlConnector, API_VERSION};
use edgelet_http::{UrlConnector, UrlExt, API_VERSION};
use futures::future::{self, FutureResult};
use futures::prelude::*;
use futures::stream;
Expand All @@ -29,9 +30,9 @@ impl ModuleClient {
pub fn new(url: &Url) -> Result<Self, Error> {
let client = Client::builder().build(UrlConnector::new(url)?);

let base_path = get_base_path(url);
let base_path = get_base_path(url)?;
let mut configuration = Configuration::new(client);
configuration.base_path = base_path.to_string();
configuration.base_path = base_path.to_str().ok_or(ErrorKind::Utf8)?.to_string();

let scheme = url.scheme().to_string();
configuration.uri_composer = Box::new(move |base_path, path| {
Expand All @@ -45,10 +46,10 @@ impl ModuleClient {
}
}

fn get_base_path(url: &Url) -> &str {
fn get_base_path(url: &Url) -> Result<PathBuf, Error> {
match url.scheme() {
"unix" => url.path(),
_ => url.as_str(),
"unix" => Ok(url.to_uds_file_path()?),
_ => Ok(url.as_str().into()),
}
}

Expand Down
2 changes: 2 additions & 0 deletions edgelet/edgelet-http-mgmt/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub enum ErrorKind {
NotModified,
#[fail(display = "Parse error")]
Parse,
#[fail(display = "UTF-8 encode/decode error")]
Utf8,
}

impl Fail for Error {
Expand Down
Loading