{"id":18,"date":"2007-05-14T08:55:19","date_gmt":"2007-05-14T14:55:19","guid":{"rendered":"http:\/\/blogs.cae.tntech.edu\/mwr\/2007\/05\/14\/client-application-management\/"},"modified":"2024-10-27T14:26:20","modified_gmt":"2024-10-27T14:26:20","slug":"client-application-management","status":"publish","type":"post","link":"https:\/\/sites.tntech.edu\/renfro\/2007\/05\/14\/client-application-management\/","title":{"rendered":"Client Application Management (Part 1, for .deb packages)"},"content":{"rendered":"<p>(<a href=\"http:\/\/www.infrastructures.org\/bootstrap\/apps.shtml\">Original infrastructures.org writeup here<\/a>.)<\/p>\n<p>Wow, this part has been a learning experience. The things I&#8217;ve picked up out of this stage:<\/p>\n<ul>\n<li>aptitude is not apt-get. Obvious, yes. But how different they are was not apparent until this weekend.<\/li>\n<li><a href=\"http:\/\/packages.debian.org\/stable\/admin\/pkgsync\">pkgsync<\/a> is great, and does exactly what it claims, but read its claims very carefully, since it can wreak legally-precise and well-defined havoc on your system.<\/li>\n<li>Xen instances beat actual hardware for testing puppet configurations. As long as the dom0 is accessible, I can pull up a console for a domU and investigate why my host fell off the face of the earth. Doing the same investigation on a real system requires a bit of a drive.<\/li>\n<\/ul>\n<p>More after the jump.<br \/>\n<!--more-->I only run Debian GNU\/Linux on our Linux systems, and I don&#8217;t think you can beat its package management policies and tools. Running primarily the stable release, and occasionally the testing release, I&#8217;ve never run into <a href=\"http:\/\/en.wikipedia.org\/wiki\/RPM_Package_Manager#Advantages_and_disadvantages_of_the_format\">dependency hell<\/a>. So I was pretty confident that anything to automate my usual route of <code>apt-get install package1 package2 ... packageN<\/code> would be a benefit.<\/p>\n<p>When I was going through making cfengine work as my configuration management tool, I had started to use <a href=\"http:\/\/www.debian-administration.org\/articles\/398\">Steve&#8217;s autoapt scripts<\/a>. I liked the way they worked: &#8220;for this hostname or system class, make sure the following packages are installed, and make sure the following are uninstalled.&#8221; No problems there, but if I was probably migrating away from cfengine to puppet, I&#8217;d take a look around and see what else was available.<\/p>\n<p>While looking around, I found this recipe for <a href=\"http:\/\/www.reductivelabs.com\/trac\/puppet\/wiki\/Recipes\/Pkgsync\">pkgsync<\/a>. Looked to be identical to what I had gotten used to with autoapt. And it almost was. Things I discovered, in relative order of occurrence:<\/p>\n<ol>\n<li>Why isn&#8217;t this pkgsync recipe doing anything? I see it rebuilding the musthave list, but nothing&#8217;s getting installed. Oh, the recipe had a -s flag on pkgsync, causing it to just simulate what was going to be installed. Well, what&#8217;s the point of that? Delete that flag, and let&#8217;s go!<\/li>\n<li>Why did my system drop off the face of the earth? It pings, but no ssh. Since it&#8217;s one of our dual-boot systems, maybe it got rebooted back into Windows via a power outage. No, nmap doesn&#8217;t show the usual Windows ports open on it. Maybe it&#8217;s back at a PXE debian-installer prompt, so drive in and see what&#8217;s up. Hmm, nope, it&#8217;s at regular login prompt. Log in. <code>ps aux | grep ssh<\/code> gives me <code>ps: Command not found<\/code>. Really? <code>dpkg -l | grep -v 'ii' | less<\/code> gives me <code>less: Command not found<\/code>. After reinstalling less, it&#8217;s obvious there&#8217;s a lot of stuff missing now. A little apt-get, dpkg, grep, and awk magic later, all my packages are back. So what happened? Oh, pkgsync has a <code>-k<\/code> flag, too. If you leave that off, it&#8217;ll remove lots of stuff. And it says so on the package page: <strong>&#8220;pkgsync will take care of meeting the demands put down in the lists, and then removing everything that is not in the &#8216;must&#8217; or &#8216;may&#8217; list and is not necessary for their operations (as determined by aptitude).&#8221;<\/strong> No <code>-k<\/code> flag, no guarantee that anything other than what is explicitly required by your musthave list will be installed after we&#8217;re done. <a href=\"http:\/\/tvtropes.org\/pmwiki\/pmwiki.php\/Main\/GravityIsAHarshMistress\">aptitude is a harsh mistress<\/a>, <a href=\"http:\/\/blueslyrics.tripod.com\/lyrics\/muddy_waters\/mean_mistreater.htm\">a mean mistreater<\/a> in blues parlance. But on the positive side, I had a very lean system with xemacs21, build-essential, rsync, ssmtp, and stow installed.<\/li>\n<li>Ok, so now all that&#8217;s cleared up. Go do other things, and pick back up on it in the morning. Hey, why&#8217;d the system fall off the face of the earth again? pkgsync has been fixed for hours, and I know nothing changed on the gold server while I was asleep. Oh, there&#8217;s a nightly cron job for pkgsync, and it doesn&#8217;t have a <code>-k<\/code> flag in it either. Let&#8217;s fix that, too. That would also explain why the original pkgsync recipe had a <code>-s<\/code> flag for pkgsync in it &#8212; probably not a mistake, but my assumption is that the author was happy with letting the cron job handle all the package updates.<\/li>\n<\/ol>\n<p>So the final configurations:<\/p>\n<p>\/etc\/puppet\/manifests\/classes\/pkgsync.pp:<\/p>\n<pre>\n# $Id$\nExec { path =&gt; \"\/usr\/bin:\/bin:\/usr\/sbin:\/sbin\" }\n\nclass pkgsync_setup {\n  package { pkgsync: ensure =&gt; installed }\n\n  file { [\"\/etc\/pkgsync\/musthave\", \"\/etc\/pkgsync\/mayhave\", \"\/etc\/pkgsync\/maynothave\"]:\n    ensure =&gt; present\n  }\n  file { \"\/etc\/cron.daily\/nightly-pkgsync\":\n    owner =&gt; root, group =&gt; root, mode =&gt; 755,\n    source =&gt; \"puppet:\/\/gold.cae.tntech.edu\/files\/apps\/pkgsync\/nightly-pkgsync\",\n    require =&gt; Package[pkgsync]\n  }\n  file { [ \"\/var\/lib\/puppet\/pkgsync\", \"\/etc\/pkgsync\"]: ensure =&gt; directory }\n  file { \"\/var\/lib\/puppet\/pkgsync\/musthave.d\":\n    ensure =&gt; directory,\n    purge =&gt; true,\n    backup =&gt; false,\n    recurse =&gt; true,\n    notify =&gt; Exec[pkgsync-musthave-rebuild]\n  }\n  file { \"\/var\/lib\/puppet\/pkgsync\/mayhave.d\":\n    ensure =&gt; directory,\n    purge =&gt; true,\n    backup =&gt; false,\n    recurse =&gt; true,\n    notify =&gt; Exec[pkgsync-mayhave-rebuild]\n  }\n  file { \"\/var\/lib\/puppet\/pkgsync\/maynothave.d\":\n    ensure =&gt; directory,\n    purge =&gt; true,\n    backup =&gt; false,\n    recurse =&gt; true,\n    notify =&gt; Exec[pkgsync-maynothave-rebuild]\n  }\n  exec { \"pkgsync-musthave-rebuild\":\n    command =&gt; \"find \/var\/lib\/puppet\/pkgsync\/musthave.d\/ -type f | xargs cat &gt; \/etc\/pkgsync\/musthave\",\n    refreshonly =&gt; true,\n    notify =&gt; Exec[pkgsync]\n  }\n  exec { \"pkgsync-mayhave-rebuild\":\n    command =&gt; \"find \/var\/lib\/puppet\/pkgsync\/mayhave.d\/ -type f | xargs cat &gt; \/etc\/pkgsync\/mayhave\",\n    refreshonly =&gt; true,\n  }\n  exec { \"pkgsync-maynothave-rebuild\":\n    command =&gt; \"find \/var\/lib\/puppet\/pkgsync\/maynothave.d\/ -type f | xargs cat &gt; \/etc\/pkgsync\/maynothave\",\n    refreshonly =&gt; true,\n  }\n  exec { \"pkgsync\": refreshonly =&gt; true, command =&gt; \"pkgsync -k\" }\n}\n\ndefine pkgsync($ensure) {\n  include pkgsync_setup\n  file { \"pkgsync_$ensure_$name\":\n    name =&gt; $ensure ? {\n      present =&gt; \"\/var\/lib\/puppet\/pkgsync\/musthave.d\/$name\",\n      absent =&gt; \"\/var\/lib\/puppet\/pkgsync\/maynothave.d\/$name\",\n      optional =&gt; \"\/var\/lib\/puppet\/pkgsync\/mayhave.d\/$name\"\n    },\n    ensure =&gt; present,\n    content =&gt; \"$namen\",\n    notify =&gt; $ensure ? {\n      present =&gt; Exec[pkgsync-musthave-rebuild],\n      absent =&gt; Exec[pkgsync-maynothave-rebuild],\n      optional =&gt; Exec[pkgsync-mayhave-rebuild]\n    }\n  }\n}<\/pre>\n<p>Host definition from site.pp:<\/p>\n<pre>\nclass cae-host {\n  include timezone-central\n  include ntp, ntpdate, sudo, openssh-server, syslog-ng\n}\n\nnode ch208e {\n  include cae-host\n  include pkgsync\n\n  # Use pkgsync for end-user apps with little to no configuration questions.\n  # Things like syslog-ng, ntp, and others with persistent daemons,\n  # non-default configuration files, etc. probably need to be broken out into\n  # their own classes above.\n  pkgsync {\n    [ \"xemacs21\", \"build-essential\", \"rsync\", \"stow\", \"ssmtp\" ]: ensure =&gt; present\n  }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>(Original infrastructures.org writeup here.) Wow, this part has been a learning experience. The things I&#8217;ve picked up out of this stage: aptitude is not apt-get. Obvious, yes. But how different they are was not apparent until this weekend. pkgsync is great, and does exactly what it claims, but read its claims very carefully, since it &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/sites.tntech.edu\/renfro\/2007\/05\/14\/client-application-management\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Client Application Management (Part 1, for .deb packages)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":87,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,7,16],"tags":[],"class_list":["post-18","post","type-post","status-publish","format-standard","hentry","category-debian","category-infrastructures","category-puppet","entry"],"_links":{"self":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/comments?post=18"}],"version-history":[{"count":1,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts\/18\/revisions"}],"predecessor-version":[{"id":503,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/posts\/18\/revisions\/503"}],"wp:attachment":[{"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/media?parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/categories?post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sites.tntech.edu\/renfro\/wp-json\/wp\/v2\/tags?post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}