Skip to content

Commit 7ac6f61

Browse files
Charlie OwenCharlie Owen
authored andcommitted
Making what should be final edits to file system.
1 parent f0c3a3a commit 7ac6f61

File tree

1 file changed

+91
-89
lines changed

1 file changed

+91
-89
lines changed

learn/file-system.md

Lines changed: 91 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,20 @@ layout: page
33
title: Modeling a file system with JSON Schema
44
---
55

6-
> Not all constraints to an fstab file can be modeled using JSON Schema alone; however, it can represent a good number of them and the exercise is useful to demonstrate how constraints work.
6+
* [Introduction](#introduction)
7+
* [Creating the `fstab` schema](#fstab-schema)
8+
* [Starting the `entry` schema](#entry-schema)
9+
* [Constraining an entry](#constraining-entry)
10+
* [The `diskDevice` definition](#diskdevice)
11+
* [The `diskUUID` definition](#diskuuid)
12+
* [The `nfs` definition](#nfs)
13+
* [The `tmpfs` definition](#tmpfs)
14+
* [The full entry schema](#full-entry)
15+
* [Referencing the `entry` schema in the `fstab` schema](#referencing-entry)
16+
17+
## <a name="introduction"></a>Introduction
18+
19+
> Not all constraints to an fstab file can be modeled using JSON Schema alone; however, it can represent a good number of them and the exercise is useful to demonstrate how constraints work. The examples provided are illustrative of the JSON Schema concepts rather than a real, working schema for an fstab file.
720
821
This example shows a possible JSON Schema representation of file system mount points as represented in an [`/etc/fstab`](https://en.wikipedia.org/wiki/Fstab) file.
922

@@ -43,7 +56,7 @@ An entry in an fstab file can have many different forms; Here is an example:
4356
}
4457
```
4558

46-
## Creating the schema outline
59+
## <a name="fstab-schema"></a>Creating the `fstab` schema
4760

4861
We will start with a base JSON Schema expressing the following constraints:
4962

@@ -57,8 +70,11 @@ Building out our JSON Schema from top to bottom:
5770
* The [`$schema`](http://json-schema.org/latest/json-schema-core.html#rfc.section.7) keyword.
5871
* The [`type`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1) validation keyword.
5972
* The [`required`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.3) validation keyword.
60-
* The [`properties`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.4) validation keyword with only a `/` entry.
61-
* The [`patternProperties`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.5) validation keyword to match other property names via a regular expression. Note: it does not match `/`).
73+
* The [`properties`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.4) validation keyword.
74+
* The `/` key is empty now; We will fill it out later.
75+
* The [`patternProperties`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.5) validation keyword.
76+
* This matches other property names via a regular expression. Note: it does not match `/`.
77+
* The `^(/[^/]+)+$` key is empty now; We will fill it out later.
6278
* The [`additionalProperties`](http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.6) validation keyword.
6379
* The value here is `false` to constrain object properties to be either `/` or to match the regular expression.
6480

@@ -80,7 +96,7 @@ Building out our JSON Schema from top to bottom:
8096
}
8197
```
8298

83-
## Starting an entry
99+
## <a name="entry-schema"></a>Starting the `entry` schema
84100

85101
We will start with an outline of the JSON schema which adds new concepts to what we've already demonstrated.
86102

@@ -97,7 +113,7 @@ To this we add:
97113

98114
```json
99115
{
100-
"id": "http://example.com/entry-schema",
116+
"$id": "http://example.com/entry-schema",
101117
"$schema": "http://json-schema.org/draft-07/schema#",
102118
"description": "JSON Schema for an fstab entry",
103119
"type": "object",
@@ -122,7 +138,7 @@ To this we add:
122138
}
123139
```
124140

125-
## Constraining entries
141+
## <a name="constraining-entry"></a>Constraining an entry
126142

127143
Let's now extend this skeleton to add constraints to some of the properties.
128144

@@ -139,7 +155,7 @@ With these added constraints, the schema now looks like this:
139155

140156
```json
141157
{
142-
"id": "http://example.com/entry-schema",
158+
"$id": "http://example.com/entry-schema",
143159
"$schema": "http://json-schema.org/draft-07/schema#",
144160
"description": "JSON Schema for an fstab entry",
145161
"type": "object",
@@ -178,7 +194,7 @@ With these added constraints, the schema now looks like this:
178194
}
179195
```
180196

181-
## The `diskDevice` definition
197+
## <a name="diskdevice"></a>The `diskDevice` definition
182198

183199
One new keyword is introduced here:
184200

@@ -202,7 +218,7 @@ One new keyword is introduced here:
202218
}
203219
```
204220

205-
## The `diskUUID` definition
221+
## <a name="diskuuid"></a>The `diskUUID` definition
206222

207223
No new keywords are introduced here.
208224

@@ -226,7 +242,7 @@ We do have a new key: `label` and the `pattern` validation keyword states it mus
226242
}
227243
```
228244

229-
## The `nfs` definition
245+
## <a name="nfs"></a>The `nfs` definition
230246

231247
We find another new keyword:
232248

@@ -256,7 +272,7 @@ We find another new keyword:
256272
}
257273
```
258274

259-
## The *tmpfs* definition
275+
## <a name="tmpfs"></a>The `tmpfs` definition
260276

261277
Our last definition introduces two new keywords:
262278

@@ -281,15 +297,15 @@ Our last definition introduces two new keywords:
281297
}
282298
```
283299

284-
## The full entry schema
300+
## <a name="full-entry"></a>The full entry schema
285301

286302
The resulting schema is quite large:
287303

288304
```json
289305
{
290-
"id": "http://some.site.somewhere/entry-schema#",
306+
"$id": "http://example.com/entry-schema",
291307
"$schema": "http://json-schema.org/draft-07/schema#",
292-
"description": "schema for an fstab entry",
308+
"description": "JSON Schema for an fstab entry",
293309
"type": "object",
294310
"required": [ "storage" ],
295311
"properties": {
@@ -308,111 +324,97 @@ The resulting schema is quite large:
308324
"options": {
309325
"type": "array",
310326
"minItems": 1,
311-
"items": { "type": "string" },
327+
"items": {
328+
"type": "string"
329+
},
312330
"uniqueItems": true
313331
},
314-
"readonly": { "type": "boolean" }
332+
"readonly": {
333+
"type": "boolean"
334+
}
315335
},
316336
"definitions": {
317337
"diskDevice": {
318338
"properties": {
319-
"type": { "enum": [ "disk" ] },
339+
"type": {
340+
"enum": [ "disk" ]
341+
},
320342
"device": {
321343
"type": "string",
322344
"pattern": "^/dev/[^/]+(/[^/]+)*$"
323345
}
324346
},
325347
"required": [ "type", "device" ],
326348
"additionalProperties": false
327-
},
328-
"diskUUID": {
329-
"properties": {
330-
"type": { "enum": [ "disk" ] },
331-
"label": {
332-
"type": "string",
333-
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
334-
}
349+
}
350+
},
351+
"diskUUID": {
352+
"properties": {
353+
"type": {
354+
"enum": [ "disk" ]
335355
},
336-
"required": [ "type", "label" ],
337-
"additionalProperties": false
356+
"label": {
357+
"type": "string",
358+
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
359+
}
338360
},
339-
"nfs": {
340-
"properties": {
341-
"type": { "enum": [ "nfs" ] },
342-
"remotePath": {
343-
"type": "string",
344-
"pattern": "^(/[^/]+)+$"
345-
},
346-
"server": {
347-
"type": "string",
348-
"oneOf": [
349-
{ "format": "hostname" },
350-
{ "format": "ipv4" },
351-
{ "format": "ipv6" }
352-
]
353-
}
361+
"required": [ "type", "label" ],
362+
"additionalProperties": false
363+
},
364+
"nfs": {
365+
"properties": {
366+
"type": { "enum": [ "nfs" ] },
367+
"remotePath": {
368+
"type": "string",
369+
"pattern": "^(/[^/]+)+$"
354370
},
355-
"required": [ "type", "server", "remotePath" ],
356-
"additionalProperties": false
371+
"server": {
372+
"type": "string",
373+
"oneOf": [
374+
{ "format": "hostname" },
375+
{ "format": "ipv4" },
376+
{ "format": "ipv6" }
377+
]
378+
}
357379
},
358-
"tmpfs": {
359-
"properties": {
360-
"type": { "enum": [ "tmpfs" ] },
361-
"sizeInMB": {
362-
"type": "integer",
363-
"minimum": 16,
364-
"maximum": 512
365-
}
366-
},
367-
"required": [ "type", "sizeInMB" ],
368-
"additionalProperties": false
369-
}
380+
"required": [ "type", "server", "remotePath" ],
381+
"additionalProperties": false
382+
},
383+
"tmpfs": {
384+
"properties": {
385+
"type": { "enum": [ "tmpfs" ] },
386+
"sizeInMB": {
387+
"type": "integer",
388+
"minimum": 16,
389+
"maximum": 512
390+
}
391+
},
392+
"required": [ "type", "sizeInMB" ],
393+
"additionalProperties": false
370394
}
371395
}
396+
}
372397
```
373398

374-
## Plugging this into our main schema
399+
## <a name="referencing-entry"></a>Referencing the `entry` schema in the `fstab` schema
375400

376-
Now that all possible entries have been described, we can refer to the entry schema from our main schema. We will, again, use a JSON Reference here:
401+
Coming full circle we use the `$ref` keyword to add our entry schema into the keys left empty at the start of the exercise:
402+
403+
* The `/` key.
404+
* The `^(/[^/]+)+$` key.
377405

378406
```json
379407
{
408+
"$id": "http://example.com/fstab",
380409
"$schema": "http://json-schema.org/draft-07/schema#",
381410
"type": "object",
411+
"required": [ "/" ],
382412
"properties": {
383-
"/": { "$ref": "http://some.site.somewhere/entry-schema#" }
413+
"/": { "$ref": "http://example.com/entry-schema" }
384414
},
385415
"patternProperties": {
386-
"^(/[^/]+)+$": { "$ref": "http://some.site.somewhere/entry-schema#" }
416+
"^(/[^/]+)+$": { "$ref": "http://example.com/entry-schema" }
387417
},
388418
"additionalProperties": false,
389-
"required": [ "/" ]
390419
}
391420
```
392-
393-
## Wrapping up
394-
395-
This example is much more advanced than the previous example; you will have learned of schema referencing and identification, you will have been introduced to other keywords. There are also a few additional points to consider.
396-
397-
### The schema can be improved
398-
399-
This is only an example for learning purposes. Some additional constraints could be described. For instance:
400-
401-
* it makes no sense for `/` to be mounted on a tmpfs filesystem;
402-
* it makes no sense to specify the filesystem type if the storage is either NFS or tmpfs.
403-
404-
As an exercise, you can always try to add these constraints. It would probably require splitting the schema further.
405-
406-
### Not all constraints can be expressed
407-
408-
JSON Schema limits itself to describing the structure of JSON data, it cannot express functional constraints.
409-
410-
If we take an NFS entry as an example, JSON Schema alone cannot check that the submitted NFS server's hostname, or IP address, is actually correct: this check is left to applications.
411-
412-
### Tools have varying JSON Schema support
413-
414-
While this is not a concern if you know that the schema you write will be used by you alone, you should keep this in mind if you write a schema which other people can potentially use. The schema we have written here has some features which can be problematic for portability:
415-
416-
* *format* support is optional, and as such other tools may ignore this keyword: this can lead to a different validation outcome for the same data;
417-
* it uses regular expressions: care should be taken not to use any advanced features (such as lookarounds), since they may not be supported at the other end;
418-
* it uses *$schema* to express the need to use draft v6 compliant processing, but not all tools support draft v6.

0 commit comments

Comments
 (0)