Ejemplo n.º 1
0
 /// <summary>
 /// Ensures that the <see cref="TestDistroName"/> does not exist from a past test run.
 /// </summary>
 public static void RemoveTestDistro()
 {
     if (Wsl2Proxy.Exists(TestDistroName))
     {
         Wsl2Proxy.Unregister(TestDistroName);
     }
 }
Ejemplo n.º 2
0
        public async Task PathMapping()
        {
            // Verify that file system path mapping works in both directions.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var tempFolder = new TempFolder())
            {
                try
                {
                    Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);

                    var distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);

                    // Linux --> Windows

                    Assert.Equal($@"\\wsl$\{distro.Name}\", distro.ToWindowsPath("/"));
                    Assert.Equal($@"\\wsl$\{distro.Name}\bin\bash", distro.ToWindowsPath("/bin/bash"));

                    // Windows --> Linux

                    Assert.Equal("/mnt/c/", distro.ToLinuxPath(@"C:\"));
                    Assert.Equal("/mnt/c/Program Files/test.exe", distro.ToLinuxPath(@"c:\Program Files\test.exe"));
                }
                finally
                {
                    TestHelper.RemoveTestDistro();
                }
            }
        }
Ejemplo n.º 3
0
        public async Task Execute_WithPathSpaces()
        {
            // Verify that we can execute SUDO and non-SUDO commands from a temporary
            // folder that includes spaces.  This happens when the user's Windows username
            // include spaces.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var folderWithSpaces = new TempFolder(folder: Path.Combine(Path.GetTempPath(), $"test {Guid.NewGuid().ToString("d")}")))
            {
                using (var tempFolder = new TempFolder())
                {
                    try
                    {
                        Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);

                        var distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);

                        distro.TempFolder = folderWithSpaces.Path;

                        Assert.Contains("Hello World!", distro.Execute("echo", "Hello World!").OutputText);
                        Assert.Contains("Hello World!", distro.SudoExecute("echo", "Hello World!").OutputText);
                    }
                    finally
                    {
                        TestHelper.RemoveTestDistro();
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public async Task UploadFile()
        {
            // Verify that we can upload a text file to the distribution
            // and set its owner and permissions.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var tempFolder = new TempFolder())
            {
                try
                {
                    Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);

                    var distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);
                    var text   =
                        @"Line 1
Line 2
Line 3
Line 4
";
                    // Write a file using the defaults to convert CRLF-->LF with
                    // no special permissions.

                    distro.UploadFile($"/home/{KubeConst.SysAdminUser}/test1.txt", text, toLinuxText: true);
                    Assert.Equal("Line 1\nLine 2\nLine 3\nLine 4\n", File.ReadAllText(distro.ToWindowsPath($"/home/{KubeConst.SysAdminUser}/test1.txt")));

                    var response = distro.SudoExecute("ls", "-l", $"/home/{KubeConst.SysAdminUser}/test1.txt");

                    response.EnsureSuccess();
                    Assert.StartsWith("-rw-r--r-- ", response.OutputText);

                    // Write another file using the leaving the line endings as CRLF
                    // and some permissions.  Also verify that the file is owned by
                    // the default distro user.

                    distro.UploadFile($"/home/{KubeConst.SysAdminUser}/test2.txt", text, permissions: "666", toLinuxText: false);
                    Assert.Equal("Line 1\r\nLine 2\r\nLine 3\r\nLine 4\r\n", File.ReadAllText(distro.ToWindowsPath($"/home/{KubeConst.SysAdminUser}/test2.txt")));

                    response = distro.SudoExecute("ls", "-l", $"/home/{KubeConst.SysAdminUser}/test2.txt");

                    response.EnsureSuccess();
                    Assert.StartsWith("-rw-rw-rw- ", response.OutputText);
                    Assert.Contains($"{KubeConst.SysAdminUser} {KubeConst.SysAdminUser}", response.OutputText);
                }
                finally
                {
                    TestHelper.RemoveTestDistro();
                }
            }
        }
Ejemplo n.º 5
0
        public async Task ImportExport()
        {
            // Verify that we can import and export distributions.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var tempFolder = new TempFolder())
            {
                try
                {
                    //---------------------------------------------------------
                    // Import the distribution and verify that we can execute a command.

                    Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);
                    Assert.True(Wsl2Proxy.Exists(TestHelper.TestDistroName));

                    var distro = new Wsl2Proxy(TestHelper.TestDistroName);

                    Assert.Equal(TestHelper.TestDistroName, distro.Name);
                    Assert.Contains("Hello World!", distro.Execute("echo", "Hello World!").OutputText);

                    //---------------------------------------------------------
                    // Terminate the distribution and verify that we can export it.

                    var exportPath = Path.Combine(tempFolder.Path, "export.tar");

                    Wsl2Proxy.Terminate(TestHelper.TestDistroName);
                    Wsl2Proxy.Export(TestHelper.TestDistroName, exportPath);

                    //---------------------------------------------------------
                    // Remove the test distribution and verify that we can regenerate
                    // it from the image we just exported.

                    TestHelper.RemoveTestDistro();

                    Wsl2Proxy.Import(TestHelper.TestDistroName, exportPath, tempFolder.Path);
                    Assert.True(Wsl2Proxy.Exists(TestHelper.TestDistroName));

                    distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);

                    Assert.Contains("Hello World!", distro.Execute("echo", "Hello World!").OutputText);
                }
                finally
                {
                    TestHelper.RemoveTestDistro();
                }
            }
        }
