{"action":"created","comment":{"url":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments/210095805","pull_request_review_id":146242237,"id":210095805,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMDA5NTgwNQ==","diff_hunk":"@@ -0,0 +1,390 @@\n+# Common code for AIX user/group providers.\n+class Puppet::Provider::AixObject < Puppet::Provider\n+  desc \"Generic AIX resource provider\"\n+\n+  # Class representing a MappedObject, which can either be an\n+  # AIX attribute or a Puppet property. This class lets us\n+  # write something like:\n+  #\n+  #   self.class.mappings[:aix_attribute][:uid].name\n+  #   self.class.mappings[:aix_attribute][:uid].convert_property_value(value)\n+  #\n+  #   self.class.mappings[:puppet_property][:id].name\n+  #   self.class.mappings[:puppet_property][:id].convert_attribute_value(value)\n+  #\n+  class MappedObject\n+    attr_reader :name\n+\n+    def initialize(name, conversion_fn, conversion_fn_code)\n+      @name = name\n+\n+      define_singleton_method(conversion_fn) do |value|\n+        conversion_fn_code.call(value)\n+      end\n+    end\n+  end\n+\n+  class << self\n+    #-------------\n+    # Mappings\n+    # ------------\n+\n+    def mappings\n+      return @mappings if @mappings\n+\n+      @mappings = {}\n+      @mappings[:aix_attribute] = {}\n+      @mappings[:puppet_property] = {}\n+\n+      @mappings\n+    end\n+\n+    # Add a mapping from a Puppet property to an AIX attribute. The mapping_info must include:\n+    #\n+    #   * :puppet_property       -- The puppet property corresponding to this attribute\n+    #   * :aix_attribute         -- The AIX attribute corresponding to this attribute. Defaults\n+    #                            to puppet_property if this is not provided.\n+    #   * :property_to_attribute -- A lambda that converts a Puppet Property to an AIX attribute\n+    #                            value. Defaults to the identity function if not provided.\n+    #   * :attribute_to_property -- A lambda that converts an AIX attribute to a Puppet property.\n+    #                            Defaults to the identity function if not provided.\n+    def mapping(mapping_info = {})\n+      identity_fn = lambda { |x| x }\n+      mapping_info[:aix_attribute] ||= mapping_info[:puppet_property]\n+      mapping_info[:property_to_attribute] ||= identity_fn\n+      mapping_info[:attribute_to_property] ||= identity_fn\n+\n+      mappings[:aix_attribute][mapping_info[:puppet_property]] = MappedObject.new(\n+        mapping_info[:aix_attribute],\n+        :convert_property_value,\n+        mapping_info[:property_to_attribute]\n+      )\n+      mappings[:puppet_property][mapping_info[:aix_attribute]] = MappedObject.new(\n+        mapping_info[:puppet_property],\n+        :convert_attribute_value,\n+        mapping_info[:attribute_to_property]\n+      )\n+    end\n+\n+    # Creates a mapping from a purely numeric Puppet property to\n+    # an attribute\n+    def numeric_mapping(mapping_info = {})\n+      property = mapping_info[:puppet_property]\n+\n+      # We have this validation here b/c not all numeric properties\n+      # handle this at the property level (e.g. like the UID). Given\n+      # that, we might as well go ahead and do this validation for all\n+      # of our numeric properties. Doesn't hurt.\n+      mapping_info[:property_to_attribute] = lambda do |value|\n+        unless value.is_a?(Integer)\n+          raise ArgumentError, _(\"Invalid value #{value}: #{property} must be an Integer!\")\n+        end\n+\n+        value.to_s\n+      end\n+\n+      # AIX will do the right validation to ensure numeric attributes\n+      # can't be set to non-numeric values, so no need for the extra clutter.\n+      mapping_info[:attribute_to_property] = lambda { |x| x.to_i }\n+\n+      mapping(mapping_info)\n+    end\n+\n+    #-------------\n+    # Useful Class Methods\n+    # ------------\n+\n+    # Defines the getter and setter methods for each Puppet property that's mapped\n+    # to an AIX attribute. We define only a getter for the :attributes property.\n+    #\n+    # Provider subclasses should call this method after they've defined all of\n+    # their <puppet_property> => <aix_attribute> mappings.\n+    def mk_resource_methods\n+      # Define the Getter methods for each of our properties + the attributes\n+      # property\n+      properties = [:attributes]\n+      properties += mappings[:aix_attribute].keys","path":"lib/puppet/provider/aix_object.rb","position":140,"original_position":106,"commit_id":"cd3c46000135b02e4bd5539218ea98614066fa96","original_commit_id":"153f829ccca083beb40928c38900c0aae8002987","user":{"login":"smcclellan","id":6577757,"node_id":"MDQ6VXNlcjY1Nzc3NTc=","avatar_url":"https://avatars1.githubusercontent.com/u/6577757?v=4","gravatar_id":"","url":"https://api.github.com/users/smcclellan","html_url":"https://github.com/smcclellan","followers_url":"https://api.github.com/users/smcclellan/followers","following_url":"https://api.github.com/users/smcclellan/following{/other_user}","gists_url":"https://api.github.com/users/smcclellan/gists{/gist_id}","starred_url":"https://api.github.com/users/smcclellan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smcclellan/subscriptions","organizations_url":"https://api.github.com/users/smcclellan/orgs","repos_url":"https://api.github.com/users/smcclellan/repos","events_url":"https://api.github.com/users/smcclellan/events{/privacy}","received_events_url":"https://api.github.com/users/smcclellan/received_events","type":"User","site_admin":false},"body":"In other words, could any of this code move up into `Puppet::Provider`?","created_at":"2018-08-14T20:39:51Z","updated_at":"2018-08-14T20:39:52Z","html_url":"https://github.com/puppetlabs/puppet/pull/6987#discussion_r210095805","pull_request_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments/210095805"},"html":{"href":"https://github.com/puppetlabs/puppet/pull/6987#discussion_r210095805"},"pull_request":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987"}},"in_reply_to_id":209402892},"pull_request":{"url":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987","id":207597205,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA3NTk3MjA1","html_url":"https://github.com/puppetlabs/puppet/pull/6987","diff_url":"https://github.com/puppetlabs/puppet/pull/6987.diff","patch_url":"https://github.com/puppetlabs/puppet/pull/6987.patch","issue_url":"https://api.github.com/repos/puppetlabs/puppet/issues/6987","number":6987,"state":"open","locked":false,"title":"(PUP-9049)(PUP-3021) Refactor AIX user/group providers + fix KeyValue property","user":{"login":"ekinanp","id":29735501,"node_id":"MDQ6VXNlcjI5NzM1NTAx","avatar_url":"https://avatars1.githubusercontent.com/u/29735501?v=4","gravatar_id":"","url":"https://api.github.com/users/ekinanp","html_url":"https://github.com/ekinanp","followers_url":"https://api.github.com/users/ekinanp/followers","following_url":"https://api.github.com/users/ekinanp/following{/other_user}","gists_url":"https://api.github.com/users/ekinanp/gists{/gist_id}","starred_url":"https://api.github.com/users/ekinanp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ekinanp/subscriptions","organizations_url":"https://api.github.com/users/ekinanp/orgs","repos_url":"https://api.github.com/users/ekinanp/repos","events_url":"https://api.github.com/users/ekinanp/events{/privacy}","received_events_url":"https://api.github.com/users/ekinanp/received_events","type":"User","site_admin":false},"body":"The AIX user/group provider code was messy, hard to reason about, buggy, and not very idiomatic. This PR refactors them to be easier to understand. The Key/Value property also had some bugs that needed to be fixed.\r\n\r\nThis PR resolves the following tickets:\r\n\r\n* PUP-9049\r\n* PUP-3021\r\n* PUP-7241\r\n* PUP-7533\r\n* PUP-7604","created_at":"2018-08-10T12:28:09Z","updated_at":"2018-08-14T20:39:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cf3a6976d3b5953c0ff31cf48efbd9fd47531cc9","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987/commits","review_comments_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987/comments","review_comment_url":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments{/number}","comments_url":"https://api.github.com/repos/puppetlabs/puppet/issues/6987/comments","statuses_url":"https://api.github.com/repos/puppetlabs/puppet/statuses/cd3c46000135b02e4bd5539218ea98614066fa96","head":{"label":"ekinanp:PUP-9049","ref":"PUP-9049","sha":"cd3c46000135b02e4bd5539218ea98614066fa96","user":{"login":"ekinanp","id":29735501,"node_id":"MDQ6VXNlcjI5NzM1NTAx","avatar_url":"https://avatars1.githubusercontent.com/u/29735501?v=4","gravatar_id":"","url":"https://api.github.com/users/ekinanp","html_url":"https://github.com/ekinanp","followers_url":"https://api.github.com/users/ekinanp/followers","following_url":"https://api.github.com/users/ekinanp/following{/other_user}","gists_url":"https://api.github.com/users/ekinanp/gists{/gist_id}","starred_url":"https://api.github.com/users/ekinanp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ekinanp/subscriptions","organizations_url":"https://api.github.com/users/ekinanp/orgs","repos_url":"https://api.github.com/users/ekinanp/repos","events_url":"https://api.github.com/users/ekinanp/events{/privacy}","received_events_url":"https://api.github.com/users/ekinanp/received_events","type":"User","site_admin":false},"repo":{"id":108305884,"node_id":"MDEwOlJlcG9zaXRvcnkxMDgzMDU4ODQ=","name":"puppet","full_name":"ekinanp/puppet","owner":{"login":"ekinanp","id":29735501,"node_id":"MDQ6VXNlcjI5NzM1NTAx","avatar_url":"https://avatars1.githubusercontent.com/u/29735501?v=4","gravatar_id":"","url":"https://api.github.com/users/ekinanp","html_url":"https://github.com/ekinanp","followers_url":"https://api.github.com/users/ekinanp/followers","following_url":"https://api.github.com/users/ekinanp/following{/other_user}","gists_url":"https://api.github.com/users/ekinanp/gists{/gist_id}","starred_url":"https://api.github.com/users/ekinanp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ekinanp/subscriptions","organizations_url":"https://api.github.com/users/ekinanp/orgs","repos_url":"https://api.github.com/users/ekinanp/repos","events_url":"https://api.github.com/users/ekinanp/events{/privacy}","received_events_url":"https://api.github.com/users/ekinanp/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ekinanp/puppet","description":"Server automation framework and application","fork":true,"url":"https://api.github.com/repos/ekinanp/puppet","forks_url":"https://api.github.com/repos/ekinanp/puppet/forks","keys_url":"https://api.github.com/repos/ekinanp/puppet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ekinanp/puppet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ekinanp/puppet/teams","hooks_url":"https://api.github.com/repos/ekinanp/puppet/hooks","issue_events_url":"https://api.github.com/repos/ekinanp/puppet/issues/events{/number}","events_url":"https://api.github.com/repos/ekinanp/puppet/events","assignees_url":"https://api.github.com/repos/ekinanp/puppet/assignees{/user}","branches_url":"https://api.github.com/repos/ekinanp/puppet/branches{/branch}","tags_url":"https://api.github.com/repos/ekinanp/puppet/tags","blobs_url":"https://api.github.com/repos/ekinanp/puppet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ekinanp/puppet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ekinanp/puppet/git/refs{/sha}","trees_url":"https://api.github.com/repos/ekinanp/puppet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ekinanp/puppet/statuses/{sha}","languages_url":"https://api.github.com/repos/ekinanp/puppet/languages","stargazers_url":"https://api.github.com/repos/ekinanp/puppet/stargazers","contributors_url":"https://api.github.com/repos/ekinanp/puppet/contributors","subscribers_url":"https://api.github.com/repos/ekinanp/puppet/subscribers","subscription_url":"https://api.github.com/repos/ekinanp/puppet/subscription","commits_url":"https://api.github.com/repos/ekinanp/puppet/commits{/sha}","git_commits_url":"https://api.github.com/repos/ekinanp/puppet/git/commits{/sha}","comments_url":"https://api.github.com/repos/ekinanp/puppet/comments{/number}","issue_comment_url":"https://api.github.com/repos/ekinanp/puppet/issues/comments{/number}","contents_url":"https://api.github.com/repos/ekinanp/puppet/contents/{+path}","compare_url":"https://api.github.com/repos/ekinanp/puppet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ekinanp/puppet/merges","archive_url":"https://api.github.com/repos/ekinanp/puppet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ekinanp/puppet/downloads","issues_url":"https://api.github.com/repos/ekinanp/puppet/issues{/number}","pulls_url":"https://api.github.com/repos/ekinanp/puppet/pulls{/number}","milestones_url":"https://api.github.com/repos/ekinanp/puppet/milestones{/number}","notifications_url":"https://api.github.com/repos/ekinanp/puppet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ekinanp/puppet/labels{/name}","releases_url":"https://api.github.com/repos/ekinanp/puppet/releases{/id}","deployments_url":"https://api.github.com/repos/ekinanp/puppet/deployments","created_at":"2017-10-25T17:57:54Z","updated_at":"2018-08-14T17:17:50Z","pushed_at":"2018-08-14T18:16:15Z","git_url":"git://github.com/ekinanp/puppet.git","ssh_url":"git@github.com:ekinanp/puppet.git","clone_url":"https://github.com/ekinanp/puppet.git","svn_url":"https://github.com/ekinanp/puppet","homepage":"https://puppet.com/puppet/what-is-puppet","size":67491,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"puppetlabs:5.5.x","ref":"5.5.x","sha":"f875158bfcb83036a40ad2416b5d447556ee9f50","user":{"login":"puppetlabs","id":234268,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIzNDI2OA==","avatar_url":"https://avatars0.githubusercontent.com/u/234268?v=4","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":910744,"node_id":"MDEwOlJlcG9zaXRvcnk5MTA3NDQ=","name":"puppet","full_name":"puppetlabs/puppet","owner":{"login":"puppetlabs","id":234268,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIzNDI2OA==","avatar_url":"https://avatars0.githubusercontent.com/u/234268?v=4","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/puppetlabs/puppet","description":"Server automation framework and application","fork":false,"url":"https://api.github.com/repos/puppetlabs/puppet","forks_url":"https://api.github.com/repos/puppetlabs/puppet/forks","keys_url":"https://api.github.com/repos/puppetlabs/puppet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/puppetlabs/puppet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/puppetlabs/puppet/teams","hooks_url":"https://api.github.com/repos/puppetlabs/puppet/hooks","issue_events_url":"https://api.github.com/repos/puppetlabs/puppet/issues/events{/number}","events_url":"https://api.github.com/repos/puppetlabs/puppet/events","assignees_url":"https://api.github.com/repos/puppetlabs/puppet/assignees{/user}","branches_url":"https://api.github.com/repos/puppetlabs/puppet/branches{/branch}","tags_url":"https://api.github.com/repos/puppetlabs/puppet/tags","blobs_url":"https://api.github.com/repos/puppetlabs/puppet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/puppetlabs/puppet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/puppetlabs/puppet/git/refs{/sha}","trees_url":"https://api.github.com/repos/puppetlabs/puppet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/puppetlabs/puppet/statuses/{sha}","languages_url":"https://api.github.com/repos/puppetlabs/puppet/languages","stargazers_url":"https://api.github.com/repos/puppetlabs/puppet/stargazers","contributors_url":"https://api.github.com/repos/puppetlabs/puppet/contributors","subscribers_url":"https://api.github.com/repos/puppetlabs/puppet/subscribers","subscription_url":"https://api.github.com/repos/puppetlabs/puppet/subscription","commits_url":"https://api.github.com/repos/puppetlabs/puppet/commits{/sha}","git_commits_url":"https://api.github.com/repos/puppetlabs/puppet/git/commits{/sha}","comments_url":"https://api.github.com/repos/puppetlabs/puppet/comments{/number}","issue_comment_url":"https://api.github.com/repos/puppetlabs/puppet/issues/comments{/number}","contents_url":"https://api.github.com/repos/puppetlabs/puppet/contents/{+path}","compare_url":"https://api.github.com/repos/puppetlabs/puppet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/puppetlabs/puppet/merges","archive_url":"https://api.github.com/repos/puppetlabs/puppet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/puppetlabs/puppet/downloads","issues_url":"https://api.github.com/repos/puppetlabs/puppet/issues{/number}","pulls_url":"https://api.github.com/repos/puppetlabs/puppet/pulls{/number}","milestones_url":"https://api.github.com/repos/puppetlabs/puppet/milestones{/number}","notifications_url":"https://api.github.com/repos/puppetlabs/puppet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/puppetlabs/puppet/labels{/name}","releases_url":"https://api.github.com/repos/puppetlabs/puppet/releases{/id}","deployments_url":"https://api.github.com/repos/puppetlabs/puppet/deployments","created_at":"2010-09-14T19:26:44Z","updated_at":"2018-08-14T17:35:22Z","pushed_at":"2018-08-14T18:16:17Z","git_url":"git://github.com/puppetlabs/puppet.git","ssh_url":"git@github.com:puppetlabs/puppet.git","clone_url":"https://github.com/puppetlabs/puppet.git","svn_url":"https://github.com/puppetlabs/puppet","homepage":"https://puppet.com/puppet/what-is-puppet","size":67600,"stargazers_count":5055,"watchers_count":5055,"language":"Ruby","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2029,"mirror_url":null,"archived":false,"open_issues_count":52,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":2029,"open_issues":52,"watchers":5055,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987"},"html":{"href":"https://github.com/puppetlabs/puppet/pull/6987"},"issue":{"href":"https://api.github.com/repos/puppetlabs/puppet/issues/6987"},"comments":{"href":"https://api.github.com/repos/puppetlabs/puppet/issues/6987/comments"},"review_comments":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987/comments"},"review_comment":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/puppetlabs/puppet/pulls/6987/commits"},"statuses":{"href":"https://api.github.com/repos/puppetlabs/puppet/statuses/cd3c46000135b02e4bd5539218ea98614066fa96"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"smcclellan"}}