Project

General

Profile

Bug #11880

[BUG] updating multiple puppet-classes to hostgroup via hammer fails to update the hostgroup

Added by Marek Hulán over 5 years ago. Updated over 4 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
-
Target version:
-
Difficulty:
Triaged:
No
Bugzilla link:
Team Backlog:
Fixed in Releases:
Found in Releases:
In Kanboard:

Description

Cloned from https://bugzilla.redhat.com/show_bug.cgi?id=1264163
Description of problem:
updating multiple puppet-classes to hostgroup via hammer fails to update the hostgroup

Version-Release number of selected component (if applicable):

How reproducible:

Steps to Reproduce:
1. Create a hostgroup and try adding puppet classes to it via hammer.
2. As per hammer --help options, multiple classes can be uploaded using below option:
----
  1. hammer hostgroup update --help
    :
    :
    --puppet-classes PUPPET_CLASS_NAMES Comma separated list of values.
    ----
3. when trying to upload multiple classes using a comma to separate list:
----
  1. hammer hostgroup update --name "hostgroup1" --puppet-classes 'motd,apache'
    Could not update the hostgroup:
    Error: one of puppetclasses not found
    ----

4. When trying to upload multiple classes using a SPACE to separate list completes successfully but the hostgroup is not updated:
----
$ hammer hostgroup update"hostgroup1" --puppet-classes 'motd apache'
Hostgroup updated
----

Actual results:
The command fails if the list is separated with comma as mentioned in the hammer help.

And when list is separated using SPACE the message shows that it was successful. But the hostgroup is not updated:
----
$ hammer hostgroup info --name "hostgroup1"
Id: 1
Name: hostgroup1
Title: hostgroup1
Operating System:
Environment: KT_Default_Organization_Library_Testaladke_8
Model:
Subnet:
Domain:
Architecture:
Partition Table:
Medium:
Puppet CA Proxy Id:
Puppet Master Proxy Id:
ComputeProfile:
Puppetclasses:

Parameters:

Organizations:
Redhat
Parent Id:
----

Expected results:

The hostgroup should be updated with the puppet classes.

Additional info:

Using puppet ids separated using comma works:
---
  1. hammer hostgroup update --name "hostgroup1" --puppet-class-ids 2,1,7
    Hostgroup updated
    ---

Related issues

Has duplicate Hammer CLI - Bug #12444: Can not assign multiple puppet classes to a hostgroupDuplicate2015-11-11
Has duplicate Hammer CLI - Bug #13471: Error when updating puppet-classes for a single hostDuplicate2016-01-29

Associated revisions

Revision 85183fca (diff)
Added by Shimon Shtein almost 5 years ago

Fixes #11880 - Added special method for dealing with puppetclasses

Revision 2a6e8f70
Added by Martin Bacovsky almost 5 years ago

Merge pull request #219 from ShimShtein/11880

Fixes #11880 - Added special method for dealing with puppetclasses

History

#1 Updated by Marek Hulán over 5 years ago

Tested with latest hammer

$ hammer -v hostgroup update --name test_conflict --puppet-classes apache,stdlib
[ERROR 2015-09-18 09:01:42 Exception] Error: one of puppetclasses not found
Could not update the hostgroup:
  Error: one of puppetclasses not found
[ERROR 2015-09-18 09:01:42 Exception] 

HammerCLIForeman::ResolverError (one of puppetclasses not found):
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli_foreman-0.1.4/lib/hammer_cli_foreman/id_resolver.rb:149:in `find_resources'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli_foreman-0.1.4/lib/hammer_cli_foreman/id_resolver.rb:118:in `puppetclass_ids'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli_foreman-0.1.4/lib/hammer_cli_foreman/hostgroup.rb:34:in `puppet_class_ids'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli_foreman-0.1.4/lib/hammer_cli_foreman/hostgroup.rb:23:in `request_params'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli-0.3.0/lib/hammer_cli/apipie/command.rb:43:in `send_request'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli_foreman-0.1.4/lib/hammer_cli_foreman/commands.rb:179:in `send_request'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli-0.3.0/lib/hammer_cli/apipie/command.rb:34:in `execute'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/clamp-1.0.0/lib/clamp/command.rb:68:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli-0.3.0/lib/hammer_cli/abstract.rb:23:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/clamp-1.0.0/lib/clamp/subcommand/execution.rb:11:in `execute'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/clamp-1.0.0/lib/clamp/command.rb:68:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli-0.3.0/lib/hammer_cli/abstract.rb:23:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/clamp-1.0.0/lib/clamp/subcommand/execution.rb:11:in `execute'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/clamp-1.0.0/lib/clamp/command.rb:68:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli-0.3.0/lib/hammer_cli/abstract.rb:23:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/clamp-1.0.0/lib/clamp/command.rb:133:in `run'
    /home/ares/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/hammer_cli-0.3.0/bin/hammer:115:in `<top (required)>'
    /home/ares/.rbenv/versions/2.0.0-p247/bin/hammer:23:in `load'
    /home/ares/.rbenv/versions/2.0.0-p247/bin/hammer:23:in `<main>'

