From 69336b8d72ca4b5591daaa540cce3cad8cc9a030 Mon Sep 17 00:00:00 2001
From: Erez Freiberger <efreiber@redhat.com>
Date: Tue, 4 Jul 2017 15:11:03 +0300
Subject: [PATCH] Add the ability to edit options settings for container
 providers

Reading the details about the provider's options from the api endpiont
/api/provider_options/<provider class> and creating tabs for them.
---
 .../ems_common/ems_common_form_controller.js  | 49 ++++++++++++++++++-
 app/controllers/mixins/ems_common_angular.rb  | 18 +++++++
 app/helpers/application_helper.rb             | 10 ++--
 .../_provider_advanced_settings.html.haml     | 26 ++++++++++
 .../_provider_proxy_settings.html.haml        | 23 +++++++++
 .../angular/_multi_auth_credentials.html.haml | 16 ++++++
 6 files changed, 136 insertions(+), 6 deletions(-)
 create mode 100644 app/views/layouts/angular-bootstrap/_provider_advanced_settings.html.haml
 create mode 100644 app/views/layouts/angular-bootstrap/_provider_proxy_settings.html.haml

diff --git a/app/assets/javascripts/controllers/ems_common/ems_common_form_controller.js b/app/assets/javascripts/controllers/ems_common/ems_common_form_controller.js
index 22a5fcc2df8b..6828298839ec 100644
--- a/app/assets/javascripts/controllers/ems_common/ems_common_form_controller.js
+++ b/app/assets/javascripts/controllers/ems_common/ems_common_form_controller.js
@@ -1,4 +1,45 @@
-ManageIQ.angular.app.controller('emsCommonFormController', ['$http', '$scope', '$attrs', 'emsCommonFormId', 'miqService', function($http, $scope, $attrs, emsCommonFormId, miqService) {
+ManageIQ.angular.app.controller('emsCommonFormController', ['$http', '$scope', '$attrs', 'emsCommonFormId', 'miqService', 'API', function($http, $scope, $attrs, emsCommonFormId, miqService, API) {
+  var getProviderOptionsDescription = function() {
+    API.get('/api/providers_options/' + $scope.emsCommonModel.emstype).then(function(response) {
+      $scope.emsCommonModel.provider_options_description = response;
+      if ($scope.emsCommonModel.provider_options_description.hasOwnProperty('advanced_settings')) {
+        var advanced_settings = $scope.emsCommonModel.provider_options_description.advanced_settings.settings
+        for (section in advanced_settings) {
+          if (advanced_settings.hasOwnProperty(section)){
+            $scope.emsCommonModel.advanced_settings = {}
+            updateProviderOptions($scope.emsCommonModel.advanced_settings, advanced_settings[section]);
+          }
+        }
+      }
+      if ($scope.emsCommonModel.provider_options_description.hasOwnProperty('proxy_settings')) {
+        $scope.emsCommonModel.proxy_settings = {}
+        updateProviderOptions($scope.emsCommonModel, $scope.emsCommonModel.provider_options_description.proxy_settings);
+      }
+    });
+  };
+
+  var updateProviderOptions = function(settings_group, options_section){
+    var section_name = $scope.toSnakeCase(options_section.label);
+    settings_group[section_name] = options_section;
+    settings_group[section_name].section_name = section_name;
+    var section = settings_group[section_name].settings;
+    for (option in section){
+      if (section.hasOwnProperty(option)) {
+        if ($scope.emsCommonModel.provider_options_values.hasOwnProperty(section_name) &&
+          $scope.emsCommonModel.provider_options_values[section_name].hasOwnProperty(option)){
+          section[option].value = $scope.emsCommonModel.provider_options_values[section_name][option];
+        } else {
+          section[option].value = "";
+        }
+        section[option].name = option;
+      }
+    }
+  };
+
+  $scope.toSnakeCase = function(st) {
+    return st.toLowerCase().split(' ').join('_');
+  };
+
   var init = function() {
     $scope.emsCommonModel = {
       name: '',
@@ -11,6 +52,8 @@ ManageIQ.angular.app.controller('emsCommonFormController', ['$http', '$scope', '
       default_hostname: '',
       amqp_hostname: '',
       hawkular_hostname: '',
+      provider_options_values: {},
+      provider_options_description: {},
       metrics_hostname: '',
       project: '',
       default_api_port: '',
@@ -100,6 +143,8 @@ ManageIQ.angular.app.controller('emsCommonFormController', ['$http', '$scope', '
       $scope.emsCommonModel.metrics_hostname                = data.metrics_hostname;
       $scope.emsCommonModel.project                         = data.project;
 
+      $scope.emsCommonModel.provider_options_values         = data.provider_options;
+
       $scope.emsCommonModel.openstack_infra_providers_exist = data.openstack_infra_providers_exist;
 
       $scope.emsCommonModel.provider_id                     = data.provider_id !== undefined ? data.provider_id.toString() : "";
@@ -171,6 +216,7 @@ ManageIQ.angular.app.controller('emsCommonFormController', ['$http', '$scope', '
       $scope.populatePostValidationModel();
 
       miqService.sparkleOff();
+      getProviderOptionsDescription();
     }
 
     function getNewEmsFormDataComplete(response) {
@@ -347,6 +393,7 @@ ManageIQ.angular.app.controller('emsCommonFormController', ['$http', '$scope', '
   };
 
   $scope.providerTypeChanged = function() {
+    getProviderOptionsDescription();
     if ($scope.emsCommonModel.ems_controller === 'ems_container') {
       $scope.emsCommonModel.default_api_port = "8443"; // TODO: correct per-type port
       $scope.emsCommonModel.metrics_selection = "hawkular_".concat($scope.emsCommonModel.metrics_selection_default);
diff --git a/app/controllers/mixins/ems_common_angular.rb b/app/controllers/mixins/ems_common_angular.rb
index c959b627d9a3..aa7784c0eda9 100644
--- a/app/controllers/mixins/ems_common_angular.rb
+++ b/app/controllers/mixins/ems_common_angular.rb
@@ -141,6 +141,8 @@ def ems_form_fields
       hawkular_security_protocol = security_protocol_default
       hawkular_tls_ca_certs = ""
 
+      provider_options = @ems.options || {}
+
       if @ems.connection_configurations.amqp.try(:endpoint)
         amqp_hostname = @ems.connection_configurations.amqp.endpoint.hostname
         amqp_port = @ems.connection_configurations.amqp.endpoint.port
@@ -295,6 +297,7 @@ def ems_form_fields
                        :ems_controller             => controller_name,
                        :default_auth_status        => default_auth_status,
                        :hawkular_auth_status       => hawkular_auth_status,
+                       :provider_options           => provider_options,
       } if controller_name == "ems_container"
 
       if controller_name == "ems_middleware"
@@ -437,6 +440,21 @@ def set_ems_record_vars(ems, mode = nil)
           hawkular_endpoint = {:role => :hawkular, :hostname => hawkular_hostname, :port => hawkular_api_port}
           hawkular_endpoint.merge!(endpoint_security_options(hawkular_security_protocol, hawkular_tls_ca_certs))
         end
+
+        new_options = {}
+        ems.class.advanced_settings.each do |section_name, section|
+          section[:settings].each do |opt, _|
+            new_options[section_name.to_sym] ||= {}
+            value = params["provider_options_#{section_name}_#{opt}".to_sym]
+            new_options[section_name.to_sym][opt.to_sym] = value if value.present?
+          end
+        end
+        new_options[:proxy_settings] = {}
+        ems.class.proxy_settings.each do |opt, _|
+          value = params["provider_options_proxy_settings_#{opt}".to_sym]
+          new_options[:proxy_settings][opt] = value if value.present?
+        end
+        ems.options = new_options
       end
 
       if ems.kind_of?(ManageIQ::Providers::MiddlewareManager)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7695b8aa9039..6b0519dea8ea 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1511,10 +1511,7 @@ def title_for_cluster_record(record)
 
   def miq_tab_header(id, active = nil, options = {}, &_block)
     tag_options = {:class => "#{options[:class]} #{active == id ? 'active' : ''}",
-                   :id    => "#{id}_tab"}
-
-    tag_options['ng-click'] = options['ng-click'] if options.key?('ng-click')
-    tag_options[:onclick] = options[:onclick] if options.key?(:onclick)
+                   :id    => "#{id}_tab"}.merge!(options)
 
     content_tag(:li, tag_options) do
       content_tag(:a, :href => "##{id}", 'data-toggle' => 'tab') do
@@ -1531,7 +1528,10 @@ def miq_tab_content(id, active = nil, options = {}, &_block)
     classname << 'active' if active == id
     classname << 'lazy' if lazy
 
-    content_tag(:div, :id => id, :class => classname.join(' ')) do
+    options.delete(:lazy)
+    options.delete(:class)
+
+    content_tag(:div, :id => id, :class => classname.join(' '), **options) do
       yield unless lazy
     end
   end
diff --git a/app/views/layouts/angular-bootstrap/_provider_advanced_settings.html.haml b/app/views/layouts/angular-bootstrap/_provider_advanced_settings.html.haml
new file mode 100644
index 000000000000..b2739825a19b
--- /dev/null
+++ b/app/views/layouts/angular-bootstrap/_provider_advanced_settings.html.haml
@@ -0,0 +1,26 @@
+%h3
+  {{ emsCommonModel.provider_options_description.advanced_settings.label }}
+%p
+  {{ emsCommonModel.provider_options_description.advanced_settings.help_text }}
+%div{"ng-repeat" => "settings_section in emsCommonModel.advanced_settings"}
+  %h4
+    {{ settings_section.label }}
+  %p
+    {{ settings_section.help_text }}
+  %div{"ng-repeat" => "option in settings_section.settings"}
+    %div{"ng-show" => "true"}
+      .form-group{"ng-attr-ng-class" => "{{ \"{'has_error': angularForm.provider_options_\" + settings_section.section_name + \"_\" + option.name + \".$invalid}\" }}"}
+        %label.col-md-2.control-label{"ng-attr-for" => "{{ \"provider_options_\" + settings_section.section_name + \"_\" + option.name }}"}
+          {{ option.label }}
+        .col-md-4
+          %input.form-control{"type"          => "text",
+                              "ng-attr-id"    => "{{ \"provider_options_\" + settings_section.section_name + \"_\" + option.name }}",
+                              "ng-attr-name"  => "{{ \"provider_options_\" + settings_section.section_name + \"_\" + option.name }}",
+                              "ng-model"      => "option.value",
+                              "checkchange"   => "",
+                              "ng-trim"       => false,
+                              "detect_spaces" => "",
+                              "placeholder"   => "{{ option.global_default }}",
+                              "prefix"        => "provider_options"}
+          %span.help-block{"ng-attr-ng-show" => "{{ \"angularForm.provider_options_\" + settings_section.section_name + \"_\" + option.name + \".$error.detectedSpaces\" }}"}
+            = _("Spaces are prohibited")
diff --git a/app/views/layouts/angular-bootstrap/_provider_proxy_settings.html.haml b/app/views/layouts/angular-bootstrap/_provider_proxy_settings.html.haml
new file mode 100644
index 000000000000..5a0c9a598ce7
--- /dev/null
+++ b/app/views/layouts/angular-bootstrap/_provider_proxy_settings.html.haml
@@ -0,0 +1,23 @@
+- prefix                 ||= 'provider_options'
+
+%h4
+  {{ emsCommonModel.provider_options_description.proxy_settings.label }}
+%p
+  {{ emsCommonModel.provider_options_description.proxy_settings.help_text }}
+%div{"ng-repeat" => "option in emsCommonModel.proxy_settings.settings"}
+  %div{"ng-show" => "true"}
+    .form-group{"ng-attr-ng-class" => "{{ \"{'has_error': angularForm.provider_options_proxy_settings_\" + option.name + \".$invalid}\" }}"}
+      %label.col-md-2.control-label{"ng-attr-for" => "{{ \"provider_options_proxy_settings_\" + option.name }}"}
+        {{ option.label }}
+      .col-md-4
+        %input.form-control{"type"                => "text",
+                            "ng-attr-id"          => "{{ \"provider_options_proxy_settings_\" + option.name }}",
+                            "ng-attr-name"        => "{{ \"provider_options_proxy_settings_\" + option.name }}",
+                            "ng-model"            => "option.value",
+                            "checkchange"         => "",
+                            "ng-trim"             => false,
+                            "detect_spaces"       => "",
+                            "placeholder"         => "{{ option.global_default }}",
+                            "prefix"              => "#{prefix}"}
+        %span.help-block{"ng-attr-ng-show" => "{{ \"angularForm.provider_options_proxy_settings_\" + option.name + \".$error.detectedSpaces\" }}"}
+          = _("Spaces are prohibited")
diff --git a/app/views/layouts/angular/_multi_auth_credentials.html.haml b/app/views/layouts/angular/_multi_auth_credentials.html.haml
index a0019230b094..2f05af3b7f84 100644
--- a/app/views/layouts/angular/_multi_auth_credentials.html.haml
+++ b/app/views/layouts/angular/_multi_auth_credentials.html.haml
@@ -31,8 +31,24 @@
         = _("Web Services")
       = miq_tab_header('ipmi', nil, {'ng-click' => "changeAuthTab('ipmi')"}) do
         = _("IPMI")
+    = miq_tab_header('proxy_settings', nil, {'ng-click' => "changeAuthTab('proxy_settings')",
+                                             'ng-if'    => "#{ng_model}.provider_options_description.hasOwnProperty('proxy_settings')"}) do
+      %i{"error-on-tab" => "hawkular", :style => "color:#cc0000"}
+      = _("Proxy Settings")
+    = miq_tab_header('advanced_settings', nil, {'ng-click' => "changeAuthTab('advanced_settings')",
+                                                'ng-if'    => "#{ng_model}.provider_options_description.hasOwnProperty('advanced_settings')"}) do
+      %i{"error-on-tab" => "hawkular", :style => "color:#cc0000"}
+      = _("Advanced Settings")
 
   .tab-content
+    = miq_tab_content('proxy_settings', 'default', "ng-if".to_sym => "#{ng_model}.provider_options_description.hasOwnProperty('proxy_settings')") do
+      .form-group
+        .col-md-12.col-md-12
+          = render :partial => "layouts/angular-bootstrap/provider_proxy_settings"
+    = miq_tab_content('advanced_settings', 'default', "ng-if".to_sym => "#{ng_model}.provider_options_description.hasOwnProperty('advanced_settings')") do
+      .form-group
+        .col-md-12.col-md-12
+          = render :partial => "layouts/angular-bootstrap/provider_advanced_settings"
     = miq_tab_content('default', 'default') do
       .form-group
         .col-md-12{"ng-if" => "#{ng_model}.ems_controller == 'ems_container' || " +  |