public void MountVolumeConstructorParsesStringInput() { // Arrange MountVolume target = new MountVolume("/dst/dir"); // Maps anonymous Docker volume into target dir MountVolume source_target = new MountVolume("/src/dir:/dst/dir"); // Maps source to target dir MountVolume target_ro = new MountVolume("/dst/dir:ro"); MountVolume source_target_ro = new MountVolume("/src/dir:/dst/dir:ro"); // Assert Assert.Null(target.SourceVolumePath); Assert.Equal("/dst/dir", target.TargetVolumePath); Assert.False(target.ReadOnly); Assert.Equal("/src/dir", source_target.SourceVolumePath); Assert.Equal("/dst/dir", source_target.TargetVolumePath); Assert.False(source_target.ReadOnly); Assert.Null(target_ro.SourceVolumePath); Assert.Equal("/dst/dir", target_ro.TargetVolumePath); Assert.True(target_ro.ReadOnly); Assert.Equal("/src/dir", source_target_ro.SourceVolumePath); Assert.Equal("/dst/dir", source_target_ro.TargetVolumePath); Assert.True(source_target_ro.ReadOnly); }
public void run() { MountVolume got = new MountVolume(Input); Assert.True(Expected.SourceVolumePath == got.SourceVolumePath, $"{Title} - testing property SourceVolumePath. Expected: '{Expected.SourceVolumePath}' Got: '{got.SourceVolumePath}' "); Assert.True(Expected.TargetVolumePath == got.TargetVolumePath, $"{Title} - testing property TargetVolumePath. Expected: '{Expected.TargetVolumePath}' Got: '{got.TargetVolumePath}'"); Assert.True(Expected.ReadOnly == got.ReadOnly, $"{Title} - testing property ReadOnly. Expected: '{Expected.ReadOnly}' Got: '{got.ReadOnly}'"); }
public MountVolumeTest(string input, MountVolume expected, string title = "") { this.Input = input; this.Expected = expected; this.Title = title; }
private async Task StartContainerAsync(IExecutionContext executionContext, ContainerInfo container) { Trace.Entering(); ArgUtil.NotNull(executionContext, nameof(executionContext)); ArgUtil.NotNull(container, nameof(container)); ArgUtil.NotNullOrEmpty(container.ContainerImage, nameof(container.ContainerImage)); Trace.Info($"Container name: {container.ContainerName}"); Trace.Info($"Container image: {container.ContainerImage}"); Trace.Info($"Container options: {container.ContainerCreateOptions}"); var groupName = container.IsJobContainer ? "Starting job container" : $"Starting {container.ContainerNetworkAlias} service container"; executionContext.Output($"##[group]{groupName}"); foreach (var port in container.UserPortMappings) { Trace.Info($"User provided port: {port.Value}"); } foreach (var volume in container.UserMountVolumes) { Trace.Info($"User provided volume: {volume.Value}"); var mount = new MountVolume(volume.Value); if (string.Equals(mount.SourceVolumePath, "/", StringComparison.OrdinalIgnoreCase)) { executionContext.Warning($"Volume mount {volume.Value} is going to mount '/' into the container which may cause file ownership change in the entire file system and cause Actions Runner to lose permission to access the disk."); } } // Pull down docker image with retry up to 3 times int retryCount = 0; int pullExitCode = 0; while (retryCount < 3) { pullExitCode = await _dockerManger.DockerPull(executionContext, container.ContainerImage); if (pullExitCode == 0) { break; } else { retryCount++; if (retryCount < 3) { var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10)); executionContext.Warning($"Docker pull failed with exit code {pullExitCode}, back off {backOff.TotalSeconds} seconds before retry."); await Task.Delay(backOff); } } } if (retryCount == 3 && pullExitCode != 0) { throw new InvalidOperationException($"Docker pull failed with exit code {pullExitCode}"); } if (container.IsJobContainer) { // Configure job container - Mount workspace and tools, set up environment, and start long running process var githubContext = executionContext.ExpressionValues["github"] as GitHubContext; ArgUtil.NotNull(githubContext, nameof(githubContext)); var workingDirectory = githubContext["workspace"] as StringContextData; ArgUtil.NotNullOrEmpty(workingDirectory, nameof(workingDirectory)); container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Work), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Work)))); #if OS_WINDOWS container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Externals), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Externals)))); #else if (Environment.GetEnvironmentVariable("K8S_POD_NAME") != null) { container.MountVolumes.Add(new MountVolume(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), "__externals_copy"), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Externals)), true)); } else { container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Externals), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Externals)), true)); } #endif container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Temp), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Temp)))); container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Actions), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Actions)))); container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Tools), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Tools)))); var tempHomeDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Temp), "_github_home"); Directory.CreateDirectory(tempHomeDirectory); container.MountVolumes.Add(new MountVolume(tempHomeDirectory, "/github/home")); container.AddPathTranslateMapping(tempHomeDirectory, "/github/home"); container.ContainerEnvironmentVariables["HOME"] = container.TranslateToContainerPath(tempHomeDirectory); var tempWorkflowDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Temp), "_github_workflow"); Directory.CreateDirectory(tempWorkflowDirectory); container.MountVolumes.Add(new MountVolume(tempWorkflowDirectory, "/github/workflow")); container.AddPathTranslateMapping(tempWorkflowDirectory, "/github/workflow"); container.ContainerWorkDirectory = container.TranslateToContainerPath(workingDirectory); container.ContainerEntryPoint = "tail"; container.ContainerEntryPointArgs = "\"-f\" \"/dev/null\""; } container.ContainerId = await _dockerManger.DockerCreate(executionContext, container); ArgUtil.NotNullOrEmpty(container.ContainerId, nameof(container.ContainerId)); // Start container int startExitCode = await _dockerManger.DockerStart(executionContext, container.ContainerId); if (startExitCode != 0) { throw new InvalidOperationException($"Docker start fail with exit code {startExitCode}"); } try { // Make sure container is up and running var psOutputs = await _dockerManger.DockerPS(executionContext, $"--all --filter id={container.ContainerId} --filter status=running --no-trunc --format \"{{{{.ID}}}} {{{{.Status}}}}\""); if (psOutputs.FirstOrDefault(x => !string.IsNullOrEmpty(x))?.StartsWith(container.ContainerId) != true) { // container is not up and running, pull docker log for this container. await _dockerManger.DockerPS(executionContext, $"--all --filter id={container.ContainerId} --no-trunc --format \"{{{{.ID}}}} {{{{.Status}}}}\""); int logsExitCode = await _dockerManger.DockerLogs(executionContext, container.ContainerId); if (logsExitCode != 0) { executionContext.Warning($"Docker logs fail with exit code {logsExitCode}"); } executionContext.Warning($"Docker container {container.ContainerId} is not in running state."); } } catch (Exception ex) { // pull container log is best effort. Trace.Error("Catch exception when check container log and container status."); Trace.Error(ex); } // Gather runtime container information if (!container.IsJobContainer) { var service = new DictionaryContextData() { ["id"] = new StringContextData(container.ContainerId), ["ports"] = new DictionaryContextData(), ["network"] = new StringContextData(container.ContainerNetwork) }; container.AddPortMappings(await _dockerManger.DockerPort(executionContext, container.ContainerId)); foreach (var port in container.PortMappings) { (service["ports"] as DictionaryContextData)[port.ContainerPort] = new StringContextData(port.HostPort); } executionContext.JobContext.Services[container.ContainerNetworkAlias] = service; } else { var configEnvFormat = "--format \"{{range .Config.Env}}{{println .}}{{end}}\""; var containerEnv = await _dockerManger.DockerInspect(executionContext, container.ContainerId, configEnvFormat); container.ContainerRuntimePath = DockerUtil.ParsePathFromConfigEnv(containerEnv); executionContext.JobContext.Container["id"] = new StringContextData(container.ContainerId); } executionContext.Output("##[endgroup]"); }
static void Main(string[] args) { Logger.Log("ImageFS In Development"); Logger.Log("By LostSoulfly"); Logger.Log("Please enter the path to your Volume image."); Logger.Log("If the image does not contain a volume, it will be created."); Console.Write("ImageFS> "); volumeFile = Console.ReadLine(); Logger.Log("Please enter the volume password:"******"ImageFS> "); volumePassword = Console.ReadLine(); if (!File.Exists(volumeFile)) { Logger.Log("Unable to locate Volume image!", Logger.LOG_LEVEL.ERR); Console.ReadKey(); Environment.Exit(-1); } if (volumePassword.Length <= 3) { Logger.Log("Password is too short.", Logger.LOG_LEVEL.ERR); Console.ReadKey(); Environment.Exit(-1); } Logger.Log("Attempting to extract ImageFS Volume.."); imageReader = new Stego.Reader(volumeFile, volumePassword); imageWriter = new Writer(); (PNGMask_Core.DataType dataType, object data) = imageReader.ReadData(ImageFSHelpers.StorageMethod.EOF); (PNGMask_Core.DataType dataType2, object data2) = imageReader.ReadData(ImageFSHelpers.StorageMethod.IDAT); Logger.Log("EOF Data: " + Enum.GetName(typeof(PNGMask_Core.DataType), dataType)); Logger.Log("IDAT Data: " + Enum.GetName(typeof(PNGMask_Core.DataType), dataType2)); if (dataType == PNGMask_Core.DataType.FileSystem) { Console.WriteLine(); volumeTable = JsonConvert.DeserializeObject <ImageFSVolume>((string)data); Logger.Log($"MaxFileSize: {volumeTable.maxFileSize}"); Logger.Log($"MaxFileCount: {volumeTable.maxFileCount}"); Logger.Log($"volumeDirectories: {volumeTable.volumeDirectories.Count}"); Logger.Log($"CurrentFileCount: {volumeTable.currentFileCount}"); Logger.Log($"ImagesUsed: {volumeTable.volumeData.Count}"); volumeOpen = true; } else if (dataType2 == PNGMask_Core.DataType.FileSystem) { Logger.Log("Falling back to volume backup file.."); volumeTable = JsonConvert.DeserializeObject <ImageFSVolume>((string)data2); Logger.Log($"MaxFileSize: {volumeTable.maxFileSize}"); Logger.Log($"MaxFileCount: {volumeTable.maxFileCount}"); Logger.Log($"volumeDirectories: {volumeTable.volumeDirectories.Count}"); Logger.Log($"CurrentFileCount: {volumeTable.currentFileCount}"); Logger.Log($"ImagesUsed: {volumeTable.volumeData.Count}"); volumeOpen = true; } else if (dataType == PNGMask_Core.DataType.None) { Logger.Log("File does not contain a ImageFS Volume. Create one?"); Console.Write("ImageFS> "); if (Console.ReadKey().Key == ConsoleKey.Y) { Console.WriteLine(); volumeTable = new ImageFSVolume(); Logger.Log("Volume created. Writing new volume to image.."); imageWriter.HideFileSystem(volumeFile, JsonConvert.SerializeObject(volumeTable), volumePassword, ImageFSHelpers.StorageMethod.IDAT); Logger.Log("Writing volume backup to EOF section.."); imageWriter.HideFileSystem(volumeFile, JsonConvert.SerializeObject(volumeTable), volumePassword, ImageFSHelpers.StorageMethod.EOF); volumeOpen = true; } } if (!volumeOpen) { Console.ReadKey(); Environment.Exit(0); } int userInput = 0; do { userInput = MainMenu(); switch (userInput) { case 1: // extract file ExtractFileMenu(); break; case 2: // insert file InsertFileMenu(); break; case 3: // new volume directory CreateVolumeDirectoryMenu(); break; case 4: // Add donor images AddDonorImagesMenu(); break; case 5: // volume maintenance VolumeMaintenanceMenu(); break; case 6: // Mount volume dokanMount = new MountVolume(volumeTable); dokanMount.Mount("n:\\"); break; } } while (userInput != 0); Logger.Log("Exiting ImageFS. Save volume?"); Console.Write("ImageFS> "); if (Console.ReadKey().Key == ConsoleKey.Y) { Console.WriteLine(); Logger.Log("Writing volume to image IDAT.."); imageWriter.HideFileSystem(volumeFile, JsonConvert.SerializeObject(volumeTable), volumePassword, ImageFSHelpers.StorageMethod.IDAT); Logger.Log("Writing volume backup to EOF section.."); imageWriter.HideFileSystem(volumeFile, JsonConvert.SerializeObject(volumeTable), volumePassword, ImageFSHelpers.StorageMethod.EOF); } }