the searching on server side looks correct, so the issue is likely in resolving the answer on hammer side

2015-09-18T09:05:43 [app] [I] Started GET "/foreman/api/puppetclasses?search=name+%3D+%22apache%22+or+name+%3D+%22stdlib%22" for 127.0.0.1 at 2015-09-18 09:05:43 +0200
2015-09-18T09:05:43 [app] [I] Processing by Api::V2::PuppetclassesController#index as JSON
2015-09-18T09:05:43 [app] [I]   Parameters: {"search"=>"name = \"apache\" or name = \"stdlib\"", "apiv"=>"v2", "puppetclass"=>{}}
2015-09-18T09:05:43 [sql] [D]   User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."lower_login" = 'admin' LIMIT 1
2015-09-18T09:05:43 [sql] [D]   AuthSource Load (0.5ms)  SELECT "auth_sources".* FROM "auth_sources" WHERE "auth_sources"."id" = 1 LIMIT 1
2015-09-18T09:05:43 [sql] [D]   CACHE (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."lower_login" = 'admin' LIMIT 1
2015-09-18T09:05:43 [sql] [D] Authenticated user admin against INTERNAL authentication source
2015-09-18T09:05:43 [sql] [D]   User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."lower_login" = 'foreman_admin' LIMIT 1
2015-09-18T09:05:43 [app] [D] Setting current user thread-local variable to foreman_admin
2015-09-18T09:05:43 [app] [D] Setting current user thread-local variable to nil
2015-09-18T09:05:43 [sql] [D] Post-login processing for admin
2015-09-18T09:05:43 [sql] [D]   CACHE (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."lower_login" = 'foreman_admin' LIMIT 1
2015-09-18T09:05:43 [app] [D] Setting current user thread-local variable to foreman_admin
2015-09-18T09:05:43 [sql] [D]    (0.2ms)  BEGIN
2015-09-18T09:05:43 [sql] [D]    (0.4ms)  UPDATE "users" SET "last_login_on" = '2015-09-18 07:05:43.541394', "updated_at" = '2015-09-18 07:05:43.542609' WHERE "users"."id" = 1
2015-09-18T09:05:43 [sql] [D]   Role Load (0.3ms)  SELECT "roles".* FROM "roles" WHERE "roles"."name" = 'Anonymous' LIMIT 1
2015-09-18T09:05:43 [sql] [D]   SQL (0.5ms)  SELECT "roles".id FROM "roles" INNER JOIN "user_roles" ON "roles"."id" = "user_roles"."role_id" WHERE "user_roles"."owner_id" = 1 AND "user_roles"."owner_type" = 'User'
2015-09-18T09:05:43 [sql] [D]    (21.1ms)  COMMIT
2015-09-18T09:05:43 [sql] [D]   CACHE (0.0ms)  SELECT "roles".* FROM "roles" WHERE "roles"."name" = 'Anonymous' LIMIT 1
2015-09-18T09:05:43 [sql] [D]   Role Exists (0.5ms)  SELECT 1 AS one FROM "roles" INNER JOIN "user_roles" ON "roles"."id" = "user_roles"."role_id" WHERE "user_roles"."owner_id" = 1 AND "user_roles"."owner_type" = 'User' AND "roles"."id" = 8 LIMIT 1
2015-09-18T09:05:43 [app] [D] Setting current user thread-local variable to nil
2015-09-18T09:05:43 [app] [D] Setting current user thread-local variable to admin
2015-09-18T09:05:43 [sql] [D]   AuthSourceHidden Load (0.7ms)  SELECT "auth_sources".* FROM "auth_sources" WHERE "auth_sources"."type" IN ('AuthSourceHidden')
2015-09-18T09:05:43 [sql] [D]   User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."lower_login" = 'admin' AND (users.auth_source_id <> 7) ORDER BY firstname LIMIT 1
2015-09-18T09:05:43 [app] [I] Authorized user admin(Admin User)
2015-09-18T09:05:43 [app] [D] Setting current user thread-local variable to admin
2015-09-18T09:05:43 [sql] [D]   Location Load (0.5ms)  SELECT "taxonomies".* FROM "taxonomies" WHERE "taxonomies"."type" IN ('Location') AND "taxonomies"."id" IS NULL ORDER BY title LIMIT 1
2015-09-18T09:05:43 [app] [D] Setting current location thread-local variable to none
2015-09-18T09:05:43 [sql] [D]   Organization Load (0.4ms)  SELECT "taxonomies".* FROM "taxonomies" WHERE "taxonomies"."type" IN ('Organization') AND "taxonomies"."id" IS NULL ORDER BY title LIMIT 1
2015-09-18T09:05:43 [app] [D] Setting current organization thread-local variable to none
2015-09-18T09:05:43 [sql] [D]    (0.3ms)  SELECT COUNT(*) FROM "puppetclasses" 
2015-09-18T09:05:43 [sql] [D]    (0.4ms)  SELECT COUNT(*) FROM "puppetclasses" WHERE ((("puppetclasses"."name" = 'apache') OR ("puppetclasses"."name" = 'stdlib')))
2015-09-18T09:05:43 [sql] [D]   Puppetclass Load (0.5ms)  SELECT "puppetclasses".* FROM "puppetclasses" WHERE ((("puppetclasses"."name" = 'apache') OR ("puppetclasses"."name" = 'stdlib'))) ORDER BY puppetclasses.name LIMIT 20 OFFSET 0
2015-09-18T09:05:43 [app] [I]   Rendered api/v2/puppetclasses/index.json.rabl within api/v2/layouts/index_layout (0.9ms)
2015-09-18T09:05:43 [app] [D] Body: {
 |   "total": 211,
 |   "subtotal": 2,
 |   "page": 1,
 |   "per_page": 20,
 |   "search": "name = \"apache\" or name = \"stdlib\"",
 |   "sort": {
 |     "by": null,
 |     "order": null
 |   },
 |   "results": {"apache":[{"id":45,"name":"apache","created_at":"2013-04-04T14:24:03Z","updated_at":"2013-04-04T14:24:03Z"}],"stdlib":[{"id":102,"name":"stdlib","created_at":"2013-08-14T12:52:23Z","updated_at":"2013-08-14T12:52:23Z"}]}
 | }
 | 
2015-09-18T09:05:43 [app] [I] Completed 200 OK in 67.4ms (Views: 4.6ms | ActiveRecord: 27.9ms)

#2 Updated by Dominic Cleal about 5 years ago

  • Has duplicate Bug #12444: Can not assign multiple puppet classes to a hostgroup added

#3 Updated by Dominic Cleal almost 5 years ago

  • Has duplicate Bug #13471: Error when updating puppet-classes for a single host added

#4 Updated by The Foreman Bot almost 5 years ago

  • Status changed from New to Ready For Testing
  • Assignee set to Shimon Shtein
  • Pull request https://github.com/theforeman/hammer-cli-foreman/pull/219 added

#5 Updated by Shimon Shtein almost 5 years ago

  • Status changed from Ready For Testing to Closed
  • % Done changed from 0 to 100

#6 Updated by Iain Walmsley almost 5 years ago

Still having issues with this having depsite having manually implemented your change, when applying to a single host;

hammer host update --name=62c89bdc2b97.adidom.com --puppet-classes 'profile::compliance,profile::ansible'
Could not update the host:
Error: one of puppetclasses not found

Same with hostgroups etc.

I had two issues, firstly the count of the hash array resolves incorrectly to 1 all of the time;

Results is being seen as (in find_puppetclasses(options));

{"profile"=>[{"id"=>175, "name"=>"profile::compliance", "created_at"=>"2016-04-16T02:52:42.000Z", "updated_at"=>"2016-04-18T09:17:24.000Z"}, {"id"=>110, "name"=>"profile::tsoreboot", "created_at"=>"2016-04-16T02:52:41.000Z", "updated_at"=>"2016-04-18T09:17:43.000Z"}]}

But results.count still resolves to 1

results.count => 1, which is why it complains about having not found one of the puppetclasses.

Additionally in puppetclass_ids, it only grabs the first class, which means multiple classes still won't get pulled;

options[HammerCLI.option_accessor_name("ids")] || find_puppetclasses(options).values.collect { |c| c.first['id'] }

I've written a really hacky fix which seems to work, and can do a pull request, but someone should probably clean it up first;

def puppetclass_ids(options)
for i in find_puppetclasses(options).values
class_ids = i.collect { |c| c['id'] }
end
class_ids
end

def find_puppetclasses(options)
resource_name = :puppetclasses
resource = @api.resource(resource_name)
results = resolved_call(resource_name, :index, options).first
for i in results.values
results_arr = i.collect { |c| c['id'] }
end
raise ResolverError.new(_("one of %s not found") % resource.name, resource) if results_arr.count < expected_record_count(options, resource)
results
end

#7 Updated by Shimon Shtein over 4 years ago

Created new issue based on your response. Nice catch!
See http://projects.theforeman.org/issues/14930

Also available in: Atom PDF