Ejemplo n.º 6
0
        public async Task StartAs_Sysadmin()
        {
            // Verify that we can start a distro as [sysadmin] without configuring
            // or starting systemd.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var tempFolder = new TempFolder())
            {
                try
                {
                    Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);

                    // Start as the [sysadmin] user.

                    var distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);

                    Assert.Equal(KubeConst.SysAdminUser, distro.User);

                    // Expecting to be running under MSFT's [init] process 1.

                    var response = distro.Execute("ps", "-e");

                    Assert.Equal(0, response.ExitCode);
                    Assert.Contains("init", response.OutputText);

                    // Expecting to be logged in as [root]

                    response = distro.Execute("echo", "$LOGNAME");

                    Assert.Equal(0, response.ExitCode);
                    Assert.Equal(KubeConst.SysAdminUser, response.OutputText.Trim());
                }
                finally
                {
                    TestHelper.RemoveTestDistro();
                }
            }
        }
Ejemplo n.º 7
0
        public async Task NoSudoPassword()
        {
            // Verify that the distribution doesn't prompt for a SUDO password.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var tempFolder = new TempFolder())
            {
                try
                {
                    Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);
                    Assert.True(Wsl2Proxy.Exists(TestHelper.TestDistroName));

                    var distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);

                    Assert.Contains("Hello World!", distro.SudoExecute("echo", "Hello World!").OutputText);
                }
                finally
                {
                    TestHelper.RemoveTestDistro();
                }
            }
        }
Ejemplo n.º 8
0
        public async Task Execute()
        {
            // Verify that we can execute SUDO and non-SUDO commands.

            var imagePath = await TestHelper.GetTestImageAsync();

            using (var tempFolder = new TempFolder())
            {
                try
                {
                    Wsl2Proxy.Import(TestHelper.TestDistroName, imagePath, tempFolder.Path);

                    var distro = new Wsl2Proxy(TestHelper.TestDistroName, user: KubeConst.SysAdminUser);

                    Assert.Contains("Hello World!", distro.Execute("echo", "Hello World!").OutputText);
                    Assert.Contains("Hello World!", distro.SudoExecute("echo", "Hello World!").OutputText);
                }
                finally
                {
                    TestHelper.RemoveTestDistro();
                }
            }
        }
