theforeman/foreman

View on GitHub
app/controllers/api/v2/registration_controller.rb

Summary

Maintainability
A
2 hrs
Test Coverage
module Api
  module V2
    class RegistrationController < V2::BaseController
      include Api::Version2
      include Foreman::Controller::Registration
      include Foreman::Controller::Parameters::Registration

      rescue_from ActiveRecord::RecordNotFound do |error|
        logger.info "#{error.message} (#{error.class})"
        not_found(error.message)
      end

      rescue_from ActiveRecord::RecordInvalid do |error|
        render_error(error.message, status: :unprocessable_entity)
      end

      api :GET, '/register', N_('Render Global registration template')
      param :organization_id, :number, desc: N_("ID of the Organization to register the host in")
      param :location_id, :number, desc: N_("ID of the Location to register the host in")
      param :hostgroup_id, :number, desc: N_("ID of the Host group to register the host in")
      param :operatingsystem_id, :number, desc: N_("ID of the Operating System to register the host in")
      param :setup_insights, :bool, desc: N_("Set 'host_registration_insights' parameter for the host. If it is set to true, insights client will be installed and registered on Red Hat family operating systems")
      param :setup_remote_execution, :bool, desc: N_("Set 'host_registration_remote_execution' parameter for the host. If it is set to true, SSH keys will be installed on the host")
      param :packages, String, desc: N_("Packages to install on the host when registered. Can be set by `host_packages` parameter, example: `pkg1 pkg2`")
      param :update_packages, :bool, desc: N_("Update all packages on the host")
      param :repo, String, desc: N_("DEPRECATED, use the `repo_data` param instead."), deprecated: true
      param :repo_gpg_key_url, String, desc: N_("DEPRECATED, use the `repo_data` param instead."), deprecated: true

      param :repo_data, Array, desc: N_("Array with repository URL and corresponding GPG key URL") do
        param :repo, String, desc: N_("Repository URL / details, for example, for Debian OS family: 'deb http://deb.example.com/ buster 1.0', for Red Hat OS family: 'http://yum.theforeman.org/client/latest/el8/x86_64/'")
        param :repo_gpg_key_url, String, desc: N_("URL of the GPG key for the repository")
      end
      def global
        find_global_registration

        if params[:repo] || params[:repo_gpg_key_url]
          Foreman::Deprecation.api_deprecation_warning("Use repo_data parameter instead of repo and repo_gpg_key_url. These will be removed soon.")
        end

        unless @provisioning_template
          not_found _('Global Registration Template with name %s defined via default_global_registration_item Setting not found, please configure the existing template name first') % Setting[:default_global_registration_item]
          return
        end

        render plain: @provisioning_template.render(variables: @global_registration_vars).html_safe
      end

      api :POST, "/register", N_("Find or create a host and render the 'Host initial configuration' template")
      param :host, Hash, required: true, action_aware: true do
        param :name, String, required: true
        param :location_id, :number, required: true
        param :organization_id, :number, required: true
        param :ip, String, desc: N_("IPv4 address, not required if using a subnet with DHCP proxy")
        param :ip6, String, desc: N_("IPv6 address, not required if using a subnet with DHCP proxy")
        param :mac, String, desc: N_("required for managed host that is bare metal, not required if it's a virtual machine")
        param :domain_id, :number, desc: N_("required if host is managed and value is not inherited from host group")
        param :operatingsystem_id, :number, desc: N_("required if host is managed and value is not inherited from host group")
        param :subnet_id, :number, desc: N_("required if host is managed and value is not inherited from host group")
        param :model_id, :number
        param :hostgroup_id, :number
        param :host_parameters_attributes, Array, desc: N_("Host's parameters (array or indexed hash)") do
          param :name, String, desc: N_("Name of the parameter"), required: true
          param :value, String, desc: N_("Parameter value"), required: true
          param :parameter_type, Parameter::KEY_TYPES, desc: N_("Type of value")
          param :hidden_value, :bool
        end
        param :build, :bool
        param :enabled, :bool, desc: N_("Include this host within Foreman reporting")
        param :managed, :bool, desc: N_("True/False flag whether a host is managed or unmanaged. Note: this value also determines whether several parameters are required or not")
        param :comment, String, desc: N_("Additional information about this host")
        param :interfaces_attributes, Array, desc: N_("Host's network interfaces") do
          param_group :interface_attributes, ::Api::V2::InterfacesController
        end
        Facets.registered_facets.each_value do |facet_config|
          next unless facet_config.host_configuration.api_param_group && facet_config.host_configuration.api_controller
          param "#{facet_config.name}_attributes".to_sym, Hash, desc: facet_config.api_param_group_description || (N_("Parameters for host's %s facet") % facet_config.name) do
            facet_config.host_configuration.load_api_controller
            param_group facet_config.host_configuration.api_param_group, facet_config.host_configuration.api_controller
          end
        end
      end
      param :setup_insights, :bool, desc: N_("Set 'host_registration_insights' parameter for the host. If it is set to true, insights client will be installed and registered on Red Hat family operating systems")
      param :setup_remote_execution, :bool, desc: N_("Set 'host_registration_remote_execution' parameter for the host. If it is set to true, SSH keys will be installed on the host")
      def host
        begin
          ActiveRecord::Base.transaction do
            find_host
            prepare_host
            setup_host_params
            host_setup_extension
            @template = @host.initial_configuration_template
            raise ActiveRecord::Rollback if @template.nil?
          end
        rescue ::Foreman::Exception => e
          render_error(e.message, status: :unprocessable_entity)
          return
        end

        unless @template
          not_found N_("Unable to find 'Host initial configuration' template for host %{host} running %{os}, associate the 'Host initial configuration' template for this OS first") % { host: @host.name, os: @host.operatingsystem }
          return
        end

        # Do not rebuild managed hosts
        # Hosts registered with subscription-manager are created
        # as a Host::Managed, but have @host.managed? => false
        # https://projects.theforeman.org/issues/36393
        @host.setBuild unless @host.managed?
        safe_render(@template)
      end

      private

      def check_media_type
        return super if action_name != 'host'
        return if ["application/json", "application/x-www-form-urlencoded"].include?(request.media_type)

        render_error(:unsupported_media_type, status: :unsupported_media_type)
      end

      def find_host
        @host = Host.find_or_initialize_by(name: host_params('host')['name'])
      end

      def prepare_host
        host_attributes = @host.apply_inherited_attributes(host_params('host'))

        @host.assign_attributes(host_attributes)
        @host.owner = User.current
        @host.save!
      end

      # Extension point for plugins
      def host_setup_extension
      end
    end
  end
end