1 | ;
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | const schema_1 = require("@stencila/schema");
|
7 | const docker_file_parser_1 = __importDefault(require("docker-file-parser"));
|
8 | const Doer_1 = __importDefault(require("./Doer"));
|
9 | /**
|
10 | * Parser for Dockerfiles
|
11 | *
|
12 | * This class implements Dockerfile parsing. It extracts meta-data defined in a Dockerfile using
|
13 | * the [`LABEL`](https://docs.docker.com/engine/reference/builder/#label) or
|
14 | * deprecated [`MAINTAINER`](https://docs.docker.com/engine/reference/builder/#maintainer-deprecated) instructions.
|
15 | * Unlike the other parsers in Dockter it does not attempt to parse out dependencies.
|
16 | *
|
17 | * Here "label" refers to a key in a LABEL instruction that is un-prefixed
|
18 | * or has either the [`org.opencontainers.image`](https://github.com/opencontainers/image-spec/blob/master/annotations.md) prefix,
|
19 | * or the deprecated [`org.label-schema`](https://github.com/label-schema/label-schema.org) prefix.
|
20 | * In other words, the following are all equivalent:
|
21 | *
|
22 | * ```Dockerfile
|
23 | * LABEL version = 1.2.0
|
24 | * LABEL org.opencontainers.image.version = 1.2.0
|
25 | * LABEL org.label-schema.version = 1.2.0
|
26 | * ```
|
27 | *
|
28 | * The following [schema crosswalk](https://en.wikipedia.org/wiki/Schema_crosswalk) defines how labels in
|
29 | * Dockerfiles are translated into JSON-LD properties
|
30 | *
|
31 | * | Label | Property (`context:type.property`)
|
32 | * | --- | ----
|
33 | * | `authors` | `schema:CreativeWork.author`
|
34 | * | `build` |
|
35 | * | `created` | `schema:SoftwareSourceCode.dateCreated`
|
36 | * | `description` | `schema:Thing.description`
|
37 | * | `documentation` | `schema:softwareHelp`
|
38 | * | `licenses` | `schema:CreativeWork.license`
|
39 | * | `maintainer` | `codemeta:SoftwareSourceCode.maintainer`
|
40 | * | `ref-name` |
|
41 | * | `revision` |
|
42 | * | `schema-version` | `schema:schemaVersion`
|
43 | * | `source` | `schema:SoftwareSourceCode.codeRepository`
|
44 | * | `title` | `schema:Thing.name`
|
45 | * | `url` | `schema:Thing.url`
|
46 | * | `vendor` | `schema:Organization.legalName`
|
47 | * | `version` | `schema:SoftwareApplication.softwareVersion`
|
48 | *
|
49 | */
|
50 | class DockerParser extends Doer_1.default {
|
51 | /**
|
52 | * Parse a folder by detecting any Dockerfile
|
53 | * and return a `SoftwareEnvironment` instance
|
54 | */
|
55 | async parse(content) {
|
56 | let dockerfile;
|
57 | if (content) {
|
58 | dockerfile = content;
|
59 | }
|
60 | else {
|
61 | if (!this.exists('Dockerfile'))
|
62 | return null;
|
63 | dockerfile = this.read('Dockerfile');
|
64 | }
|
65 | const environ = new schema_1.SoftwareEnvironment();
|
66 | // Parse instructions from the Dockerfile
|
67 | const instructions = docker_file_parser_1.default.parse(dockerfile);
|
68 | // Process LABEL instructions
|
69 | for (let instruction of instructions.filter(instruction => instruction.name === 'LABEL')) {
|
70 | for (let [key, value] of Object.entries(instruction.args)) {
|
71 | // Remove recognised prefixes from key
|
72 | const match = key.match(/^(org\.opencontainers\.image|org\.label-schema)\.([^ ]+)$/);
|
73 | if (match)
|
74 | key = match[2];
|
75 | // Unquote value if necessary
|
76 | if (value.startsWith('"'))
|
77 | value = value.substring(1);
|
78 | if (value.endsWith('"'))
|
79 | value = value.slice(0, -1);
|
80 | // Unescape spaces
|
81 | value = value.replace(/\\ /, ' ');
|
82 | switch (key) {
|
83 | case 'name':
|
84 | environ.name = value;
|
85 | break;
|
86 | case 'description':
|
87 | environ.description = value;
|
88 | break;
|
89 | case 'maintainer':
|
90 | case 'author':
|
91 | environ.authors.push(schema_1.Person.fromText(value));
|
92 | break;
|
93 | }
|
94 | }
|
95 | }
|
96 | // Process MAINTAINER instructions
|
97 | for (let instruction of instructions.filter(instruction => instruction.name === 'MAINTAINER')) {
|
98 | let author = '';
|
99 | if (typeof instruction.args === 'string')
|
100 | author = instruction.args;
|
101 | else
|
102 | throw new Error(`Unexpected type of instruction arguments ${typeof instruction.args}`);
|
103 | environ.authors.push(schema_1.Person.fromText(author));
|
104 | }
|
105 | return environ;
|
106 | }
|
107 | }
|
108 | exports.default = DockerParser;
|