/// <summary> /// Writes the module blocks for any modules this module refers to. /// </summary> /// <returns>Task to await.</returns> public async Task WriteModuleBlocksAsync() { var modulesFile = Path.Combine(this.ModuleDirectory, TerraformExporterConstants.ModulesFile); if (File.Exists(modulesFile)) { // In case we removed all pre-existing submodule references File.Delete(modulesFile); } if (!this.NestedModules.Any()) { return; } using (var fs = AsyncFileHelpers.OpenWriteAsync(modulesFile)) using (var writer = new StreamWriter(fs, AsyncFileHelpers.DefaultEncoding)) { foreach (var module in this.NestedModules) { var sb = new StringBuilder().AppendLine($"module \"{module.Name}\" {{").AppendLine( $" source = \"./{module.Settings.ModuleDirectory.Replace('\\', '/')}\""); if (module.IsImported) { // We can only emit module arguments once the module has been imported and // corresponding "variable" declarations are visible to Terraform command. foreach (var input in module.Inputs.Where(i => !(i.IsDataSource || i is PseudoParameterInput))) { sb.AppendLine($" {input.GenerateVariableAssignment()}"); } } sb.AppendLine("}"); await writer.WriteLineAsync(sb.ToString()); } } }
/// <summary> /// Recursively process nested stacks. /// </summary> /// <param name="settings">The settings.</param> /// <param name="warnings">The warnings.</param> /// <returns>Module being processed.</returns> private static async Task <ModuleInfo> ProcessChildModule( ITerraformExportSettings settings, IList <string> warnings) { var childModules = new List <ModuleInfo>(); foreach (var child in settings.Resources.Where( r => r.ResourceType == TerraformExporterConstants.AwsCloudFormationStack)) { var logicalId = child.LogicalResourceId; var stackName = GetStackName(child.StackResource.PhysicalResourceId); var stackData = await StackHelper.ReadStackAsync( settings.CloudFormationClient, stackName, new Dictionary <string, object>()); var childModuleSettings = settings.CopyWith( stackData.Template, stackData.Resources, stackData.Outputs, stackName, Path.Combine("modules", stackName), logicalId); childModules.Add(await ProcessChildModule(childModuleSettings, warnings)); } var workingDirectory = Path.Combine(settings.WorkspaceDirectory, settings.ModuleDirectory); if (!Directory.Exists(workingDirectory)) { Directory.CreateDirectory(workingDirectory); } settings.Logger.LogInformation($"Processing stack {settings.StackName}..."); var scriptFile = Path.Combine(workingDirectory, TerraformExporterConstants.MainScriptFile); ModuleInfo module; using (var fs = settings.IsRootModule ? AsyncFileHelpers.OpenAppendAsync(scriptFile) : AsyncFileHelpers.OpenWriteAsync(scriptFile)) using (var writer = new StreamWriter(fs, AsyncFileHelpers.DefaultEncoding)) { var thisModuleSettings = settings.CopyWith( settings.Template, settings.Resources.Where(r => r.ResourceType != TerraformExporterConstants.AwsCloudFormationStack), null, settings.StackName, settings.IsRootModule ? "." : settings.ModuleDirectory, settings.LogicalId); module = new ModuleInfo( thisModuleSettings, childModules, new InputVariableProcessor(thisModuleSettings, warnings).ProcessInputs(), thisModuleSettings.CloudFormationOutputs); await module.ProcessResources(writer, warnings); } await module.WriteModuleBlocksAsync(); return(module); }