Locked learning resources

Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Porting the Backup Check

Porting the Backup Check

In this lesson, you ported the sysadmin’s Python check to JavaScript, line by line, keeping its logic and changing its declarations and types. Then you ran both versions three ways and compared their output and exit status.

  • In Node, process.env plays the part of os.environ, and it needs no import. You read each setting as a property, with a dot, not with a get() call. An unset variable is undefined, not None, and every set one is a string.
  • Each read becomes a declaration with a camelCase name. A setting the check never changes is a const. The region is reassigned further down, when its default is filled in, so it’s a let.
  • The flag compares with === "1", so dryRun holds true or false. DRY_RUN=false is the text "false", which isn’t "1", so the check runs live.
  • The placeholder lastSuccess is a let, because the job reassigns it when a backup finishes, and it starts as null, where Python uses None.
  • Reading process.env.BACKUP_RETRIES is a plain property read, with nowhere to pass a default the way you pass one to os.environ.get(). So the port fills in the retry count’s default of "3" the way it fills in the region’s, then converts the text once with Number(retriesText). Without the conversion, retries + 1 would join text and promise 51 attempts.
  • Unlike int(), Number() never raises: it gives NaN for text that isn’t a number, such as "abc". The port doesn’t check for that, so it runs on and exits with status 0, where Python’s int() stops the check with status 1.
  • is None becomes === undefined. A === null check would wave an unset bucket through.
  • sys.exit(1) becomes process.exit(1), which ends the program with an exit code, as sys.exit() does. An exit code of 0 means success and anything else means failure, which is what cron checks, so cron sees the failure.
  • The mode is declared with let mode; before its if/else, so the print lines can reach it. A const inside each branch would end at its closing brace.
  • node --check backup-check.js reads the whole file without running it, and prints nothing when there’s no syntax error, such as a second let for the same name.

Here’s the port, backup-check.js, without the warning and the debug line:

Language: JavaScript
const bucket = process.env.BACKUP_BUCKET;
let region = process.env.BACKUP_REGION;
const notifyEmail = process.env.NOTIFY_EMAIL;
const dryRun = process.env.DRY_RUN === "1";
let retriesText = process.env.BACKUP_RETRIES;
if (retriesText === undefined) {
  retriesText = "3";
}
const retries = Number(retriesText);
let lastSuccess = null;

if (bucket === undefined) {
  console.log("No BACKUP_BUCKET set: refusing to start.");
  process.exit(1);
}

if (region === undefined) {
  region = "eu-west-1";
}

let mode;
if (dryRun) {
  mode = "dry run";
} else {
  mode = "live";
}

console.log(`Backing up to ${bucket} in ${region} (${mode})`);
console.log(`Up to ${retries + 1} attempts`);

Locked learning resources

Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Already a member? Sign-In

Locked learning resources

The full lesson is for members only. Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Already a member? Sign-In

00:02 Twice, the nightly backup has succeeded in the wrong place, so this Python check runs first. It reads five settings, refuses to start without a bucket, and prints what it’ll use.

00:15 You’ll port it. The port must refuse a missing bucket as Python does, with the same exit status, or cron reports success again. In Node, process.env stands in for os.environ, with no import.

00:32 Each setting is a property, not a .get() call: undefined when unset, and always a string when set. Each read becomes a camelCase const where the setting never changes.

00:45 The region is a let, because it’s reassigned later.

00:50 The flag is text, so it compares with strict === against the text one, and holds true or false. Set to false, it’s the text false, not the text one, so the check runs live.

01:04 The placeholder is a let, since the job reassigns it, and it starts as null, standing in for Python’s None here.

01:13 Python’s .get() takes a default, the text three. A property read can’t take one, so the port fills it in: a let, and an if that assigns the text three when it’s unset.

01:26 Then Number() converts the text once. Unlike int(), it never raises: bad text gives NaN, and the port, which doesn’t check for it, runs on and exits zero.

01:38 Without it, plus one would join text and promise fifty-one attempts.

01:45 Python’s is None becomes === undefined for an unset setting. A === check for null would wave the backup through.

01:55 Then sys.exit() becomes process.exit(). It ends the program with an exit code, as sys.exit() does. Zero means success, anything else failure, and that’s what cron checks.

02:10 The region’s check ports the same way.

02:15 The mode gets a let with no value before its if and else, so the print lines can reach it. A const inside each branch would end at its closing brace.

02:26 The print lines port with template literals, and plus one adds. The warning and the debug line are the exercise’s.

02:36 node --check reads the whole file without running it. It prints nothing, so there’s no syntax error, such as a second let for one name.

02:47 The first run sets everything but the region. Python prints three lines, and the port prints two. Those match, and Python’s third is the debug line. echo $? shows each exit status: both are zero.

03:06 The second run leaves the bucket unset. Python refuses and exits with status one. The port prints the same refusal and exits with one too. With === undefined and process.exit(), cron now sees the failure.

03:25 The third run sets the flag to the text false, empties the address, and unsets the retry count. How many attempts will the port promise? Your turn: pause the video and predict.

03:43 Four: the default three, plus one.

03:48 Both say live, and both exit with status zero. Python warns first, a line the port doesn’t have yet.

03:58 Bad retry text aside, the logic stays, and the declarations and types change. Use const unless a name is reassigned, === undefined for an unset setting, Number() once, and process.exit() to fail.

04:15 Next up is the exercise Finish the Backup Check. You’ll add the warning and the debug line, where Python’s str becomes string.

Become a Member to join the conversation.