mirror of
https://github.com/silverstripe/silverstripe-environmentcheck
synced 2024-10-22 17:05:40 +02:00
Initial release of the module, based on Sam and Will's work
This commit is contained in:
commit
9426ffb12e
84
README.md
Normal file
84
README.md
Normal file
@ -0,0 +1,84 @@
|
||||
# SilverStripe Environment Checker Module
|
||||
|
||||
Developed by Sam Minnée, thanks to Will Rossiter.
|
||||
|
||||
This module adds an API for running environment checks to your API.
|
||||
|
||||
* `dev/health`` - A public URL that performs a quick check that this environment is functioning. This could be tied to a load balancer, for example.
|
||||
* `dev/check` - An admin-only URL that performs a more comprehensive set of checks. This could be tied to a deployment system, for example.
|
||||
|
||||
## Aren't these just unit tests?
|
||||
|
||||
Almost, but not really. Environment checks differ from unit tests in two important ways:
|
||||
|
||||
* **They test environment specific settings.** Unit tests are designed to use dummy data and mock interfaces to external system. Environment checks check the real systems and data that the given environment is actually connected to.
|
||||
* **They can't modify data.** Because these checks will run using production databases, they can't go modifying the data in there. This is the biggest reason why we haven't used the same base class as a unit test for writing environment checks - we wanted to make it impossible to accidentally plug the a unit test into the environment checker!
|
||||
|
||||
## Adding more checks
|
||||
|
||||
To add more checks, you should put additional `EnvironmentCheckSuite::register` calls into your `_config.php`. See the `_config.php` file of this mode for examples.
|
||||
|
||||
:::php
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("curl_init")', "Does PHP have CURL support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("imagecreatetruecolor")', "Does PHP have GD2 support?");
|
||||
|
||||
The first argument is the name of the check suite. There are two built-in check suites, "health", and "check", corresponding to the `dev/health` and `dev/check` URLs. If you wish, you can create your own check suites and execute them on other URLs.
|
||||
|
||||
The module comes bundled with a few checks in DefaultHealthChecks.php. However, to test your own application, you probably want to write custom checks.
|
||||
|
||||
* Implement the EnvironmentCheck interface
|
||||
* Define the check() function, which returns a 2 element array:
|
||||
* The first element is one of `EnvironmentCheck::OK`, `EnvironmentCheck::WARNING`, `EnvironmentCheck::ERROR`, depending on the status of the check
|
||||
* The second element is a string describing the response.
|
||||
|
||||
Here is a simple example of how you might create a check to test your own code. In this example, we are checking that an instance of the `MyGateway` class will return "foo" when `call()` is called on it. Testing interfaces with 3rd party systems is a common use case for custom environment checks.
|
||||
|
||||
:::php
|
||||
class MyGatewayCheck implements EnvironmentCheck {
|
||||
protected $checkTable;
|
||||
|
||||
function check() {
|
||||
$g = new MyGateway;
|
||||
|
||||
$response = $g->call();
|
||||
$expectedResponse = "foo";
|
||||
|
||||
if($response == null) {
|
||||
return array(EnvironmentCheck::ERROR, "MyGateway didn't return a response");
|
||||
} else if($response != $expectedResponse) {
|
||||
return array(EnvironmentCheck::WARNING, "MyGateway returned unexpected response $response");
|
||||
} else {
|
||||
return array(EnvironmentCheck::OK, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Once you have created your custom check class, don't forget to register it in a check suite
|
||||
|
||||
:::php
|
||||
EnvironmentCheckSuite::register('check', 'MyGatewayCheck', "Can I connect to the gateway?");
|
||||
|
||||
### Using other environment check suites
|
||||
|
||||
"health" and "check" are the only environment check suites that we use because they aren
|
||||
|
||||
If you want to use the same UI as dev/health and dev/check, you can create an `EnvironmentChecker` object. This class is a `RequestHandler` and so can be returned from an action handler. The first argument to the `EnvironmentChecker` constructor is the suite name. For example:
|
||||
|
||||
class DevHealth extends Controller {
|
||||
function index() {
|
||||
$e = new EnvironmentChecker('health', 'Site health');
|
||||
return $e;
|
||||
}
|
||||
}
|
||||
|
||||
If you wish to embed an environment check suite in another, you can use the following call.
|
||||
|
||||
$result = EnvironmentCheckSuite::inst("health")->run();
|
||||
|
||||
`$result` will contain a `EnvironmentCheckSuiteResult` object
|
||||
|
||||
* **`$result->ShouldPass()`:** Return a boolean of whether or not the tests passed.
|
||||
* **`$result->Status()`:** The string "OK", "WARNING", or "ERROR", depending on the worst failure.
|
||||
* **`$result->Details()`:** A `DataObjectSet` of details about the result of each check in the suite.
|
||||
|
||||
See `EnvironmentChecker.ss` to see how these can be used to build a UI.
|
25
_config.php
Normal file
25
_config.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// These power dev/health, which can be used by load balancers and other such systems
|
||||
EnvironmentCheckSuite::register('health', 'DatabaseCheck');
|
||||
|
||||
// These power dev/check, which is used for diagnostics and for deployment
|
||||
EnvironmentCheckSuite::register('check', 'DatabaseCheck("Member")', "Is the database accessible?");
|
||||
EnvironmentCheckSuite::register('check', 'URLCheck("")', "Is the homepage accessible?");
|
||||
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("curl_init")', "Does PHP have CURL support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("imagecreatetruecolor")', "Does PHP have GD2 support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("xml_set_object")', "Does PHP have XML support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("token_get_all")', "Does PHP have tokenizer support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("iconv")', "Does PHP have iconv support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("hash")', "Does PHP have hash support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasFunctionCheck("session_start")', "Does PHP have session support?");
|
||||
EnvironmentCheckSuite::register('check', 'HasClassCheck("DOMDocument")', "Does PHP have DOMDocument support?");
|
||||
|
||||
EnvironmentCheckSuite::register('check', 'FileWriteableCheck("assets")', "Is assets/ writeable?");
|
||||
EnvironmentCheckSuite::register('check', 'FileWriteableCheck("' . TEMP_FOLDER . '")', "Is the temp folder writeable?");
|
||||
|
||||
Director::addRules(100, array(
|
||||
'dev/health' => 'DevHealth',
|
||||
'dev/check' => 'DevCheck',
|
||||
));
|
157
code/DefaultHealthChecks.php
Normal file
157
code/DefaultHealthChecks.php
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file contains a number of default environment checks that you can use.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Check that the connection to the database is working, by looking for records in some table.
|
||||
* By default, Member will be checked.
|
||||
*
|
||||
* @param $checkTable The table that will be checked.
|
||||
*/
|
||||
class DatabaseCheck implements EnvironmentCheck {
|
||||
protected $checkTable;
|
||||
|
||||
function __construct($checkTable = "Member") {
|
||||
$this->checkTable = $checkTable;
|
||||
}
|
||||
|
||||
function check() {
|
||||
$count = DB::query("SELECT COUNT(*) FROM \"$this->checkTable\"")->value();
|
||||
|
||||
if($count > 0) {
|
||||
return array(EnvironmentCheck::OK, "");
|
||||
} else {
|
||||
return array(EnvironmentCheck::WARNING, "$this->checkTable queried ok but has no records");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a given URL is functioning, by default, the homepage.
|
||||
*
|
||||
* Note that Director::test() will be used rather than a CURL check.
|
||||
*/
|
||||
class URLCheck implements EnvironmentCheck {
|
||||
protected $url;
|
||||
protected $testString;
|
||||
|
||||
/*
|
||||
* @param $url The URL to check, relative to the site. "" is the homepage.
|
||||
* @param $testString A piece of text to optionally search for in the homepage HTML. If omitted, no such check is made.
|
||||
*/
|
||||
function __construct($url = "", $testString = "") {
|
||||
$this->url = $url;
|
||||
$this->testString = $testString;
|
||||
}
|
||||
|
||||
function check() {
|
||||
$response = Director::test($this->url);
|
||||
|
||||
if($response->getStatusCode() != 200) {
|
||||
return array(EnvironmentCheck::ERROR, "Homepage requested and returned HTTP " . $response->getStatusCode() . " response");
|
||||
|
||||
} else if($this->testString && (strpos($response->getBody(), $this->testString) === false)) {
|
||||
return array(EnvironmentCheck::WARNING, "Homepage requested ok but '$testString' not found.");
|
||||
|
||||
} else {
|
||||
return array(EnvironmentCheck::OK, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given function exists.
|
||||
* This can be used to check that PHP modules or features are installed.
|
||||
* @param $functionName The name of the function to look for.
|
||||
*/
|
||||
class HasFunctionCheck implements EnvironmentCheck {
|
||||
protected $functionName;
|
||||
|
||||
function __construct($functionName) {
|
||||
$this->functionName = $functionName;
|
||||
}
|
||||
|
||||
function check() {
|
||||
if(function_exists($this->functionName)) return array(EnvironmentCheck::OK, $this->functionName.'() exists');
|
||||
else return array(EnvironmentCheck::ERROR, $this->functionName.'() doesn\'t exist');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given class exists.
|
||||
* This can be used to check that PHP modules or features are installed.
|
||||
* @param $className The name of the class to look for.
|
||||
*/
|
||||
class HasClassCheck implements EnvironmentCheck {
|
||||
protected $className;
|
||||
|
||||
function __construct($className) {
|
||||
$this->className = $className;
|
||||
}
|
||||
|
||||
function check() {
|
||||
if(class_exists($this->className)) return array(EnvironmentCheck::OK, 'Class ' . $this->className.' exists');
|
||||
else return array(EnvironmentCheck::ERROR, 'Class ' . $this->className.' doesn\'t exist');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given file is writeable.
|
||||
* This can be used to check that the environment doesn't have permission set-up errors.
|
||||
* @param $path The full path. If a relative path, it will relative to the BASE_PATH
|
||||
*/
|
||||
class FileWriteableCheck implements EnvironmentCheck {
|
||||
protected $path;
|
||||
|
||||
function __construct($path) {
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
function check() {
|
||||
if($this->path[0] == '/') $filename = $this->path;
|
||||
else $filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $this->path);
|
||||
|
||||
if(file_exists($filename)) $isWriteable = is_writeable($filename);
|
||||
else $isWriteable = is_writeable(dirname($filename));
|
||||
|
||||
if(!$isWriteable) {
|
||||
if(function_exists('posix_getgroups')) {
|
||||
$userID = posix_geteuid();
|
||||
$user = posix_getpwuid($userID);
|
||||
|
||||
$currentOwnerID = fileowner(file_exists($filename) ? $filename : dirname($filename) );
|
||||
$currentOwner = posix_getpwuid($currentOwnerID);
|
||||
|
||||
$message = "User '$user[name]' needs to be able to write to this file:\n$filename\n\nThe file is currently owned by '$currentOwner[name]'. ";
|
||||
|
||||
if($user['name'] == $currentOwner['name']) {
|
||||
$message .= "We recommend that you make the file writeable.";
|
||||
} else {
|
||||
|
||||
$groups = posix_getgroups();
|
||||
$groupList = array();
|
||||
foreach($groups as $group) {
|
||||
$groupInfo = posix_getgrgid($group);
|
||||
if(in_array($currentOwner['name'], $groupInfo['members'])) $groupList[] = $groupInfo['name'];
|
||||
}
|
||||
if($groupList) {
|
||||
$message .= " We recommend that you make the file group-writeable and change the group to one of these groups:\n - ". implode("\n - ", $groupList)
|
||||
. "\n\nFor example:\nchmod g+w $filename\nchgrp " . $groupList[0] . " $filename";
|
||||
} else {
|
||||
$message .= " There is no user-group that contains both the web-server user and the owner of this file. Change the ownership of the file, create a new group, or temporarily make the file writeable by everyone during the install process.";
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$message .= "The webserver user needs to be able to write to this file:\n$filename";
|
||||
}
|
||||
|
||||
return array(EnvironmentCheck::ERROR, $message);
|
||||
}
|
||||
|
||||
return array(EnvironmentCheck::OK,'');
|
||||
}
|
||||
}
|
10
code/DevCheck.php
Normal file
10
code/DevCheck.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
class DevCheck extends Controller {
|
||||
function index() {
|
||||
if(!Permission::check("ADMIN")) return Security::permissionFailure();
|
||||
|
||||
$e = new EnvironmentChecker('check', 'Environment status');
|
||||
return $e;
|
||||
}
|
||||
}
|
9
code/DevHealth.php
Normal file
9
code/DevHealth.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
class DevHealth extends Controller {
|
||||
function index() {
|
||||
$e = new EnvironmentChecker('health', 'Site health');
|
||||
$e->setErrorCode(404);
|
||||
return $e;
|
||||
}
|
||||
}
|
175
code/EnvironmentCheck.php
Normal file
175
code/EnvironmentCheck.php
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Interface for environment checks
|
||||
*
|
||||
* An environment check is a test that can be performed on a live environment. They differ from unit
|
||||
* tests in that they are designed to check the state of the evnironment / server, rather than the code.
|
||||
*
|
||||
* Environment checks should *never* alter production data.
|
||||
*
|
||||
* Some things you might make environment checks for:
|
||||
* - Can I access the database?
|
||||
* - Are the right PHP modules installed?
|
||||
* - Are the file permissions correct?
|
||||
*/
|
||||
interface EnvironmentCheck {
|
||||
|
||||
const ERROR = 3;
|
||||
const WARNING = 2;
|
||||
const OK = 1;
|
||||
|
||||
/**
|
||||
* Perform this check
|
||||
*
|
||||
* @return 2 element array( $status, $message )
|
||||
* $status is EnvironmentCheck::ERROR, EnvironmentCheck::WARNING, or EnvironmentCheck::OK
|
||||
*/
|
||||
function check();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a suite of environment checks.
|
||||
* Also has a register for assigning environment checks to named instances of EnvironmentCheckSuite
|
||||
*
|
||||
* Usage:
|
||||
* EnvironmentCheckSuite::register('health', 'MyHealthCheck');
|
||||
*
|
||||
* $result = EnvironmentCheckSuite::inst('health')->run();
|
||||
*/
|
||||
class EnvironmentCheckSuite {
|
||||
protected $checks = array();
|
||||
|
||||
/**
|
||||
* Run this test suite
|
||||
* @return The result code of the worst result.
|
||||
*/
|
||||
public function run() {
|
||||
$worstResult = 0;
|
||||
|
||||
$result = new EnvironmentCheckSuiteResult;
|
||||
foreach($this->checkInstances() as $check) {
|
||||
list($checkClass, $checkTitle) = $check;
|
||||
try {
|
||||
list($status, $message) = $checkClass->check();
|
||||
// If the check fails, register that as an error
|
||||
} catch(Exception $e) {
|
||||
$status = EnvironmentCheck::ERROR;
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
$result->addResult($status, $message, $checkTitle);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instances of all the environment checks
|
||||
*/
|
||||
protected function checkInstances() {
|
||||
$output = array();
|
||||
foreach($this->checks as $check) {
|
||||
list($checkClass, $checkTitle) = $check;
|
||||
if(is_string($checkClass)) {
|
||||
$checkInst = Object::create_from_string($checkClass);
|
||||
if($checkInst instanceof EnvironmentCheck) {
|
||||
$output[] = array($checkInst, $checkTitle);
|
||||
} else {
|
||||
throw new InvalidArgumentException("Bad EnvironmentCheck: '$checkClass' - the named class doesn't implement EnvironmentCheck");
|
||||
}
|
||||
} else if($checkClass instanceof EnvironmentCheck) {
|
||||
$output[] = array($checkClass, $checkTitle);
|
||||
} else {
|
||||
throw new InvalidArgumentException("Bad EnvironmentCheck: " . var_export($check, true));
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a check to this suite.
|
||||
*
|
||||
*/
|
||||
public function push($check, $title = null) {
|
||||
if(!$title) {
|
||||
$title = is_string($check) ? $check : get_class($check);
|
||||
}
|
||||
$this->checks[] = array($check, $title);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected static $instances = array();
|
||||
|
||||
/**
|
||||
* Return a named instance of EnvironmentCheckSuite.
|
||||
*/
|
||||
static function inst($name) {
|
||||
if(!isset(self::$instances[$name])) self::$instances[$name] = new EnvironmentCheckSuite();
|
||||
return self::$instances[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a check against the named check suite
|
||||
*/
|
||||
static function register($name, $check, $title = null) {
|
||||
self::inst($name)->push($check, $title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A single set of results from running an EnvironmentCheckSuite
|
||||
*/
|
||||
class EnvironmentCheckSuiteResult extends ViewableData {
|
||||
protected $details, $worst = 0;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->details = new DataObjectSet();
|
||||
}
|
||||
|
||||
function addResult($status, $message, $checkIdentifier) {
|
||||
$this->details->push(new ArrayData(array(
|
||||
'Check' => $checkIdentifier,
|
||||
'Status' => $this->statusText($status),
|
||||
'Message' => $message,
|
||||
)));
|
||||
|
||||
$this->worst = max($this->worst, $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are no ERRORs, only WARNINGs or OK
|
||||
*/
|
||||
function ShouldPass() {
|
||||
return $this->worst <= EnvironmentCheck::WARNING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns overall (i.e. worst) status as a string.
|
||||
*/
|
||||
function Status() {
|
||||
return $this->statusText($this->worst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns detailed status information about each check
|
||||
*/
|
||||
function Details() {
|
||||
return $this->details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a text version of a status code
|
||||
*/
|
||||
protected function statusText($status) {
|
||||
switch($status) {
|
||||
case EnvironmentCheck::ERROR: return "ERROR";
|
||||
case EnvironmentCheck::WARNING: return "WARNING";
|
||||
case EnvironmentCheck::OK: return "OK";
|
||||
case 0: return "NO CHECKS";
|
||||
default: throw new InvalidArgumentException("Bad environment check status '$status'");
|
||||
}
|
||||
}
|
||||
}
|
59
code/EnvironmentChecker.php
Normal file
59
code/EnvironmentChecker.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Provides an interface for checking the given EnvironmentCheckSuite.
|
||||
*/
|
||||
class EnvironmentChecker extends RequestHandler {
|
||||
static $url_handlers = array(
|
||||
'' => 'index',
|
||||
);
|
||||
|
||||
protected $checkSuiteName;
|
||||
protected $title;
|
||||
|
||||
protected $errorCode = 500;
|
||||
|
||||
function __construct($checkSuiteName, $title) {
|
||||
parent::__construct();
|
||||
|
||||
$this->checkSuiteName = $checkSuiteName;
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HTTP status code that should be returned when there's an error.
|
||||
* Defaults to 500
|
||||
*/
|
||||
function setErrorCode($errorCode) {
|
||||
$this->errorCode = $errorCode;
|
||||
}
|
||||
|
||||
function init() {
|
||||
parent::init();
|
||||
|
||||
// We allow access to this controller regardless of live-status or ADMIN permission only
|
||||
// if on CLI. Access to this controller is always allowed in "dev-mode", or of the user is ADMIN.
|
||||
$canAccess = (Director::isDev()
|
||||
|| Director::is_cli()
|
||||
// Its important that we don't run this check if dev/build was requested
|
||||
|| Permission::check("ADMIN")
|
||||
);
|
||||
if(!$canAccess) return Security::permissionFailure($this);
|
||||
}
|
||||
|
||||
function index() {
|
||||
$response = new SS_HTTPResponse;
|
||||
$result = EnvironmentCheckSuite::inst($this->checkSuiteName)->run();
|
||||
|
||||
if(!$result->ShouldPass()) {
|
||||
$response->setStatusCode($this->errorCode);
|
||||
}
|
||||
|
||||
$response->setBody($result->customise(array(
|
||||
"Title" => $this->title,
|
||||
"ErrorCode" => $this->errorCode,
|
||||
))->renderWith("EnvironmentChecker"));
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
75
templates/EnvironmentChecker.ss
Normal file
75
templates/EnvironmentChecker.ss
Normal file
@ -0,0 +1,75 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Site health: $Status</title>
|
||||
<style>
|
||||
* {
|
||||
font-family: Helvetica, Arial;
|
||||
font-size: 12px;
|
||||
}
|
||||
.subtext {
|
||||
margin-top: -10px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table th {
|
||||
color: white;
|
||||
background-color: #777;
|
||||
/*border: 1px #aaa solid;*/
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
table td {
|
||||
background-color: #eee;
|
||||
/*border: 1px #ddd solid;*/
|
||||
padding: 5px 10px;
|
||||
}
|
||||
table tr:nth-child(odd) td {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.OK {
|
||||
color: green;
|
||||
}
|
||||
.WARNING {
|
||||
color: orange;
|
||||
font-weight: bold;
|
||||
}
|
||||
.ERROR {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<h1 class="$Status">$Title: $Status</h1>
|
||||
|
||||
<table>
|
||||
<tr><th>Check</th> <th>Status</th> <th>Message</th></tr>
|
||||
<% control Details %>
|
||||
<tr><td>$Check</td> <td class="$Status">$Status</td> <td>$Message.XML</td></tr>
|
||||
<% end_control %>
|
||||
</table>
|
||||
|
||||
<% if ShouldPass %>
|
||||
<p>Site is available</p>
|
||||
<p class="subtext">(you may check for the presence of the text 'Site is available' rather than an HTTP $ErrorCode error on this page, if you prefer.)</p>
|
||||
<% else %>
|
||||
<p><b>Site is not available</b></p>
|
||||
<% end_if %>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user