Creating custom modules for CloudInit.NET

Included with the binaries is a dll called CloudInit.Modules.Core.dll this dll contains all the core references to create a new module. Include this reference in your project to begin creating a new module.

IInputModule Interface

namespace CloudInit.Modules.Core
{
    /// <summary>
    /// Cloud init module interface
    /// </summary>
    public interface IInputModule
    {
        /// <summary>
        /// Event log object to log errors
        /// </summary>
        EventLog EventLog { get; set; }

        /// <summary>
        /// Log file where the output of the script should be written
        /// </summary>
        String LogFile { get; set; }

        /// <summary>
        /// Header of the file that will cause the engine to use this module
        /// </summary>
        String Header { get; }

        /// <summary>
        /// Executes the script
        /// </summary>
        /// <param name="input">Input file to execute</param>
        /// <returns>
        /// Output log of the execution
        /// </returns>
        String Execute(String input);
    }
}

The two important parts of this interface are the Header Property and the Execute method. When the CloudInit service starts it loads all the modules and registers the header so that any scripts downloaded that contain this header will use this module for execution. The execute method is where all the magic happens. Lets look at the PowershellIncludeModule as an example of how to write a module.

        /// <summary>
        /// Header of the file that will cause the engine to use this module
        /// </summary>
        public override String Header
        {
            get
            {
                // Any file that includes this header will use this module
                // to execute the script
                return "#include";
            }
        }

Now lets take a look at the execute method which downloads all the files in the list and executes them using the PowershellModuleBase class's execute method.

        /// <summary>
        /// Executes the script
        /// </summary>
        /// <param name="input">Input file to execute</param>
        /// <returns>
        /// Output log of the execution
        /// </returns>
        public override String Execute(String input)
        {
            using (StringWriter writer = new StringWriter())
            using (StringReader reader = new StringReader(input))
            {
                String line = String.Empty;

                // Read all the lines of the file ignoring any that are comments
                while ((line = reader.ReadLine()) != null)
                {
                    if (!line.StartsWith("#"))
                    {
                        // Download the file and execute contents as a powershell script
                        String data = DownloadFile(line);

                        // You don't have to execute anything else at this 
                        // point if you don't want to but in this scenario we want 
                        // the data downloaded from each file to be executed as a 
                        // powershell script so we'll use the base class to execute the 
                        // contents as a script
                        String output = base.Execute(data);
                    }
                }
                return writer.ToString();
            }
        }

        /// <summary>
        /// Downloads a file from an http endpoint
        /// </summary>
        /// <param name="url">Location of the file to be downloaded</param>
        /// <returns>Contents of the file downloaded</returns>
        private String DownloadFile(String url)
        {
            // Make a web request to the provided url
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Method = "GET";
            request.Timeout = 30000;

            // Get the response from the request
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                // Read the steam into a string
                String content = reader.ReadToEnd();

                reader.Close();
                response.Close();

                // Return the file contents
                return content;
            }
        }

Last edited Dec 20, 2011 at 10:07 PM by bwight4157, version 1

Comments

No comments yet.