Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cloud types to authentication options #13951

Merged
merged 5 commits into from
Mar 16, 2017
Merged

Add cloud types to authentication options #13951

merged 5 commits into from
Mar 16, 2017

Conversation

jntullo
Copy link

@jntullo jntullo commented Feb 16, 2017

The UI needs a way to populate a dropdown menu with the different ansible cloud credential type names and know the subclass to filter on for those credentials:

Sample output: (not all included - because it's long)

"data":{  
   "credential_types":{  
      "external_ansible_credentials":{  
         "ManageIQ::Providers::AnsibleTower::AutomationManager::AmazonCredential":{  
            "type":"cloud",
            "label":"Amazon",
            "attributes":{  
               "userid":{  
                  "label":"Access Key",
                  "help_text":"AWS Access Key for this credential"
               },
               "password":{  
                  "type":"password",
                  "label":"Secret Key",
                  "help_text":"AWS Secret Key for this credential"
               },
               "security_token":{  
                  "type":"password",
                  "label":"STS Token",
                  "help_text":"Security Token Service(STS) Token for this credential",
                  "max_length":1024
               }
            }
         }
      },
      "embedded_ansible_credentials":{  
         "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ScmCredential":{  
            "label":"Scm",
            "type":"scm",
            "attributes":{  
               "userid":{  
                  "label":"Access Key",
                  "help_text":"AWS Access Key for this credential"
               },
               "password":{  
                  "type":"password",
                  "label":"Secret Key",
                  "help_text":"AWS Secret Key for this credential"
               },
               "ssh_key_unlock":{  
                  "type":"password",
                  "label":"Private key passphrase",
                  "help_text":"Passphrase to unlock SSH private key if encrypted",
                  "max_length":1024
               },
               "ssh_key_data":{  
                  "type":"password",
                  "label":"Private key",
                  "help_text":"RSA or DSA private key to be used instead of password"
               }
            }
         },
         "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::AmazonCredential":{  
            "type":"cloud",
            "label":"Amazon",
            "attributes":{  
               "userid":{  
                  "label":"Access Key",
                  "help_text":"AWS Access Key for this credential"
               },
               "password":{  
                  "type":"password",
                  "label":"Secret Key",
                  "help_text":"AWS Secret Key for this credential"
               },
               "security_token":{  
                  "type":"password",
                  "label":"STS Token",
                  "help_text":"Security Token Service(STS) Token for this credential",
                  "max_length":1024
               }
            }
         },
         "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::VmwareCredential":{  
            "label":"VMware",
            "type":"cloud",
            "attributes":{  
               "userid":{  
                  "label":"Username",
                  "help_text":"Username for this credential"
               },
               "password":{  
                  "type":"password",
                  "label":"Password",
                  "help_text":"Password for this credential"
               },
               "host":{  
                  "type":"string",
                  "label":"vCenter Host",
                  "help_text":"The hostname or IP address of the vCenter Host",
                  "max_length":1024
               }
            }
         }
      }
   }

@miq-bot add_label api, enhancement, euwe/no
@miq-bot assign @abellotti

cc: @h-kataria @bdunne


def build_additional_fields
{
:cloud_types => ManageIQ::Providers::AnsibleTower::AutomationManager::CloudCredential.credential_types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they looked sorted, but that may not always be guaranteed. can you add a sort here or in the credential_types method itself (otherwise, you'd need the sort in the rspec too).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 looks like the underlying method now does the sort, so we're good.

attributes = (Authentication.attribute_names - Authentication.virtual_attribute_names).sort.as_json
attributes.delete('password')
reflections = (Authentication.reflections.keys | Authentication.virtual_reflections.keys.collect(&:to_s)).sort
subcollections = Array(Api::ApiConfig.collections[:authentications].subcollections).collect(&:to_s).sort
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the above four are now repeated (short of class name) in arbitration_rule_spec.rb, querying_spec.rb, and not authentications. Can you create a helper that returns the four (attributes, virtual_attributes, relationships, subcollections) in a hash for a given class and use that helper ? Thanks.

@@ -1,2 +1,10 @@
class ManageIQ::Providers::AnsibleTower::AutomationManager::CloudCredential < ManageIQ::Providers::AutomationManager::Authentication
def self.credential_types
credential_types = {}
subclasses.each do |subclass|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use subclasses.each_with_object({}) do |subclass, credential_types|

provider_name = subclass.name.demodulize.split('Credential').first
credential_types[provider_name] = subclass.name
end
credential_types.sort.to_h
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be sorted?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If sorting is important, it would be more efficient to sort before creating the hash.

subclasses.sort_by(&:name).each_with_object.....

@@ -1,2 +1,10 @@
class ManageIQ::Providers::AnsibleTower::AutomationManager::CloudCredential < ManageIQ::Providers::AutomationManager::Authentication
def self.credential_types
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be defined on the base class?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bdunne we're only worried about cloud credentials here

@miq-bot
Copy link
Member

miq-bot commented Feb 16, 2017

This pull request is not mergeable. Please rebase and repush.

'virtual_attributes' => Authentication.virtual_attribute_names.sort.as_json,
'relationships' => reflections,
'subcollections' => subcollections,
'data' => {}.merge!(data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this just be 'data' => data ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂 yes

@abellotti
Copy link
Member

@jntullo I'm good with this PR. there are 3 specs, clusters_spec.rb, hosts_spec.rb and querying_spec.rb that could use the new expect_options_results and remove some duplication, we can do this here or in another PR if you prefer. up to you. Thanks.

@jntullo
Copy link
Author

jntullo commented Feb 16, 2017

@abellotti I'll create another PR for that 👍

@abellotti
Copy link
Member

@bdunne ok by you ?

@Fryguy
Copy link
Member

Fryguy commented Feb 16, 2017

Does this mean a "toplevel" credential will be named "Amazon", or is that only the display name.

Can you show here what the result of the OPTIONS call is (might help me understand better)

@jntullo
Copy link
Author

jntullo commented Feb 16, 2017

@Fryguy only the display name. The response from OPTIONS is:

{
"attributes" => [<authentication attributes>],
"virtual_attributes" => [...],
"relationships" => [...],
"subcollections" => []
"data"=>
  {"cloud_types"=>
    {"Amazon"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::AmazonCredential",
     "Azure"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::AzureCredential",
     "Google"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::GoogleCredential",
     "Openstack"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::OpenstackCredential",
     "Rackspace"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::RackspaceCredential",
     "Satellite6"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::Satellite6Credential",
     "Vmware"=>"ManageIQ::Providers::AnsibleTower::AutomationManager::VmwareCredential"}}
}

@@ -1,2 +1,8 @@
class ManageIQ::Providers::AnsibleTower::AutomationManager::CloudCredential < ManageIQ::Providers::AnsibleTower::AutomationManager::Credential
def self.credential_types
subclasses.sort_by(&:name).each_with_object({}) do |subclass, credential_types|
provider_name = subclass.name.demodulize.split('Credential').first
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a display_name class method on each subclass?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Fryguy
Copy link
Member

Fryguy commented Feb 16, 2017

Ah, now I see...so, to me, this feels off a bit, and also may cause issues with when we need to have the extra attributes in the OPTIONS (see #13826).

cloud_types is too high level, and precludes including credentials for Cloud Managers in the future (say, Amazon Key Pair types), because the "cloud" name is taken. I'm thinking this should be related to the class nesting somehow, My initial thought is something like:

{
  "automation_manager/cloud" => { # Not sold on this naming or nesting with strings versus proper Hash nesting, but just illustrating
    "ManageIQ::Providers::AnsibleTower::AutomationManager::AmazonCredential" => {
      "display_name" => "Amazon",
      "extra_attributes" => [
        {
          "type" => "password",
          "display_name" => "STS Token",
          "description" => "For the tooltip"
        }
      ]
    }
  }
}

@Fryguy
Copy link
Member

Fryguy commented Feb 16, 2017

Re: "automation_manager/cloud" @bdunne @blomquisg @jntullo Thoughts on better naming? I was trying to go with the class nesting, but it's kind of nasty.

@Fryguy
Copy link
Member

Fryguy commented Feb 16, 2017

Alternately, we don't nest by cloud/machine whatever and that just becomes a property....

{
  "automation_manager" => { # Not sold on this naming or nesting with strings versus proper Hash nesting, but just illustrating
    "ManageIQ::Providers::AnsibleTower::AutomationManager::AmazonCredential" => {
      "display_name" => "Amazon",
      "type" => "cloud",  # or group or something
      "extra_attributes" => [
        {
          "type" => "password",
          "display_name" => "STS Token",
          "description" => "For the tooltip"
        }
      ]
    }
  }
}

@jntullo
Copy link
Author

jntullo commented Feb 16, 2017

@Fryguy I like the automation_manager suggestion. All of that info then, display_name, type, extra_attributes can be returned from a class method - so #13826 can include that.

@Fryguy
Copy link
Member

Fryguy commented Feb 17, 2017

Agreed. cc @blomquisg re more data we might need on the OPTIONS call.

@Fryguy
Copy link
Member

Fryguy commented Feb 22, 2017

I'm thinking we may remove the concept of "extra_attributes" here and just have it be "attributes" or something, and would include both the "extra" stuff and the regular columns. See #13826 (comment)

@@ -23,4 +23,10 @@ module ManageIQ::Providers::AnsibleTower::Shared::AutomationManager::AmazonCrede
}.freeze

API_ATTRIBUTES = COMMON_ATTRIBUTES.merge(EXTRA_ATTRIBUTES).freeze

API_OPTIONS = {
'display_name' => 'Amazon',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use label for the individual fields in the credential as here. It will be of same usage as display_name. Do we want to unify them?

@jntullo jntullo reopened this Mar 9, 2017
@jntullo
Copy link
Author

jntullo commented Mar 13, 2017

ping @abellotti

@abellotti
Copy link
Member

Hi @jntullo nice detailed options returned.

One concern here is that we lost one level under data which precludes us from adding option data for a different aspect of the collection.

"data" : {
  "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::MachineCredential": {
    "label": "Machine",
    ...
  },
  "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ScmCredential": {
    "label": "Scm",
   ...
  },
  ...
}

maybe add something like credential_types as follows:

"data" : {
  "credential_types" : {
    "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::MachineCredential": {
      "label": "Machine",
      ...
    },
    "ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ScmCredential": {
      "label": "Scm",
     ... 
    },
  ...
  }
}


API_OPTIONS = {
:type => 'cloud',
:label => 'Amazon',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the 'Amazon' here (and the other labels too) needs to be inside N_():

N_('Amazon')

so that it gets into the translation catalog and can then be localized on the UI side (or whatever would
consume this info via API).

@@ -23,4 +23,10 @@ module ManageIQ::Providers::AnsibleTower::Shared::AutomationManager::AmazonCrede
}.freeze

API_ATTRIBUTES = COMMON_ATTRIBUTES.merge(EXTRA_ATTRIBUTES).freeze

API_OPTIONS = {
:type => N_('cloud'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think :type here doesn't need to be inside N_(). It's not going to be presented in the UI as a nice string, correct? Just the label should be enough here.

@abellotti
Copy link
Member

Thanks @jntullo for the added credential_types section. Why the additional sections in it ? ansible_tower_credentials, embedded_ansible_credentials, etc. it will be more work to just search by class name, plus it will add churn to this API options logic as more types are added.

@jntullo
Copy link
Author

jntullo commented Mar 15, 2017

@abellotti this was required by @h-kataria - she may be able to provide more information.

@h-kataria
Copy link
Contributor

@abellotti i need to show Cloud types only for Embedded Ansible class, without ansible_tower_credentials, embedded_ansible_credentials sections, i am not able to get only specific type to populate the drop down.

@abellotti
Copy link
Member

ok. @jntullo so the remaining concern is the possible future churn on that API code.

I see the code for build_ansible_tower_creds and build_embedded_ansible_creds similar other than the starting class. would it be possible to have the model provide us the following Hash:

{
  :ansible_tower_credential_types => ManangeIQ::Providers::AnsibleTower::AutomationManager::Credential,
  :embedded_ansible_credential_types => ManageIQ::Providers::EmbeddedAnsible::AutomationManager::Credential
}

or some variant, then the API simply go throw that Hash in build_additional_fields to generate dynamically. In future we could simply update that Hash in model and no API changes needed.

@miq-bot
Copy link
Member

miq-bot commented Mar 16, 2017

This pull request is not mergeable. Please rebase and repush.

@miq-bot
Copy link
Member

miq-bot commented Mar 16, 2017

Checked commits jntullo/manageiq@f45eea5~...2a74dc1 with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0
9 files checked, 0 offenses detected
Everything looks good. ⭐

@abellotti
Copy link
Member

Thanks @jntullo for the update. LGTM!! 👍

@abellotti abellotti merged commit 2cbb57b into ManageIQ:master Mar 16, 2017
@abellotti abellotti added this to the Sprint 57 Ending Mar 27, 2017 milestone Mar 16, 2017
@chrisarcand chrisarcand deleted the cloud_credential_options branch November 28, 2017 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants