############################################################
#
# The self-healing tower: Anti-Dominoes
#
#  This method works with Enterprise
#
#  If you want to test this on localhost, just edit /etc/hosts
#  to add host1 host2 host3 host4 as aliases to localhost
#
############################################################

body common control
{
      bundlesequence => { "weak_dependency_symphony" };
      inputs => { "libraries/cfengine_stdlib.cf" };
}

body server control
{
      allowconnects         => { "127.0.0.1" , "::1", @(def.acl) };
      allowallconnects      => { "127.0.0.1" , "::1", @(def.acl) };
}


############################################################

bundle agent weak_dependency_symphony
{
  methods:

      # We have to seed the beginning by creating the tower
      # /tmp/tower_localhost

    host1::
      "tower"  usebundle => tier1,
      classes => publish_ok("ok_O");

    host2::
      "tower"  usebundle => tier2,
      classes => publish_ok("ok_1");

    host3::
      "tower"  usebundle => tier3,
      classes => publish_ok("ok_2");

    host4::
      "tower"  usebundle => tier4,
      classes => publish_ok("ok_f");

  classes:

    ok_O:: # Wait for the methods, report on host1 only

      "check1" expression => remoteclassesmatching("ok.*","host2","yes","a");
      "check2" expression => remoteclassesmatching("ok.*","host3","yes","a");
      "check3" expression => remoteclassesmatching("ok.*","host4","yes","a");

  reports:

    ok_O::
      "tier 1 is ok";
    a_ok_1::
      "tier 2 is ok";
    a_ok_2::
      "tier 3 is ok";
    a_ok_f::
      "tier 4 is ok";

    ok_O&a_ok_1&a_ok_2&a_ok_f::
      "The Tower is standing";

    !(ok_O&a_ok_1&a_ok_2&a_ok_f)::
      "The Tower is down";
}

############################################################

bundle agent tier1
{
  files:

      "/tmp/something_to_do_1"
      create => "true";
}

bundle agent tier2
{
  files:

      "/tmp/something_to_do_2"
      create => "true";
}

bundle agent tier3
{
  files:

      "/tmp/something_to_do_3"
      create => "true";

}

bundle agent tier4
{
  files:

      "/tmp/something_to_do_4"
      create => "true";
}

############################################################


bundle server access_rules()
{
  access:

      "ok.*"
      resource_type => "context",
      admit => { "127.0.0.1" };

}

############################################################

body classes publish_ok(x)
{
      promise_repaired => { "$(x)" };
      promise_kept => { "$(x)" };
      cancel_notkept => { "$(x)" };
      persist_time => "2";
}

