{"action":"created","issue":{"url":"https://api.github.com/repos/cfengine/core/issues/2153","labels_url":"https://api.github.com/repos/cfengine/core/issues/2153/labels{/name}","comments_url":"https://api.github.com/repos/cfengine/core/issues/2153/comments","events_url":"https://api.github.com/repos/cfengine/core/issues/2153/events","html_url":"https://github.com/cfengine/core/pull/2153","id":64994062,"number":2153,"title":"Redmine#4309: implement common body attribute inherit_from for body inheritance","user":{"login":"tzz","id":67764,"avatar_url":"https://avatars.githubusercontent.com/u/67764?v=3","gravatar_id":"","url":"https://api.github.com/users/tzz","html_url":"https://github.com/tzz","followers_url":"https://api.github.com/users/tzz/followers","following_url":"https://api.github.com/users/tzz/following{/other_user}","gists_url":"https://api.github.com/users/tzz/gists{/gist_id}","starred_url":"https://api.github.com/users/tzz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tzz/subscriptions","organizations_url":"https://api.github.com/users/tzz/orgs","repos_url":"https://api.github.com/users/tzz/repos","events_url":"https://api.github.com/users/tzz/events{/privacy}","received_events_url":"https://api.github.com/users/tzz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"kacfengine","id":4037094,"avatar_url":"https://avatars.githubusercontent.com/u/4037094?v=3","gravatar_id":"","url":"https://api.github.com/users/kacfengine","html_url":"https://github.com/kacfengine","followers_url":"https://api.github.com/users/kacfengine/followers","following_url":"https://api.github.com/users/kacfengine/following{/other_user}","gists_url":"https://api.github.com/users/kacfengine/gists{/gist_id}","starred_url":"https://api.github.com/users/kacfengine/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kacfengine/subscriptions","organizations_url":"https://api.github.com/users/kacfengine/orgs","repos_url":"https://api.github.com/users/kacfengine/repos","events_url":"https://api.github.com/users/kacfengine/events{/privacy}","received_events_url":"https://api.github.com/users/kacfengine/received_events","type":"User","site_admin":false},"milestone":null,"comments":16,"created_at":"2015-03-28T21:56:51Z","updated_at":"2015-05-04T10:07:42Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/cfengine/core/pulls/2153","html_url":"https://github.com/cfengine/core/pull/2153","diff_url":"https://github.com/cfengine/core/pull/2153.diff","patch_url":"https://github.com/cfengine/core/pull/2153.patch"},"body":"After #2088 was merged thanks to @worr I realized it could be used to implement a universal `inherit_from` slist body attribute.\r\n\r\nExample:\r\n\r\n```\r\nbundle agent main\r\n{\r\n  reports:\r\n      \"def\" classes => classes_generic_2(\"def\");\r\n\r\n    def_ok::\r\n      \"def was OK!\";\r\n}\r\n\r\nbody classes classes_generic(x)\r\n# @brief Define `x` prefixed/suffixed with promise outcome\r\n# @param x The unique part of the classes to be defined\r\n{\r\n      promise_repaired => { \"promise_repaired_$(x)\", \"$(x)_repaired\", \"$(x)_ok\", \"$(x)_reached\" };\r\n      repair_failed => { \"repair_failed_$(x)\", \"$(x)_failed\", \"$(x)_not_ok\", \"$(x)_error\", \"$(x)_not_kept\", \"$(x)_not_repaired\", \"$(x)_reached\" };\r\n      repair_denied => { \"repair_denied_$(x)\", \"$(x)_denied\", \"$(x)_not_ok\", \"$(x)_error\", \"$(x)_not_kept\", \"$(x)_not_repaired\", \"$(x)_reached\" };\r\n      repair_timeout => { \"repair_timeout_$(x)\", \"$(x)_timeout\", \"$(x)_not_ok\", \"$(x)_error\", \"$(x)_not_kept\", \"$(x)_not_repaired\", \"$(x)_reached\" };\r\n      promise_kept => { \"promise_kept_$(x)\", \"$(x)_kept\", \"$(x)_ok\", \"$(x)_not_repaired\", \"$(x)_reached\" };\r\n}\r\n\r\nbody classes classes_generic_2(x)\r\n{\r\n      inherit_from => { classes_generic };\r\n}\r\n```\r\n\r\nOutput:\r\n\r\n```console\r\nR: def\r\nR: def was OK!\r\n```\r\n\r\nThe key to making this happen was that body attributes are actually appended to the promise, so CFEngine doesn't keep track of bodies per se.  So to implement inheritance, we just have to walk through a list of parent bodies and insert their attributes verbatim.  Thus this is a simple splice, **without** evaluation implications.  The only requirement is that derived bodies **must** use the same parameter names as their parents, if the parameter names are in the attributes.  In other words, if the parent is `classes_generic` as in the above example, then the child has to have the parameter `x` or the parent's attributes won't work.\r\n\r\nDuplicate attributes are overwritten by the child.\r\n\r\nAcceptance test is included.  If this is accepted, I'll add docs as well."},"comment":{"url":"https://api.github.com/repos/cfengine/core/issues/comments/98662155","html_url":"https://github.com/cfengine/core/pull/2153#issuecomment-98662155","issue_url":"https://api.github.com/repos/cfengine/core/issues/2153","id":98662155,"user":{"login":"basvandervlies","id":431367,"avatar_url":"https://avatars.githubusercontent.com/u/431367?v=3","gravatar_id":"","url":"https://api.github.com/users/basvandervlies","html_url":"https://github.com/basvandervlies","followers_url":"https://api.github.com/users/basvandervlies/followers","following_url":"https://api.github.com/users/basvandervlies/following{/other_user}","gists_url":"https://api.github.com/users/basvandervlies/gists{/gist_id}","starred_url":"https://api.github.com/users/basvandervlies/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/basvandervlies/subscriptions","organizations_url":"https://api.github.com/users/basvandervlies/orgs","repos_url":"https://api.github.com/users/basvandervlies/repos","events_url":"https://api.github.com/users/basvandervlies/events{/privacy}","received_events_url":"https://api.github.com/users/basvandervlies/received_events","type":"User","site_admin":false},"created_at":"2015-05-04T10:07:42Z","updated_at":"2015-05-04T10:07:42Z","body":"@kacfengine it is like the include all the bundle files option, that is now applied and make the life easier for some people.  I feel this option has the same potential. You do not have to use it for your masterfiles its an option for people that write their own libs, the \"power users\". we also have our own SURFsara library and the feature will really be used in this lib."}}