Example #1
0
        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;
 }
Example #4
0
        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]");
        }
Example #5
0
        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);
            }
        }