Ejemplo n.º 1
0
        /// <summary>
        /// Expands any environment variables of the form <b>${NAME}</b> in the input
        /// string and returns the expanded result.
        /// </summary>
        /// <param name="input">The input string.</param>
        /// <returns>The expanded output string.</returns>
        private string ExpandEnvironmentVars(string input)
        {
            Covenant.Requires <ArgumentNullException>(input != null);

            using (var reader = new PreprocessReader(input))
            {
                reader.VariableExpansionRegex = PreprocessReader.CurlyVariableExpansionRegex;

                // Load the environment variables.

                foreach (DictionaryEntry item in Environment.GetEnvironmentVariables())
                {
                    // $hack(jeff.lill):
                    //
                    // Some common Windows enmvironment variables names include characters
                    // like parens that are not compatible with PreprocessReader.  We're
                    // just going to catch the exceptions and ignore these.

                    var key = (string)item.Key;

                    if (PreprocessReader.VariableValidationRegex.IsMatch(key))
                    {
                        reader.Set(key, (string)item.Value);
                    }
                }

                // Perform the substitutions.

                return(reader.ReadToEnd());
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Reads the script text from a file path, replacing any variable references with the
 /// variable's value.
 /// </summary>
 /// <param name="scriptPath">The script file path.</param>
 /// <returns>The processed script text.</returns>
 private string LoadScript(string scriptPath)
 {
     using (var reader = new StreamReader(scriptPath))
     {
         using (var preprocessReader = new PreprocessReader(reader, variables))
         {
             return(preprocessReader.ReadToEnd());
         }
     }
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Reads the script text from an embedded resource file, replacing any variable references with the
 /// variable's value.
 /// </summary>
 /// <param name="scriptFile">The embedded resurce script file.</param>
 /// <returns>The processed script text.</returns>
 private string LoadScript(IStaticFile scriptFile)
 {
     using (var reader = scriptFile.OpenReader())
     {
         using (var preprocessReader = new PreprocessReader(reader, variables))
         {
             return(preprocessReader.ReadToEnd());
         }
     }
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Reads the script text from an embedded resource file, replacing any variable references with the
 /// variable's value.
 /// </summary>
 /// <param name="scriptFile">The embedded resurce script file.</param>
 /// <returns>The processed script text.</returns>
 private string LoadScript(IStaticFile scriptFile)
 {
     using (var reader = scriptFile.OpenReader())
     {
         using (var preprocessReader = new PreprocessReader(reader, variables))
         {
             preprocessReader.VariableExpansionRegex = PreprocessReader.CurlyVariableExpansionRegex;
             return(preprocessReader.ReadToEnd());
         }
     }
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Reads the script text from a file path, replacing any variable references with the
 /// variable's value.
 /// </summary>
 /// <param name="scriptPath">The script file path.</param>
 /// <returns>The processed script text.</returns>
 private string LoadScript(string scriptPath)
 {
     using (var reader = new StreamReader(scriptPath))
     {
         using (var preprocessReader = new PreprocessReader(reader, variables))
         {
             preprocessReader.VariableExpansionRegex = PreprocessReader.CurlyVariableExpansionRegex;
             return(preprocessReader.ReadToEnd());
         }
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Parses a hive definition from JSON text.
        /// </summary>
        /// <param name="json">The JSON text.</param>
        /// <param name="strict">Optionally require that all input properties map to <see cref="HiveDefinition"/> properties.</param>
        /// <returns>The parsed <see cref="HiveDefinition"/>.</returns>
        /// <remarks>
        /// <note>
        /// The source is first preprocessed using <see cref="PreprocessReader"/>
        /// and then is parsed as JSON.
        /// </note>
        /// </remarks>
        public static HiveDefinition FromJson(string json, bool strict = false)
        {
            Covenant.Requires <ArgumentNullException>(json != null);

            using (var stringReader = new StringReader(json))
            {
                using (var preprocessReader = new PreprocessReader(stringReader))
                {
                    return(NeonHelper.JsonDeserialize <HiveDefinition>(preprocessReader.ReadToEnd(), strict: strict));
                }
            }
        }
Ejemplo n.º 7
0
        public void Comments_CustomMarkers()
        {
            // Verify that we can handle multiple custom comment prefixes.

            var input =
                @"# This is a comment
     # This is a comment
This is a test
// This is a comment
of the emergency # not a comment
broadcasting system
#

a
ab
abc

";

            var expected =
                @"

This is a test

of the emergency # not a comment
broadcasting system


a
ab
abc

";

            using (var reader = new PreprocessReader(input))
            {
                reader.ClearCommentMarkers();
                reader.AddCommentMarker("#");
                reader.AddCommentMarker("//");

                var output = reader.ReadToEnd();

                Assert.Equal(expected, output);
            }
        }
Ejemplo n.º 8
0
        public void DisableStatements()
        {
            const string input =
                @"# line1
line2
# line3
";

            using (var reader = new PreprocessReader(input)
            {
                LineEnding = LineEnding.CRLF
            })
            {
                reader.ProcessStatements = false;

                Assert.Equal("# line1\r\nline2\r\n# line3\r\n", reader.ReadToEnd());
            }
        }
Ejemplo n.º 9
0
        public async Task LineEndings()
        {
            const string input =
                @"line1
line2
line3
";

            using (var reader = new PreprocessReader(input)
            {
                LineEnding = LineEnding.CRLF
            })
            {
                Assert.Equal("line1\r\nline2\r\nline3\r\n", reader.ReadToEnd());
            }

            using (var reader = new PreprocessReader(input)
            {
                LineEnding = LineEnding.LF
            })
            {
                Assert.Equal("line1\nline2\nline3\n", reader.ReadToEnd());
            }

            using (var reader = new PreprocessReader(input)
            {
                LineEnding = LineEnding.CRLF
            })
            {
                Assert.Equal("line1\r\nline2\r\nline3\r\n", await reader.ReadToEndAsync());
            }

            using (var reader = new PreprocessReader(input)
            {
                LineEnding = LineEnding.LF
            })
            {
                Assert.Equal("line1\nline2\nline3\n", await reader.ReadToEndAsync());
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Parses a hive definition from a file.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <param name="strict">Optionally require that all input properties map to <see cref="HiveDefinition"/> properties.</param>
        /// <returns>The parsed <see cref="HiveDefinition"/>.</returns>
        /// <exception cref="ArgumentException">Thrown if the definition is not valid.</exception>
        /// <remarks>
        /// <note>
        /// The source is first preprocessed using <see cref="PreprocessReader"/>
        /// and then is parsed as JSON.
        /// </note>
        /// </remarks>
        public static HiveDefinition FromFile(string path, bool strict = false)
        {
            Covenant.Requires <ArgumentNullException>(path != null);

            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                using (var stringReader = new StreamReader(stream))
                {
                    using (var preprocessReader = new PreprocessReader(stringReader))
                    {
                        var hiveDefinition = NeonHelper.JsonDeserialize <HiveDefinition>(preprocessReader.ReadToEnd(), strict: strict);

                        if (hiveDefinition == null)
                        {
                            throw new ArgumentException($"Invalid hive definition in [{path}].");
                        }

                        // Populate the [node.Name] properties from the dictionary name.

                        foreach (var item in hiveDefinition.NodeDefinitions)
                        {
                            var node = item.Value;

                            if (string.IsNullOrEmpty(node.Name))
                            {
                                node.Name = item.Key;
                            }
                            else if (item.Key != node.Name)
                            {
                                throw new FormatException($"The node names don't match [\"{item.Key}\" != \"{node.Name}\"].");
                            }
                        }

                        hiveDefinition.Validate();

                        return(hiveDefinition);
                    }
                }
            }
        }
Ejemplo n.º 11
0
        /// <inheritdoc/>
        public override async Task RunAsync(CommandLine commandLine)
        {
            if (commandLine.HasHelpOption)
            {
                Console.WriteLine(usage);
                Program.Exit(0);
            }

            var splitCommandLine = commandLine.Split("--");
            var leftCommandLine  = splitCommandLine.Left;
            var rightCommandLine = splitCommandLine.Right;

            if (rightCommandLine == null || rightCommandLine.Arguments.Length == 0)
            {
                Console.Error.WriteLine("*** ERROR: Expected a command after a [--] argument.");
                Program.Exit(1);
            }

            // All arguments on the left command line should be VARIABLES files.
            // We're going to open each of these and set any enviroment variables
            // like [NAME=VALUE] we find.
            //
            // Note that these files may be encrypted.  If any are, we'll decrypt
            // to a temporary file before we read them.

            foreach (var path in leftCommandLine.Arguments)
            {
                if (!File.Exists(path))
                {
                    Console.Error.WriteLine($"*** ERROR: File [{path}] does not exist.");
                    Program.Exit(1);
                }

                DecryptWithAction(path,
                                  decryptedPath =>
                {
                    var lineNumber = 1;

                    foreach (var line in File.ReadAllLines(decryptedPath))
                    {
                        var trimmed = line.Trim();

                        if (line == string.Empty || line.StartsWith("#"))
                        {
                            continue;
                        }

                        var fields = line.Split('=', 2);

                        if (fields.Length != 2 || fields[0] == string.Empty)
                        {
                            Console.Error.WriteLine($"*** ERROR: [{path}:{lineNumber}] is not formatted like: NAME=VALUE");
                            Program.Exit(1);
                        }

                        var name  = fields[0].Trim();
                        var value = fields[1].Trim();

                        Environment.SetEnvironmentVariable(name, value);

                        lineNumber++;
                    }
                });
            }

            // Any left command line options with a "--" prefix also specify environment variables.

            foreach (var option in leftCommandLine.Options.Where(o => o.Key.StartsWith("--")))
            {
                Environment.SetEnvironmentVariable(option.Key.Substring(2), option.Value);
            }

            // We've read all of the variable files and left command line options
            // and initialized all environment variables.  Now we need to process
            // and then execute the right command line.

            var tempFiles = new List <TempFile>();

            try
            {
                var subcommand = rightCommandLine.Items;

                // Note that the first element of the subcommand specifies the
                // executable so we don't need to process that.

                for (int i = 1; i < subcommand.Length; i++)
                {
                    var arg = subcommand[i];

                    if (arg.StartsWith("_..."))
                    {
                        // Argument is a reference to a potentially encrypted
                        // file that needs to be passed decrypted.

                        var path = arg.Substring(4);

                        if (!File.Exists(path))
                        {
                            Console.Error.WriteLine($"*** ERROR: File [{path}] does not exist.");
                            Program.Exit(1);
                        }

                        if (NeonVault.IsEncrypted(path))
                        {
                            var tempFile = new TempFile();

                            tempFiles.Add(tempFile);
                            vault.Decrypt(path, tempFile.Path);

                            path = tempFile.Path;
                        }

                        subcommand[i] = path;
                    }
                    else if (arg.StartsWith("_.."))
                    {
                        // Argument is a reference to a potentially encrypted text file
                        // with environment variable references we'll need to update.

                        var path = arg.Substring(3);

                        if (!File.Exists(path))
                        {
                            Console.Error.WriteLine($"*** ERROR: File [{path}] does not exist.");
                            Program.Exit(1);
                        }

                        if (NeonVault.IsEncrypted(path))
                        {
                            var tempFile = new TempFile();

                            tempFiles.Add(tempFile);
                            vault.Decrypt(path, tempFile.Path);

                            path = tempFile.Path;
                        }

                        subcommand[i] = path;

                        // Perform the subsitutions.

                        var unprocessed      = File.ReadAllText(path);
                        var processed        = string.Empty;
                        var linuxLineEndings = !unprocessed.Contains("\r\n");

                        using (var reader = new StreamReader(path))
                        {
                            using (var preprocessor = new PreprocessReader(reader))
                            {
                                preprocessor.ExpandVariables        = true;
                                preprocessor.LineEnding             = linuxLineEndings ? LineEnding.LF : LineEnding.CRLF;
                                preprocessor.ProcessStatements      = false;
                                preprocessor.StripComments          = false;
                                preprocessor.VariableExpansionRegex = PreprocessReader.AngleVariableExpansionRegex;

                                processed = preprocessor.ReadToEnd();
                            }
                        }

                        File.WriteAllText(path, processed);
                    }
                    else if (arg.StartsWith("_."))
                    {
                        // Argument is a reference to an environment variable.

                        var name = arg.Substring(2);

                        if (name == string.Empty)
                        {
                            Console.Error.WriteLine($"*** ERROR: Subcommand argument [{arg}] is not valid.");
                            Program.Exit(1);
                        }

                        var value = Environment.GetEnvironmentVariable(name);

                        if (value == null)
                        {
                            Console.Error.WriteLine($"*** ERROR: Subcommand argument [{arg}] references an undefined environment variable.");
                            Program.Exit(2);
                        }

                        subcommand[i] = value;
                    }
                    else if (arg.StartsWith("-"))
                    {
                        // Argument is a command line option.  We'll check to see if
                        // it contains a reference to an environment variable.

                        var valuePos = arg.IndexOf("=_.");

                        if (valuePos != -1)
                        {
                            var optionPart = arg.Substring(0, valuePos);
                            var name       = arg.Substring(valuePos + 3);

                            if (name == string.Empty)
                            {
                                Console.Error.WriteLine($"*** ERROR: Subcommand argument [{arg}] is not valid.");
                                Program.Exit(1);
                            }

                            var value = Environment.GetEnvironmentVariable(name);

                            if (value == null)
                            {
                                Console.Error.WriteLine($"*** ERROR: Subcommand argument [{arg}] references an undefined environment variable.");
                                Program.Exit(1);
                            }

                            subcommand[i] = $"{optionPart}={value}";
                        }
                    }
                    else
                    {
                        // Otherwise, expand any envrionment variable references.

                        subcommand[i] = Environment.ExpandEnvironmentVariables(subcommand[i]);
                    }
                }

                // Execute the subcommand.

                var subcommandArgs = new List <object>();

                foreach (var subcommandArg in subcommand)
                {
                    subcommandArgs.Add(subcommandArg);
                }

                var exitCode = NeonHelper.Execute(subcommand[0], subcommandArgs.Skip(1).ToArray());

                Program.Exit(exitCode);
            }
            finally
            {
                foreach (var tempFile in tempFiles)
                {
                    tempFile.Dispose();
                }
            }

            Program.Exit(0);
            await Task.CompletedTask;
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Parses a cluster definition from YAML text.
        /// </summary>
        /// <param name="yaml">The JSON text.</param>
        /// <param name="strict">Optionally require that all input properties map to <see cref="ClusterDefinition"/> properties.</param>
        /// <returns>The parsed <see cref="ClusterDefinition"/>.</returns>
        /// <remarks>
        /// <note>
        /// The source is first preprocessed using <see cref="PreprocessReader"/>
        /// and then is parsed as YAML.
        /// </note>
        /// </remarks>
        public static ClusterDefinition FromYaml(string yaml, bool strict = false)
        {
            Covenant.Requires <ArgumentNullException>(yaml != null, nameof(yaml));

            using (var stringReader = new StringReader(yaml))
            {
                using (var preprocessReader = new PreprocessReader(stringReader))
                {
                    var clusterDefinition = NeonHelper.YamlDeserialize <ClusterDefinition>(preprocessReader.ReadToEnd(), strict: strict);

                    clusterDefinition.Validate();

                    return(clusterDefinition);
                }
            }
        }