Ejemplo n.º 9
0
        /// <inheritdoc/>
        public override async Task RunAsync(CommandLine commandLine)
        {
            if (commandLine.HasHelpOption || commandLine.Arguments.Length == 0)
            {
                Console.WriteLine(usage);
                Program.Exit(0);
            }

            var sourceFolder = commandLine.Arguments.ElementAtOrDefault(0);
            var outputPath   = commandLine.Arguments.ElementAtOrDefault(1);
            var sbGccArgs    = new StringBuilder();

            if (string.IsNullOrEmpty(sourceFolder) || string.IsNullOrEmpty(outputPath))
            {
                Console.WriteLine(usage);
                Program.Exit(1);
            }

            foreach (var arg in commandLine.Arguments.Skip(2))
            {
                sbGccArgs.AppendWithSeparator(arg);
            }

            // We're going to build this within the distro at [/tmp/wsl-util/GUID] by
            // recursively copying the contents of SOURCE-FOLDER to this directory,
            // running GCC to build the thing, passing [*.c] to include all of the C
            // source files and generating the binary as [output.bin] with the folder.
            //
            // We're also going to clear the [/tmp/wsl-util] folder first to ensure that we don't
            // accumulate any old build files over time and we'll also ensure that
            // [gcc] is installed.

            var defaultDistro = Wsl2Proxy.GetDefault();

            if (string.IsNullOrEmpty(defaultDistro))
            {
                Console.Error.WriteLine("*** ERROR: There is no default WSL2 distro.");
                Program.Exit(1);
            }

            var distro = new Wsl2Proxy(defaultDistro);

            if (!distro.IsDebian)
            {
                Console.Error.WriteLine($"*** ERROR: Your default WSL2 distro [{distro.Name}] is running: {distro.OSRelease["ID"]}/{distro.OSRelease["ID_LIKE"]}");
                Console.Error.WriteLine($"           The CRI-O build requires an Debian/Ubuntu based distribution.");
                Program.Exit(1);
            }

            var linuxUtilFolder    = LinuxPath.Combine("/", "tmp", "wsl-util");
            var linuxBuildFolder   = LinuxPath.Combine(linuxUtilFolder, Guid.NewGuid().ToString("d"));
            var linuxOutputPath    = LinuxPath.Combine(linuxBuildFolder, "output.bin");
            var windowsUtilFolder  = distro.ToWindowsPath(linuxUtilFolder);
            var windowsBuildFolder = distro.ToWindowsPath(linuxBuildFolder);

            try
            {
                // Delete the [/tmp/wsl-util] folder on Linux and the copy the
                // source from the Windows side into a fresh distro folder.

                NeonHelper.DeleteFolder(windowsUtilFolder);
                NeonHelper.CopyFolder(sourceFolder, windowsBuildFolder);

                // Install [safe-apt-get] if it's not already present.  We're using this
                // because it's possible that projects build in parallel and it's possible
                // that multiple GCC commands could also be running in parallel.

                var linuxSafeAptGetPath   = "/usr/bin/safe-apt-get";
                var windowsSafeAptGetPath = distro.ToWindowsPath(linuxSafeAptGetPath);

                if (!File.Exists(windowsSafeAptGetPath))
                {
                    var resources  = Assembly.GetExecutingAssembly().GetResourceFileSystem("WslUtil.Resources");
                    var toolScript = resources.GetFile("/safe-apt-get.sh").ReadAllText();

                    // Note that we need to escape all "$" characters in the script
                    // so the upload script won't attempt to replace any variables
                    // (with blanks).

                    toolScript = toolScript.Replace("$", "\\$");

                    var uploadScript =
                        $@"
cat <<EOF > {linuxSafeAptGetPath}
{toolScript}
EOF

chmod 754 {linuxSafeAptGetPath}
";
                    distro.SudoExecuteScript(uploadScript).EnsureSuccess();
                }

                // Perform the build.

                var buildScript =
                    $@"
set -euo pipefail

safe-apt-get install -yq gcc

cd {linuxBuildFolder}
gcc *.c -o {linuxOutputPath} {sbGccArgs}
";
                distro.SudoExecuteScript(buildScript).EnsureSuccess();

                // Copy the build output to the Windows output path.

                Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
                NeonHelper.DeleteFile(outputPath);
                File.Copy(distro.ToWindowsPath(linuxOutputPath), outputPath);
            }
            finally
            {
                // Remove the temporary distro folder.

                NeonHelper.DeleteFolder(windowsBuildFolder);
            }

            await Task.CompletedTask;
        }