開始使用
使用 JSON Schema 建立檔案系統模型
在這個逐步指南中,您將學習如何設計一個 JSON Schema,來反映 /etc/fstab
檔案的結構。
本指南分為以下幾個部分
- 簡介
- 建立
fstab
schema - 開始建立
entry
schema - 約束一個 entry
diskDevice
定義diskUUID
定義nfs
定義tmpfs
定義- 完整的 entry schema
- 在
fstab
schema 中參考entry
schema
簡介
並非 fstab 檔案的所有約束都可以單獨使用 JSON Schema 來建立模型; 但是,它可以表示其中的許多約束,並且此練習有助於展示約束如何運作。提供的範例說明了 JSON Schema 的概念,而不是真正的 fstab 檔案的工作 schema。
此範例顯示了檔案系統掛載點的 JSON Schema 表示法,如 /etc/fstab
檔案中所表示。
fstab 檔案中的 entry 可以有多種不同的形式; 這是一個範例
資料
{ "/": { "storage": { "type": "disk", "device": "/dev/sda1" }, "fstype": "btrfs", "readonly": true }, "/var": { "storage": { "type": "disk", "label": "8f3ba6f4-5c70-46ec-83af-0d5434953e5f" }, "fstype": "ext4", "options": [ "nosuid" ] }, "/tmp": { "storage": { "type": "tmpfs", "sizeInMB": 64 } }, "/var/www": { "storage": { "type": "nfs", "server": "my.nfs.server", "remotePath": "/exports/mypath" } }}
建立 fstab
schema
我們將從一個基本的 JSON Schema 開始,表達以下約束
- entry 的清單是一個 JSON 物件;
- 此物件的成員名稱(或屬性名稱)必須都是有效的絕對路徑;
- 必須有根檔案系統的 entry(即,
/
)。
從上到下建構我們的 JSON Schema
$id
關鍵字。$schema
關鍵字。type
驗證關鍵字。required
驗證關鍵字。properties
驗證關鍵字。/
金鑰現在是空的; 我們稍後再填寫。
patternProperties
驗證關鍵字。- 這會透過正規表示式比對其他屬性名稱。 注意:它不比對
/
。 ^(/[^/]+)+$
金鑰現在是空的; 我們稍後再填寫。
- 這會透過正規表示式比對其他屬性名稱。 注意:它不比對
additionalProperties
驗證關鍵字。- 這裡的值為
false
,以約束物件屬性為/
或符合正規表示式。
- 這裡的值為
您會注意到,正規表示式是明確錨定的(使用 ^
和 $
):在 JSON Schema 中,正規表示式(在 patternProperties
和 pattern
中)預設不會錨定。
{ "$id": "https://example.com/fstab", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "type": "object", "required": [ "/" ], "properties": { "/": {} }, "patternProperties": { "^(/[^/]+)+$": {} }, "additionalProperties": false}
開始建立 entry
schema
我們將從 JSON Schema 的大綱開始,其中會新增一些我們已經展示過的概念。
我們在先前的練習中看過這些關鍵字:$id
、$schema
、type
、required
和 properties
。
對此,我們加入:
description
註解關鍵字。oneOf
關鍵字。$ref
關鍵字。- 在這個例子中,所有使用的參考都是 Schema 本地的,使用相對片段 URI (
#/...
)。
- 在這個例子中,所有使用的參考都是 Schema 本地的,使用相對片段 URI (
$defs
關鍵字。- 包括幾個我們稍後會定義的關鍵名稱。
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "description": "JSON Schema for an fstab entry", "type": "object", "required": [ "storage" ], "properties": { "storage": { "type": "object", "oneOf": [ { "$ref": "#/$defs/diskDevice" }, { "$ref": "#/$defs/diskUUID" }, { "$ref": "#/$defs/nfs" }, { "$ref": "#/$defs/tmpfs" } ] } }, "$defs": { "diskDevice": {}, "diskUUID": {}, "nfs": {}, "tmpfs": {} }}
約束一個 entry
現在讓我們擴展這個骨架,為一些屬性新增限制。
- 我們的
fstype
鍵使用enum
驗證關鍵字。 - 我們的
options
鍵使用以下:type
驗證關鍵字(見上文)。minItems
驗證關鍵字。- 關於
items
驗證關鍵字。 - 關於
uniqueItems
驗證關鍵字。 - 它們共同表示:
options
必須是一個陣列,其中的項目必須是字串,至少要有一個項目,而且所有項目都應該是唯一的。
- 我們有一個
readonly
鍵。
加入這些限制後,schema 現在看起來像這樣
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "description": "JSON Schema for an fstab entry", "type": "object", "required": [ "storage" ], "properties": { "storage": { "type": "object", "oneOf": [ { "$ref": "#/$defs/diskDevice" }, { "$ref": "#/$defs/diskUUID" }, { "$ref": "#/$defs/nfs" }, { "$ref": "#/$defs/tmpfs" } ] }, "fstype": { "enum": [ "ext3", "ext4", "btrfs" ] }, "options": { "type": "array", "minItems": 1, "items": { "type": "string" }, "uniqueItems": true }, "readonly": { "type": "boolean" } }, "$defs": { "diskDevice": {}, "diskUUID": {}, "nfs": {}, "tmpfs": {} }}
diskDevice
定義
這裡引入了一個新的關鍵字
pattern
驗證關鍵字指出device
鍵必須是一個以 /dev 開頭的絕對路徑。
資料
{ "diskDevice": { "properties": { "type": { "enum": [ "disk" ] }, "device": { "type": "string", "pattern": "^/dev/[^/]+(/[^/]+)*$" } }, "required": [ "type", "device" ], "additionalProperties": false }}
diskUUID
定義
這裡沒有引入新的關鍵字。
我們有一個新的鍵:label
,而且 pattern
驗證關鍵字表示它必須是一個有效的 UUID。
資料
{ "diskUUID": { "properties": { "type": { "enum": [ "disk" ] }, "label": { "type": "string", "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}$" } }, "required": [ "type", "label" ], "additionalProperties": false }}
nfs
定義
我們發現另一個新的關鍵字
format
註解與斷言關鍵字。
資料
{ "nfs": { "properties": { "type": { "enum": [ "nfs" ] }, "remotePath": { "type": "string", "pattern": "^(/[^/]+)+$" }, "server": { "type": "string", "oneOf": [ { "format": "hostname" }, { "format": "ipv4" }, { "format": "ipv6" } ] } }, "required": [ "type", "server", "remotePath" ], "additionalProperties": false }}
tmpfs
定義
我們最後的定義引入了兩個新的關鍵字
資料
{ "tmpfs": { "properties": { "type": { "enum": [ "tmpfs" ] }, "sizeInMB": { "type": "integer", "minimum": 16, "maximum": 512 } }, "required": [ "type", "sizeInMB" ], "additionalProperties": false }}
完整的 entry schema
產生的結構描述相當龐大
{ "$id": "https://example.com/entry-schema", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "description": "JSON Schema for an fstab entry", "type": "object", "required": [ "storage" ], "properties": { "storage": { "type": "object", "oneOf": [ { "$ref": "#/$defs/diskDevice" }, { "$ref": "#/$defs/diskUUID" }, { "$ref": "#/$defs/nfs" }, { "$ref": "#/$defs/tmpfs" } ] }, "fstype": { "enum": [ "ext3", "ext4", "btrfs" ] }, "options": { "type": "array", "minItems": 1, "items": { "type": "string" }, "uniqueItems": true }, "readonly": { "type": "boolean" } }, "$defs": { "diskDevice": { "properties": { "type": { "enum": [ "disk" ] }, "device": { "type": "string", "pattern": "^/dev/[^/]+(/[^/]+)*$" } }, "required": [ "type", "device" ], "additionalProperties": false }, "diskUUID": { "properties": { "type": { "enum": [ "disk" ] }, "label": { "type": "string", "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}$" } }, "required": [ "type", "label" ], "additionalProperties": false }, "nfs": { "properties": { "type": { "enum": [ "nfs" ] }, "remotePath": { "type": "string", "pattern": "^(/[^/]+)+$" }, "server": { "type": "string", "oneOf": [ { "format": "hostname" }, { "format": "ipv4" }, { "format": "ipv6" } ] } }, "required": [ "type", "server", "remotePath" ], "additionalProperties": false }, "tmpfs": { "properties": { "type": { "enum": [ "tmpfs" ] }, "sizeInMB": { "type": "integer", "minimum": 16, "maximum": 512 } }, "required": [ "type", "sizeInMB" ], "additionalProperties": false } }}
在 fstab
schema 中參考 entry
schema
回到原點,我們使用 $ref
關鍵字,將我們的條目結構描述新增到練習開始時留空的鍵中。
/
鍵。^(/[^/]+)+$
鍵。
{ "$id": "https://example.com/fstab", "$schema": "https://json-schema.dev.org.tw/draft/2020-12/schema", "type": "object", "required": [ "/" ], "properties": { "/": { "$ref": "https://example.com/entry-schema" } }, "patternProperties": { "^(/[^/]+)+$": { "$ref": "https://example.com/entry-schema" } }, "additionalProperties": false}