{"action":"created","issue":{"url":"https://api.github.com/repos/magfest/ubersystem-puppet/issues/28","repository_url":"https://api.github.com/repos/magfest/ubersystem-puppet","labels_url":"https://api.github.com/repos/magfest/ubersystem-puppet/issues/28/labels{/name}","comments_url":"https://api.github.com/repos/magfest/ubersystem-puppet/issues/28/comments","events_url":"https://api.github.com/repos/magfest/ubersystem-puppet/issues/28/events","html_url":"https://github.com/magfest/ubersystem-puppet/issues/28","id":73323736,"number":28,"title":"The Final Puppetization","user":{"login":"EliAndrewC","id":651592,"avatar_url":"https://avatars.githubusercontent.com/u/651592?v=3","gravatar_id":"","url":"https://api.github.com/users/EliAndrewC","html_url":"https://github.com/EliAndrewC","followers_url":"https://api.github.com/users/EliAndrewC/followers","following_url":"https://api.github.com/users/EliAndrewC/following{/other_user}","gists_url":"https://api.github.com/users/EliAndrewC/gists{/gist_id}","starred_url":"https://api.github.com/users/EliAndrewC/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EliAndrewC/subscriptions","organizations_url":"https://api.github.com/users/EliAndrewC/orgs","repos_url":"https://api.github.com/users/EliAndrewC/repos","events_url":"https://api.github.com/users/EliAndrewC/events{/privacy}","received_events_url":"https://api.github.com/users/EliAndrewC/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2015-05-05T14:04:45Z","updated_at":"2016-09-14T17:06:31Z","closed_at":null,"body":"At the moment, our puppet manifests suffer from the problem that if we add a config option, we need to go into our puppet manifest and template and then add it there as well, or else it isn't really configurable.  Ditto for config options which are not currently tracked by Puppet; they're technically configurable, but not really.\r\n\r\nAs it happens, our configuration is currently just a giant dictionary.  I mean, technically it's an ini file, but it ends up parsing to a dictionary.  So instead of having a bunch of different hiera variables, each controlling a single option, I'd like to have a single dictionary which maps to the entire config.  For example, if we had this yaml\r\n\r\n```yaml\r\nconfig:\r\n    foo: 5\r\n    bar:\r\n        baz: 6\r\n        spam:\r\n            hello: \"world\"\r\n```\r\n\r\nthat would render the following to our development.ini file\r\n\r\n```\r\nfoo = 5\r\n[bar]\r\nbaz = 6\r\n[[spam]\r\nhello = \"world\"\r\n```\r\n\r\nThen we could have a single nested hiera variable which will always be able to contain any/all of our config options without having to individually puppetize each one."},"comment":{"url":"https://api.github.com/repos/magfest/ubersystem-puppet/issues/comments/247083998","html_url":"https://github.com/magfest/ubersystem-puppet/issues/28#issuecomment-247083998","issue_url":"https://api.github.com/repos/magfest/ubersystem-puppet/issues/28","id":247083998,"user":{"login":"EliAndrewC","id":651592,"avatar_url":"https://avatars.githubusercontent.com/u/651592?v=3","gravatar_id":"","url":"https://api.github.com/users/EliAndrewC","html_url":"https://github.com/EliAndrewC","followers_url":"https://api.github.com/users/EliAndrewC/followers","following_url":"https://api.github.com/users/EliAndrewC/following{/other_user}","gists_url":"https://api.github.com/users/EliAndrewC/gists{/gist_id}","starred_url":"https://api.github.com/users/EliAndrewC/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EliAndrewC/subscriptions","organizations_url":"https://api.github.com/users/EliAndrewC/orgs","repos_url":"https://api.github.com/users/EliAndrewC/repos","events_url":"https://api.github.com/users/EliAndrewC/events{/privacy}","received_events_url":"https://api.github.com/users/EliAndrewC/received_events","type":"User","site_admin":false},"created_at":"2016-09-14T17:06:31Z","updated_at":"2016-09-14T17:06:31Z","body":"Someone implemented this where I work and it turned out to be pretty straightforward for the simple case (which wouldn't completely apply to us).  If we have a ``foo`` project then we just have a single hiera variable.  Then we put this in the erb template for our ``development.ini``:\r\n\r\n```\r\n<% \r\ndef hash_to_config(any_name, any_hash, level)\r\n   if any_hash.empty?\r\n      return \"\"\r\n   end\r\n\r\n   if level > 0 \r\n      ret_val = \"\\n\" + \"[\" * level + any_name + \"]\" * level + \"\\n\"\r\n   else\r\n      ret_val = \"\"\r\n   end\r\n\r\n   any_hash.sort_by{|n,v| if v.is_a?(Hash) then \"z\"+n else n end}.each do |data, value|\r\n      if value.is_a?(Hash)\r\n         ret_val += hash_to_config(data, value, level+1)\r\n      elsif value.is_a?(Array)\r\n         ret_val += data + \" = \" + value.collect{|x| \"\\'#{x}\\'\"}.join(',') + \"\\n\"\r\n      elsif value.is_a?(Integer)\r\n         ret_val += data + \" = \" + value.to_s + \"\\n\"\r\n      elsif value == !!value\r\n         ret_val += data + \" = \" + value.to_s.capitalize + \"\\n\"\r\n      elsif [\"true\",\"false\"].include? value.downcase\r\n         ret_val += data + \" = \" + value.capitalize + \"\\n\"\r\n      else\r\n         ret_val += data + \" = \\\"\" + value + \"\\\"\\n\"\r\n      end\r\n   end\r\n   return ret_val\r\nend \r\n-%>\r\n<% if not foo_options.empty? -%>\r\n<%= hash_to_config(\"\", foo_options, 0) -%>\r\n<% end -%>\r\n```\r\n\r\nObviously it would be a pretty big refactor to go from what we have now to taking this approach.  And the difficult part which this ducks merging data from different sub-parts of the has.  Still, I figured I'd post this snippet since it's at least half the battle (even if it is the easy half)."}}
{"actor":{"display_login":"EliAndrewC"}}