############################################################
#
#  Chinese Dragon Dancing on a Star
#
#  This method works with either Community or Enterprise.
#  and uses named signals
#
#  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 => { "dragon_symphony" };
      inputs => { "libraries/cfengine_stdlib.cf" };
}

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

bundle agent dragon_symphony
{
  methods:

      # We have to seed the beginning by creating the dragon
      # /tmp/dragon_localhost

      "dragon"  usebundle => visit("localhost","host1","chapter1");

      "dragon"  usebundle => visit("host1","host2","chapter2");

      "dragon"  usebundle => visit("host2","host3","chapter3");

      "dragon"  usebundle => visit("host3","host4","chapter4"),
      classes => if_ok("finale");

  reports:

    finale::

      "The dragon is slain:"
      printfile => visitors_book("/tmp/shoo_dragon_host4");
}

############################################################
# Define the 
############################################################

bundle agent chapter1(x)
{
      # Do something significant here

  reports:

    host1::
      " ----> Breathing fire on $(x)";
}

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

bundle agent chapter2(x)
{
      # Do something significant here

  reports:

    host2::
      " ----> Breathing fire on $(x)";

}

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

bundle agent chapter3(x)
{
      # Do something significant here

  reports:

    host3::
      " ----> Breathing fire on $(x)";

}

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

bundle agent chapter4(x)
{
      # Do something significant here

  reports:

    host4::
      " ----> Breathing fire on $(x)";

}

############################################################
# Orchestration wrappers
############################################################

bundle agent visit(predecessor,satellite,method)
{

      # This is a wrapper for the orchestration will be acted on
      # first by the dragon's lair and then by the satellite

  vars:

      "dragons_lair" string => "host0";

  files:

      # We start in the dragon's lair ..

      "/tmp/unleash_dragon"

      comment => "Unleash the dragon",
      rename => to("/tmp/enter_the_dragon"),
      classes => if_repaired("dispatch_dragon_$(satellite)"),
      ifvarclass => "$(dragons_lair)";

      # if we are the dragon's lair, welcome the dragon back, shooed from the satellite

      "/tmp/enter_the_dragon"

      comment => "Returning from a visit to a satellite",
      copy_from => secure_cp("/tmp/shoo_dragon_$(predecessor)","$(predecessor)"),
      classes => if_repaired("dispatch_dragon_$(satellite)"),
      ifvarclass => "$(dragons_lair)";

      # If we are a satellite, receive the dragon from its lair

      "/tmp/enter_the_dragon"
      comment => "Wait for our cue or relay/conductor baton",
      copy_from => secure_cp("/tmp/dragon_$(satellite)","$(dragons_lair)"),
      classes => if_repaired("cue_action_on_$(satellite)"),
      ifvarclass => "$(satellite)";

  methods:

      "check in at home"
      comment => "Edit the load balancer?",
      usebundle => switch_satellite(" -> Send dragon to $(satellite)"),
      classes => if_repaired("send_the_dragon_to_$(satellite)"),
      ifvarclass => "dispatch_dragon_$(satellite)";

      "dragon visits"
      comment => "One off activity that the nodes carry out while the dragon visits",
      usebundle => $(method)("$(satellite)"),
      classes => if_repaired("send_the_dragon_back_from_$(satellite)"),
      ifvarclass => "cue_action_on_$(satellite)";


  files:

      # hub/lair hub signs the book too and schedules the dragon for next satellite

      "/tmp/dragon_$(satellite)"   
      create => "true",
      comment => "Add our signature to the dragon's tail",
      edit_line => sign_visitor_book("Dragon returned from $(predecessor)"),
      ifvarclass => "send_the_dragon_to_$(satellite)";

      # Satellite signs the book and shoos dragon for hub to collect

      "/tmp/shoo_dragon_$(satellite)"
      create => "true",
      comment => "Add our signature to the dragon's tail",
      edit_line => sign_visitor_book("Dragon visited $(satellite) and did: $(method)"),
      ifvarclass => "send_the_dragon_back_from_$(satellite)";

  reports:
      "Done $(satellite)";

}

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

bundle agent switch_satellite(name)
{
  files:

      "/tmp/enter_the_dragon"
      comment => "Add our signature to the dragon's tail",
      edit_line => append_if_no_line("Switch new dragon's target $(name)");

  reports:
      " X Switching new dragon's target $(name)";
}


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

bundle edit_line sign_visitor_book(s)
{
  insert_lines:

      "/tmp/enter_the_dragon"
      comment => "Import the current visitor's book",
      insert_type => "file";

      "$(s)" comment => "Append this string to the visitor's book";
}

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


bundle server access_rules()
{
  access:

      "/tmp"

      admit => { "127.0.0.1" };

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

}

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

body printfile visitors_book(file)
{
      file_to_print   => "$(file)";
      number_of_lines => "100";
}


