1############################################################################### 2# 3# failsafe.cf - Basic Failsafe Policy for Community 4# 5############################################################################### 6 7body common control 8{ 9 bundlesequence => { "git_update" }; 10 version => "git-failsafe.cf 1.0.0"; 11} 12 13############################################################################# 14 15body agent control 16{ 17 ifelapsed => "1"; 18 skipidentify => "true"; 19} 20 21############################################################################# 22 23bundle agent git_update 24{ 25 vars: 26 27 "inputs_dir" string => translatepath("$(sys.workdir)/inputs"), 28 comment => "Directory containing Cfengine policies", 29 handle => "update_vars_inputs_dir"; 30 31 "ppkeys_file" string => translatepath("$(sys.workdir)/ppkeys/localhost.pub"), 32 comment => "Path to public key file", 33 handle => "update_vars_ppkeys_file"; 34 35 "file_check" string => translatepath("$(inputs_dir)/promises.cf"), 36 comment => "Path to a policy file", 37 handle => "update_vars_file_check"; 38 39 "master_location" string => "/var/cfengine/masterfiles", 40 comment => "The master cfengine policy directory on the policy host", 41 handle => "update_vars_master_location"; 42 43 "git_origin" string => "http://myserver.com/myrepo.git", 44 comment => "The URL to the Git repository.", 45 handle => "update_vars_git_origin"; 46 47 "git_checkout_location" string => "$(master_location)/myrepo", 48 comment => "The desired checkout location of the Git repository", 49 handle => "update_vars_git_checkout_location"; 50 51 "git_checkout_umask" string => "077", 52 comment => "The desired umask while checking out the Git repository", 53 handle => "update_vars_git_checkout_umask"; 54 55 "git_configfile" string => "$(git_checkout_location)/.git/config", 56 comment => "The .git/config file location", 57 handle => "update_vars_git_configfile"; 58 59 "git_branch" string => "master", 60 comment => "The desired branch of the Git repository", 61 handle => "update_vars_git_branch"; 62 63 "git_binary" string => "/usr/bin/git", 64 comment => "The location of the Git executable. Leave blank if you don't want to use Git.", 65 handle => "update_vars_git_binary"; 66 67 # 1. Remove untracked files, 2. Discard changes to index and working tree since HEAD 68 # 3. Check out the proper branch; 4. Pull the latest changes from origin; 69 # 5. Reset the working tree to the latest updates 70 "git_update_command" string => "$(git_binary) clean -f -f -x -q -d .; $(git_binary) reset -q --hard HEAD; $(git_binary) checkout -q $(git_branch); $(git_binary) pull -q -s recursive -Xtheirs origin $(git_branch); $(git_binary) reset -q --hard HEAD", 71 comment => "The commands to do a Git update. They should DTRT for your environment (checkout/reset/clean/etc).", 72 handle => "update_vars_git_update_command"; 73 74 "git_clone_command" string => "$(git_binary) clone -b $(git_branch) $(git_origin) $(git_checkout_location)", 75 comment => "The commands to do a Git update. They should DTRT for your environment (checkout/reset/clean/etc).", 76 handle => "update_vars_git_clone_command"; 77 78 "git_config_template" string => " 79[core] 80 repositoryformatversion = 0 81 filemode = true 82 bare = false 83 logallrefupdates = true 84[remote \"origin\"] 85 fetch = +refs/heads/*:refs/remotes/origin/* 86 url = $(git_origin) 87[branch \"master\"] 88 remote = origin 89 merge = refs/heads/master 90[branch \"$(git_branch)\"] 91 remote = origin 92 merge = refs/heads/$(git_branch) 93", 94 comment => "The $(git_configfile) template.", 95 handle => "update_vars_git_config_template"; 96 97# 98 99 classes: 100 101 # Set this to "any" or a machine class to have those machines do 102 # the Git checkouts locally, effectively replacing the policy 103 # hub model for a "just checkout from Git everywhere" model. 104 105 # This is not recommended unless you are testing in isolation or 106 # have other very specific requirements. 107 "idempotent_git" expression => "!any"; 108 109 "use_git" expression => fileexists("$(git_binary)"), 110 comment => "True if we found the Git binary and should use Git.", 111 handle => "update_classes_use_git"; 112 113 "git_checkout_location_exists" expression => fileexists("$(git_checkout_location)"), 114 comment => "True if the Git checkout location exists.", 115 handle => "update_classes_git_checkout_location_exists"; 116 117 "git_checkout_exists" expression => fileexists("$(git_checkout_location)/.git"), 118 comment => "True if the Git checkout has already happened.", 119 handle => "update_classes_git_checkout_exists"; 120 121 122 "have_ppkeys" expression => fileexists("$(ppkeys_file)"), 123 comment => "Check for /var/cfengine/ppkeys/localhost.pub", 124 handle => "update_classes_have_ppkeys"; 125 126 "files_ok" expression => fileexists("$(file_check)"), 127 comment => "Check for /var/cfengine/masterfiles/promises.cf", 128 handle => "update_classes_files_ok"; 129 130# 131 132 processes: 133 134 files_ok:: 135 136 "cf-serverd" restart_class => "start_server", 137 comment => "Monitor cf-serverd process", 138 handle => "update_processes_cf_serverd"; 139 140 "cf-monitord" restart_class => "start_monitor", 141 comment => "Monitor cf-monitord process", 142 handle => "update_processes_cf_monitord"; 143 144 files_ok.!windows:: 145 146 "cf-execd" restart_class => "start_exec", 147 comment => "Monitor cf-execd process", 148 handle => "update_processes_cf_execd"; 149 150# 151 152 commands: 153 154 start_server:: 155 156 "$(sys.cf_serverd)" 157 comment => "Start cf-serverd process", 158 handle => "update_commands_start_cf_serverd"; 159 160 start_monitor:: 161 162 "$(sys.cf_monitord)" 163 comment => "Start cf-monitord process", 164 handle => "update_commands_start_cf_monitord"; 165 166 !windows.start_exec:: 167 168 "$(sys.cf_execd)" 169 comment => "Start cf-execd process", 170 handle => "update_commands_start_cf_execd_not_windows"; 171 172 !have_ppkeys:: 173 174 "$(sys.cf_key)", 175 comment => "Generate cfengine encryption keys if necessary", 176 handle => "update_commands_generate_keys"; 177 178 (idempotent_git||am_policy_hub).use_git.git_config_ok:: 179 "$(git_update_command)" 180 contain => u_in_dir_umask_shell("$(git_checkout_location)", "$(git_checkout_umask)"), 181 comment => "Update the Git repository.", 182 handle => "update_commands_git_update", 183 classes => u_if_repaired("git_resolve_updated"); 184 185 (idempotent_git||am_policy_hub).use_git.!git_checkout_location_exists.!git_checkout_exists:: 186 "$(git_clone_command)" 187 contain => u_in_dir_umask_shell("/", "$(git_checkout_umask)"), 188 comment => "Clone the Git repository.", 189 handle => "update_commands_git_clone", 190 classes => u_if_repaired("git_resolve_cloned"); 191 192# 193 194 files: 195 196 !(idempotent_git||am_policy_hub):: # policy hub should not alter inputs/ uneccessary 197 198 "$(inputs_dir)/cf_promises_validated" 199 comment => "Check whether a validation stamp is available for a new policy update to reduce the distributed load", 200 handle => "check_valid_update", 201 copy_from => u_rcp("$(master_location)/cf_promises_validated","$(sys.policy_hub)"), 202 action => u_immediate, 203 classes => u_if_repaired("validated_updates_ready"); 204 205 # on the policy hub, converge the .git/config file iff the checkout has been made already 206 (idempotent_git||am_policy_hub).use_git.git_checkout_location_exists.git_checkout_exists:: 207 "$(git_configfile)" 208 handle => "converge_git_configfile", 209 classes => u_if_ok("git_config_ok"), 210 perms => u_m("600"), 211 edit_defaults => u_empty, 212 edit_line => u_insert_lines("$(git_config_template)"); 213 214 # on the policy hub, do the following if a) we don't use Git 215 # or b) the Git update succeeded 216 !idempotent_git.(am_policy_hub.((git_resolve_cloned||git_resolve_updated)|!use_git))|validated_updates_ready:: # policy hub should always put masterfiles in inputs in order to check new policy 217 218 "$(inputs_dir)" 219 comment => "Copy policy updates from master source on policy server if a new validation was acquired", 220 handle => "update_files_inputs_dir", 221 copy_from => u_rcp("$(master_location)","$(sys.policy_hub)"), 222 depth_search => u_recurse("inf"), 223 file_select => u_input_files, 224 depends_on => { "check_valid_update" }, 225 action => u_immediate, 226 classes => u_if_repaired("update_report"); 227 228 !windows:: 229 230 "$(sys.workdir)/bin" 231 comment => "Make sure cfengine binaries have right file permissions", 232 handle => "update_files_sys_workdir_bin", 233 perms => u_m("755"), 234 depth_search => u_recurse_basedir("inf"), 235 action => u_immediate; 236 237 "$(sys.workdir)/lib" 238 comment => "Make sure cfengine libraries have right file permissions", 239 handle => "update_files_sys_workdir_lib", 240 perms => u_m("644"), 241 depth_search => u_recurse_basedir("inf"), 242 action => u_immediate; 243 244 "$(sys.workdir)/lib" 245 comment => "Make sure cfengine libraries have right file permissions for only HP-UX", 246 handle => "update_files_sys_workdir_lib_hpux", 247 perms => u_m("755"), 248 depth_search => u_recurse_basedir("inf"), 249 action => u_immediate, 250 ifvarclass => "hpux"; 251 252 "/usr/local/bin" 253 comment => "Ensure cfengine binaries were copied to /usr/local/bin", 254 handle => "update_files_usr_local_bin", 255 perms => u_m("755"), 256 copy_from => u_cp_nobck("$(sys.workdir)/bin"), 257 file_select => u_cf3_files, 258 depth_search => u_recurse("1"), 259 action => u_immediate; 260 261 am_policy_hub:: 262 263 "$(master_location)/." 264 comment => "Make sure masterfiles folder has right file permissions", 265 handle => "update_files_sys_workdir_masterfiles", 266 perms => u_m("644"), 267 depth_search => u_recurse_basedir("inf"), 268 action => u_immediate; 269 270 reports: 271 git_checkout_location_exists.!git_checkout_exists:: 272 "$(git_checkout_location) already exists but it's not a Git checkout location. Aborting."; 273 git_resolve_updated:: 274 "Updated $(git_origin) (branch $(git_branch), umask $(git_checkout_umask)) into $(git_checkout_location)"; 275 git_resolve_cloned:: 276 "Cloned $(git_origin) (branch $(git_branch), umask $(git_checkout_umask)) into $(git_checkout_location)"; 277} 278 279######################################################### 280# Self-contained bodies from the lib to avoid dependencies 281######################################################### 282 283body perms u_m(p) 284{ 285 mode => "$(p)"; 286} 287 288######################################################### 289 290body file_select u_cf3_files 291{ 292 leaf_name => { "cf-.*" }; 293 file_result => "leaf_name"; 294} 295 296######################################################### 297 298body file_select u_input_files 299{ 300 leaf_name => { ".*.cf",".*.dat",".*.txt" }; 301 file_result => "leaf_name"; 302} 303 304######################################################### 305 306body copy_from u_rcp(from,server) 307{ 308 source => "$(from)"; 309 compare => "digest"; 310 trustkey => "false"; 311 312!am_policy_hub:: 313 314 servers => { "$(server)" }; 315} 316 317######################################################### 318 319body copy_from u_cp_nobck(from) 320{ 321 source => "$(from)"; 322 compare => "digest"; 323 copy_backup => "false"; 324} 325 326######################################################### 327 328body action u_immediate 329{ 330 ifelapsed => "0"; 331} 332 333######################################################### 334 335body depth_search u_recurse(d) 336{ 337 depth => "$(d)"; 338 exclude_dirs => { "\.svn", "\.git", "\.hg", "\.bzr" }; 339} 340 341######################################################### 342 343body depth_search u_recurse_basedir(d) 344{ 345 include_basedir => "true"; 346 depth => "$(d)"; 347 exclude_dirs => { "\.svn", "\.git", "\.hg", "\.bzr" }; 348} 349 350######################################################### 351 352body classes u_if_repaired(x) 353{ 354 promise_repaired => { "$(x)" }; 355} 356 357body classes u_if_ok(x) 358{ 359 promise_repaired => { "$(x)" }; 360 promise_kept => { "$(x)" }; 361} 362 363######################################################### 364 365body contain u_in_dir_umask_shell(dir, umask) 366{ 367 chdir => "$(dir)"; 368 useshell => "true"; 369 umask => "$(umask)"; 370} 371 372######################################################### 373 374bundle edit_line u_insert_lines(lines) 375{ 376 insert_lines: 377 378 "$(lines)" 379 comment => "Append lines if they don't exist"; 380} 381 382######################################################### 383 384body edit_defaults u_empty 385{ 386 empty_file_before_editing => "true"; 387 edit_backup => "false"; 388} 389 390######################################################### 391