diff options
Diffstat (limited to 'lib/chef/util/dsc/configuration_generator.rb')
-rw-r--r-- | lib/chef/util/dsc/configuration_generator.rb | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/chef/util/dsc/configuration_generator.rb b/lib/chef/util/dsc/configuration_generator.rb new file mode 100644 index 0000000000..ea949bb9c4 --- /dev/null +++ b/lib/chef/util/dsc/configuration_generator.rb @@ -0,0 +1,115 @@ +# +# Author:: Adam Edwards (<adamed@getchef.com>) +# +# Copyright:: 2014, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/util/powershell/cmdlet' + +class Chef::Util::DSC + class ConfigurationGenerator + def initialize(node, config_directory) + @node = node + @config_directory = config_directory + end + + def configuration_document_from_script_code(code, configuration_flags, shellout_flags) + Chef::Log.debug("DSC: DSC code:\n '#{code}'") + generated_script_path = write_document_generation_script(code, 'chef_dsc') + begin + configuration_document_from_script_path(generated_script_path, 'chef_dsc', configuration_flags, shellout_flags) + ensure + ::FileUtils.rm(generated_script_path) + end + end + + def configuration_document_from_script_path(script_path, configuration_name, configuration_flags, shellout_flags) + validate_configuration_name!(configuration_name) + + document_generation_cmdlet = Chef::Util::Powershell::Cmdlet.new( + @node, + configuration_document_generation_code(script_path, configuration_name)) + + merged_configuration_flags = get_merged_configuration_flags!(configuration_flags, configuration_name) + + document_generation_cmdlet.run(merged_configuration_flags, shellout_flags) + configuration_document_location = find_configuration_document(configuration_name) + + if ! configuration_document_location + raise RuntimeError, "No DSC configuration for '#{configuration_name}' was generated from supplied DSC script" + end + + configuration_document = get_configuration_document(configuration_document_location) + ::FileUtils.rm_rf(configuration_document_location) + configuration_document + end + + protected + + # From PowerShell error help for the Configuration language element: + # Standard names may only contain letters (a-z, A-Z), numbers (0-9), and underscore (_). + # The name may not be null or empty, and should start with a letter. + def validate_configuration_name!(configuration_name) + if !!(configuration_name =~ /\A[A-Za-z]+[_a-zA-Z0-9]*\Z/) == false + raise ArgumentError, 'Configuration `#{configuration_name}` is not a valid PowerShell cmdlet name' + end + end + + def get_merged_configuration_flags!(configuration_flags, configuration_name) + merged_configuration_flags = { :outputpath => configuration_document_directory(configuration_name) } + if configuration_flags + configuration_flags.map do | switch, value | + if merged_configuration_flags.key?(switch.to_s.downcase.to_sym) + raise ArgumentError, "The `flags` attribute for the dsc_script resource contained a command line switch :#{switch.to_s} that is disallowed." + end + merged_configuration_flags[switch.to_s.downcase.to_sym] = value + end + end + merged_configuration_flags + end + + def configuration_code(code, configuration_name) + "$ProgressPreference = 'SilentlyContinue';Configuration '#{configuration_name}'\n{\n\t#{code}\n}\n" + end + + def configuration_document_generation_code(configuration_script, configuration_name) + ". '#{configuration_script}';#{configuration_name}" + end + + def write_document_generation_script(code, configuration_name) + script_path = "#{@config_directory}/chef_dsc_config.ps1" + ::File.open(script_path, 'wt') do | script | + script.write(configuration_code(code, configuration_name)) + end + script_path + end + + def find_configuration_document(configuration_name) + document_directory = configuration_document_directory(configuration_name) + document_file_name = ::Dir.entries(document_directory).find { | path | path =~ /.*.mof/ } + ::File.join(document_directory, document_file_name) + end + + def configuration_document_directory(configuration_name) + ::File.join(@config_directory, configuration_name) + end + + def get_configuration_document(document_path) + ::File.open(document_path, 'rb') do | file | + file.read + end + end + end +end |