diff --git a/lib/manifold/api/project.rb b/lib/manifold/api/project.rb index 4cbb12a..a24035d 100644 --- a/lib/manifold/api/project.rb +++ b/lib/manifold/api/project.rb @@ -24,6 +24,7 @@ def workspaces def generate workspaces.each(&:generate) + generate_terraform_entrypoint end def workspaces_directory @@ -39,6 +40,46 @@ def vectors_directory def workspace_directories workspaces_directory.children.select(&:directory?) end + + def generate_terraform_entrypoint + terraform_config = { + "terraform" => { + "required_providers" => { + "google" => { + "source" => "hashicorp/google", + "version" => "~> 4.0" + } + } + }, + "provider" => { + "google" => { + "project" => "${var.project_id}" + } + }, + "variable" => { + "project_id" => { + "description" => "The GCP project ID where resources will be created", + "type" => "string" + } + }, + "module" => generate_workspace_modules + } + + terraform_path.write(JSON.pretty_generate(terraform_config)) + end + + def generate_workspace_modules + workspaces.each_with_object({}) do |workspace, modules| + modules[workspace.name] = { + "source" => "./workspaces/#{workspace.name}", + "project_id" => "${var.project_id}" + } + end + end + + def terraform_path + directory.join("main.tf.json") + end end end end diff --git a/lib/manifold/api/workspace.rb b/lib/manifold/api/workspace.rb index 0f33f4c..e5f95cf 100644 --- a/lib/manifold/api/workspace.rb +++ b/lib/manifold/api/workspace.rb @@ -30,6 +30,7 @@ def generate return unless manifold_exists? && any_vectors? generate_dimensions + generate_terraform logger.info("Generated BigQuery dimensions table schema for workspace '#{name}'.") end @@ -99,6 +100,57 @@ def any_vectors? def vectors manifold_yaml["vectors"] end + + def generate_terraform + generate_terraform_config + generate_terraform_variables + end + + def generate_terraform_config + tf = { + "resource" => { + "google_bigquery_dataset" => { + name => { + "dataset_id" => name, + "project" => "${var.PROJECT_ID}", + "location" => "US" + } + }, + "google_bigquery_table" => { + "dimensions" => { + "dataset_id" => name, + "project" => "var.PROJECT_ID", + "table_id" => "dimensions", + "schema" => "${file(\"${path.module}/tables/dimensions.json\")}", + "depends_on" => ["google_bigquery_dataset.#{name}"] + } + } + } + } + + terraform_main_path.write(JSON.pretty_generate(tf)) + end + + def generate_terraform_variables + variables_config = { + "variable" => { + "PROJECT_ID" => { + "description" => "The GCP project ID where resources will be created", + "type" => "string" + } + } + } + + terraform_variables_path.write(JSON.pretty_generate(variables_config)) + end + + def terraform_main_path + directory.join("main.tf.json") + end + + def terraform_variables_path + directory.join("variables.tf.json") + end end end end diff --git a/lib/manifold/cli.rb b/lib/manifold/cli.rb index e121480..0d7a7f7 100644 --- a/lib/manifold/cli.rb +++ b/lib/manifold/cli.rb @@ -47,8 +47,9 @@ def add(name) desc "generate", "Generate BigQuery schema for all workspaces in the project" def generate - name = Pathname.pwd.basename.to_s - project = API::Project.new(name, directory: Pathname.pwd, logger:) + path = Pathname.pwd + name = path.basename.to_s + project = API::Project.new(name, directory: path, logger:) project.generate logger.info "Generated BigQuery schema for all workspaces in the project." end diff --git a/spec/manifold/api/project_spec.rb b/spec/manifold/api/project_spec.rb index 0b09a5a..b7b857a 100644 --- a/spec/manifold/api/project_spec.rb +++ b/spec/manifold/api/project_spec.rb @@ -48,8 +48,8 @@ end describe "#generate" do - let(:workspace_one) { instance_double(Manifold::API::Workspace) } - let(:workspace_two) { instance_double(Manifold::API::Workspace) } + let(:workspace_one) { instance_double(Manifold::API::Workspace, name: "workspace_one") } + let(:workspace_two) { instance_double(Manifold::API::Workspace, name: "workspace_two") } before do described_class.create(name) @@ -64,5 +64,25 @@ project.generate expect([workspace_one, workspace_two]).to all(have_received(:generate)) end + + it "creates a terraform configuration file" do + project.generate + expect(project.directory.join("main.tf.json")).to be_file + end + + it "includes workspace modules in the terraform configuration" do + project.generate + config = JSON.parse(project.directory.join("main.tf.json").read) + expect(config["module"]).to include( + "workspace_one" => { + "source" => "./workspaces/workspace_one", + "project_id" => "${var.project_id}" + }, + "workspace_two" => { + "source" => "./workspaces/workspace_two", + "project_id" => "${var.project_id}" + } + ) + end end end