diff --git a/app/controllers/terraform_registry_controller.rb b/app/controllers/terraform_registry_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..00e66cdba4911ffcc185953a4641469304265dfb --- /dev/null +++ b/app/controllers/terraform_registry_controller.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class TerraformRegistryController < ApplicationController + skip_before_action :authenticate_user! + + def index + render json: '{ "modules.v1":"/api/v4/terraform/modules/" }' + end +end diff --git a/app/presenters/terraform_presenter.rb b/app/presenters/terraform_presenter.rb new file mode 100644 index 0000000000000000000000000000000000000000..124298ec05b3b352fbabbb39cc366c899e5a08c9 --- /dev/null +++ b/app/presenters/terraform_presenter.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class TerraformPresenter < Gitlab::View::Presenter::Simple + attr_accessor :project, :tags, :provider + + presents :modules + + def initialize(project, tags, provider) + @project = project + @tags = tags + @provider = provider + end + + def modules + modules = [ + { + "source" => @project.web_url, + "versions" => [] + } + ] + @tags.each do |tag| + version = { + "version" => tag.name.delete_prefix("v"), + "submodules" => [], + "root" => { + "dependencies" => [], + "providers" => [ + { + "name" => @provider, + "version" => "" + } + ] + } + } + modules[0]['versions'].push(version) + end + + modules + end +end diff --git a/config/routes.rb b/config/routes.rb index b1ab4ec6baba9d05cbe3d53f45fec3d29bd22102..3c4db792822809bedfe79f69ace0e83b75e93eac 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -69,6 +69,9 @@ # Health check get 'health_check(/:checks)' => 'health_check#index', as: :health_check + # Terraform sevice discovery + get '.well-known/terraform.json' => 'terraform_registry#index' + # Begin of the /-/ scope. # Use this scope for all new global routes. scope path: '-' do diff --git a/lib/api/api.rb b/lib/api/api.rb index 2be6792af5f1034b42234111172b3222b4e22d34..b04d9b51ad8be92e5b1cbf4707627d5e46591ed5 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -231,6 +231,7 @@ class API < Grape::API::Instance mount ::API::SystemHooks mount ::API::Tags mount ::API::Templates + mount ::API::TerraformModules mount ::API::Todos mount ::API::Triggers mount ::API::UserCounts diff --git a/lib/api/entities/terraform_versions.rb b/lib/api/entities/terraform_versions.rb new file mode 100644 index 0000000000000000000000000000000000000000..1b34d1f59c2ad9ab5759316aede72148b248c751 --- /dev/null +++ b/lib/api/entities/terraform_versions.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module API + module Entities + class TerraformVersions < Grape::Entity + expose :modules + end + end +end diff --git a/lib/api/terraform_modules.rb b/lib/api/terraform_modules.rb new file mode 100644 index 0000000000000000000000000000000000000000..b99107120fedb3c137f202ff030201f2ae3b8a03 --- /dev/null +++ b/lib/api/terraform_modules.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module API + class TerraformModules < Grape::API + include RoutableActions + resource :terraform do + resource :modules do + namespace ":namespace/:name/:provider" do + get "versions" do + not_found! unless project + authorize!(:read_package, project) + + tags = ::TagsFinder.new(project.repository, sort: "name_desc").execute + presenter = TerraformPresenter.new(project, tags, params['provider']) + present presenter, with: Entities::TerraformVersions + end + + get ":tag/download", requirements: { tag: /.*/ } do + not_found! unless project + authorize!(:read_package, project) + + tag = project.repository.find_tag(params['tag']) + tag ||= project.repository.find_tag('v' + params['tag']) + not_found! unless tag + + header 'X-Terraform-Get', ActionDispatch::Http::URL.full_url_for(Rails.application.routes.default_url_options.merge(path: "/api/v4/projects/#{project.id}/repository/archive?archive=tar.gz&sha=#{tag.name}")) + status :no_content + end + end + end + end + + helpers do + include Gitlab::Utils::StrongMemoize + + def project + strong_memoize(:project) do + Project.find_by_full_path(CGI.unescape(params['namespace']) + "/terraform-" + params['provider'] + "-" + params['name']) + end + end + end + end +end