f62a0e189d
Service container entrypoint/command support is now unconditional.
185 lines
5.8 KiB
TypeScript
185 lines
5.8 KiB
TypeScript
import {TemplateContext} from "../../templates/template-context.js";
|
|
import {MappingToken, SequenceToken, StringToken, TemplateToken} from "../../templates/tokens/index.js";
|
|
import {isString} from "../../templates/tokens/type-guards.js";
|
|
import {Container, Credential} from "../workflow-template.js";
|
|
|
|
export function convertToJobContainer(context: TemplateContext, container: TemplateToken): Container | undefined {
|
|
let image: StringToken | undefined;
|
|
let env: MappingToken | undefined;
|
|
let ports: SequenceToken | undefined;
|
|
let volumes: SequenceToken | undefined;
|
|
let options: StringToken | undefined;
|
|
|
|
// Skip validation for expressions for now to match
|
|
// behavior of the other parsers
|
|
for (const [, token] of TemplateToken.traverse(container)) {
|
|
if (token.isExpression) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (isString(container)) {
|
|
// Workflow uses shorthand syntax `container: image-name`
|
|
image = container.assertString("container item");
|
|
return {image: image};
|
|
}
|
|
|
|
const mapping = container.assertMapping("container item");
|
|
if (mapping)
|
|
for (const item of mapping) {
|
|
const key = item.key.assertString("container item key");
|
|
const value = item.value;
|
|
|
|
switch (key.value) {
|
|
case "image":
|
|
image = value.assertString("container image");
|
|
break;
|
|
case "credentials":
|
|
convertToJobCredentials(context, value);
|
|
break;
|
|
case "env":
|
|
env = value.assertMapping("container env");
|
|
for (const envItem of env) {
|
|
envItem.key.assertString("container env value");
|
|
}
|
|
break;
|
|
case "ports":
|
|
ports = value.assertSequence("container ports");
|
|
for (const port of ports) {
|
|
port.assertString("container port");
|
|
}
|
|
break;
|
|
case "volumes":
|
|
volumes = value.assertSequence("container volumes");
|
|
for (const volume of volumes) {
|
|
volume.assertString("container volume");
|
|
}
|
|
break;
|
|
case "options":
|
|
options = value.assertString("container options");
|
|
break;
|
|
default:
|
|
context.error(key, `Unexpected container item key: ${key.value}`);
|
|
}
|
|
}
|
|
|
|
if (!image) {
|
|
context.error(container, "Container image cannot be empty");
|
|
} else {
|
|
return {image, env, ports, volumes, options};
|
|
}
|
|
}
|
|
|
|
export function convertToServiceContainer(context: TemplateContext, container: TemplateToken): Container | undefined {
|
|
let image: StringToken | undefined;
|
|
let env: MappingToken | undefined;
|
|
let ports: SequenceToken | undefined;
|
|
let volumes: SequenceToken | undefined;
|
|
let options: StringToken | undefined;
|
|
let entrypoint: StringToken | undefined;
|
|
let command: StringToken | undefined;
|
|
|
|
// Skip validation for expressions for now to match
|
|
// behavior of the other parsers
|
|
for (const [, token] of TemplateToken.traverse(container)) {
|
|
if (token.isExpression) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (isString(container)) {
|
|
image = container.assertString("container item");
|
|
return {image: image};
|
|
}
|
|
|
|
const mapping = container.assertMapping("container item");
|
|
if (mapping)
|
|
for (const item of mapping) {
|
|
const key = item.key.assertString("container item key");
|
|
const value = item.value;
|
|
|
|
switch (key.value) {
|
|
case "image":
|
|
image = value.assertString("container image");
|
|
break;
|
|
case "credentials":
|
|
convertToJobCredentials(context, value);
|
|
break;
|
|
case "env":
|
|
env = value.assertMapping("container env");
|
|
for (const envItem of env) {
|
|
envItem.key.assertString("container env value");
|
|
}
|
|
break;
|
|
case "ports":
|
|
ports = value.assertSequence("container ports");
|
|
for (const port of ports) {
|
|
port.assertString("container port");
|
|
}
|
|
break;
|
|
case "volumes":
|
|
volumes = value.assertSequence("container volumes");
|
|
for (const volume of volumes) {
|
|
volume.assertString("container volume");
|
|
}
|
|
break;
|
|
case "options":
|
|
options = value.assertString("container options");
|
|
break;
|
|
case "entrypoint":
|
|
entrypoint = value.assertString("container entrypoint");
|
|
break;
|
|
case "command":
|
|
command = value.assertString("container command");
|
|
break;
|
|
default:
|
|
context.error(key, `Unexpected container item key: ${key.value}`);
|
|
}
|
|
}
|
|
|
|
if (!image) {
|
|
context.error(container, "Container image cannot be empty");
|
|
} else {
|
|
return {image, env, ports, volumes, options, entrypoint, command};
|
|
}
|
|
}
|
|
|
|
export function convertToJobServices(context: TemplateContext, services: TemplateToken): Container[] | undefined {
|
|
const serviceList: Container[] = [];
|
|
|
|
const mapping = services.assertMapping("services");
|
|
for (const service of mapping) {
|
|
service.key.assertString("service key");
|
|
const container = convertToServiceContainer(context, service.value);
|
|
if (container) {
|
|
serviceList.push(container);
|
|
}
|
|
}
|
|
return serviceList;
|
|
}
|
|
|
|
function convertToJobCredentials(context: TemplateContext, value: TemplateToken): Credential | undefined {
|
|
const mapping = value.assertMapping("credentials");
|
|
|
|
let username: StringToken | undefined;
|
|
let password: StringToken | undefined;
|
|
|
|
for (const item of mapping) {
|
|
const key = item.key.assertString("credentials item");
|
|
const value = item.value;
|
|
|
|
switch (key.value) {
|
|
case "username":
|
|
username = value.assertString("credentials username");
|
|
break;
|
|
case "password":
|
|
password = value.assertString("credentials password");
|
|
break;
|
|
default:
|
|
context.error(key, `credentials key ${key.value}`);
|
|
}
|
|
}
|
|
|
|
return {username, password};
|
|
}
|