From 3f1e9f848aec5605a394b7ca971cc30f80d9d4b4 Mon Sep 17 00:00:00 2001 From: Hariharan Thavachelvam <164553783+thavaahariharangit@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:59:07 +0000 Subject: [PATCH] If overridden file exists, then process it and find the missing key values from base file. (#11137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * If overridden file exists, then process it and find the missing key values from parent. * Updated as per review comments, Sorbet fixes. * lint error fixes * Lint error fixes --------- Co-authored-by: “Thavachelvam <“thavaahariharangit@git.com”> --- .../lib/dependabot/terraform/file_parser.rb | 8 +++++ .../lib/dependabot/terraform/file_selector.rb | 36 ++++++++++++++++++- .../dependabot/terraform/file_parser_spec.rb | 12 +++++++ .../child_module_with_no_source/main.tf | 4 +++ .../child_module_with_no_source/override.tf | 3 ++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 terraform/spec/fixtures/projects/child_module_with_no_source/main.tf create mode 100644 terraform/spec/fixtures/projects/child_module_with_no_source/override.tf diff --git a/terraform/lib/dependabot/terraform/file_parser.rb b/terraform/lib/dependabot/terraform/file_parser.rb index ee25a3e297..0eb9b5438e 100644 --- a/terraform/lib/dependabot/terraform/file_parser.rb +++ b/terraform/lib/dependabot/terraform/file_parser.rb @@ -58,6 +58,14 @@ def ecosystem def parse_terraform_files(dependency_set) terraform_files.each do |file| modules = parsed_file(file).fetch("module", {}) + # If override.tf files are present, we need to merge the modules + if override_terraform_files.any? + override_terraform_files.each do |override_file| + override_modules = parsed_file(override_file).fetch("module", {}) + modules = merge_modules(override_modules, modules) + end + end + modules.each do |name, details| details = details.first diff --git a/terraform/lib/dependabot/terraform/file_selector.rb b/terraform/lib/dependabot/terraform/file_selector.rb index 6b6431c47b..0488006137 100644 --- a/terraform/lib/dependabot/terraform/file_selector.rb +++ b/terraform/lib/dependabot/terraform/file_selector.rb @@ -11,6 +11,9 @@ module FileSelector extend T::Sig extend T::Helpers + TF_EXTENSION = ".tf" + OVERRIDE_TF_EXTENSION = "override.tf" + abstract! sig { abstract.returns(T::Array[Dependabot::DependencyFile]) } @@ -22,7 +25,12 @@ def dependency_files; end sig { returns(T::Array[Dependabot::DependencyFile]) } def terraform_files - dependency_files.select { |f| f.name.end_with?(".tf") } + dependency_files.select { |f| f.name.end_with?(TF_EXTENSION) && !f.name.end_with?(OVERRIDE_TF_EXTENSION) } + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def override_terraform_files + dependency_files.select { |f| f.name.end_with?(OVERRIDE_TF_EXTENSION) } end sig { returns(T::Array[Dependabot::DependencyFile]) } @@ -34,6 +42,32 @@ def terragrunt_files def lockfile dependency_files.find { |f| lockfile?(f.name) } end + + sig do + params(modules: T::Hash[String, T::Array[T::Hash[String, T.untyped]]], + base_modules: T::Hash[String, + T::Array[T::Hash[String, + T.untyped]]]) + .returns(T::Hash[String, + T::Array[T::Hash[String, + T.untyped]]]) + end + def merge_modules(modules, base_modules) + merged_modules = base_modules.dup + + modules.each do |key, value| + merged_modules[key] = + if merged_modules.key?(key) + T.must(merged_modules[key]).map do |base_value| + base_value.merge(T.must(value.first)) + end + else + value + end + end + + merged_modules + end end end end diff --git a/terraform/spec/dependabot/terraform/file_parser_spec.rb b/terraform/spec/dependabot/terraform/file_parser_spec.rb index fce0de48fd..b814e2f213 100644 --- a/terraform/spec/dependabot/terraform/file_parser_spec.rb +++ b/terraform/spec/dependabot/terraform/file_parser_spec.rb @@ -870,6 +870,18 @@ end end + context "when the overridden module does not include source" do + let(:files) { project_dependency_files("child_module_with_no_source") } + + it "has the module with no source" do + module_dependency = dependencies.find { |d| d.name == "babbel/cloudfront-bucket/aws" } + + expect(module_dependency).not_to be_nil + expect(module_dependency.version).to eq("2.2.0") + expect(module_dependency.requirements.first[:source][:module_identifier]).to eq("babbel/cloudfront-bucket/aws") + end + end + context "with a toplevel provider" do let(:files) { project_dependency_files("provider") } diff --git a/terraform/spec/fixtures/projects/child_module_with_no_source/main.tf b/terraform/spec/fixtures/projects/child_module_with_no_source/main.tf new file mode 100644 index 0000000000..c813efb265 --- /dev/null +++ b/terraform/spec/fixtures/projects/child_module_with_no_source/main.tf @@ -0,0 +1,4 @@ +module "aws" { + source = "babbel/cloudfront-bucket/aws" + version = "2.0.0" +} diff --git a/terraform/spec/fixtures/projects/child_module_with_no_source/override.tf b/terraform/spec/fixtures/projects/child_module_with_no_source/override.tf new file mode 100644 index 0000000000..0be201d2e5 --- /dev/null +++ b/terraform/spec/fixtures/projects/child_module_with_no_source/override.tf @@ -0,0 +1,3 @@ +module "aws" { + version = "2.2.0" +}