UNPKG

@adpt/cloud

Version:
140 lines 5.51 kB
"use strict"; /* * Copyright 2019 Unbounded Systems, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const core_1 = tslib_1.__importStar(require("@adpt/core")); const Container_1 = require("../Container"); const NetworkService_1 = require("../NetworkService"); const DockerContainer_1 = require("./DockerContainer"); const NetworkService_2 = require("./NetworkService"); function mapContainer(absEl, spProps, helpers, portBindings) { const { containerProps = {} } = spProps; const _a = absEl.props, { handle: _h } = _a, absProps = tslib_1.__rest(_a, ["handle"]); const finalProps = Object.assign({}, absProps, containerProps, { key: absEl.props.key }); if (spProps.dockerHost) finalProps.dockerHost = spProps.dockerHost; // Add the port bindings from the NetworkServices if (portBindings) { finalProps.portBindings = Object.assign({}, (finalProps.portBindings || {}), portBindings); } const ctr = core_1.default.createElement(DockerContainer_1.DockerContainer, Object.assign({}, finalProps)); absEl.props.handle.replaceTarget(ctr, helpers); return ctr; } function mapNetworkService(absEl, _props, helpers) { const _a = absEl.props, { handle: _h } = _a, props = tslib_1.__rest(_a, ["handle"]); const svc = core_1.default.createElement(NetworkService_2.NetworkService, Object.assign({}, props)); absEl.props.handle.replaceTarget(svc, helpers); return svc; } /** * Record which NetworkService elements expose a service with external * scope and record the port binding associated with the endpoint element. * @internal */ function getPortBindings(elems) { const portMap = new Map(); const getPorts = (el) => { let ret = portMap.get(el); if (!ret) { ret = {}; portMap.set(el, ret); } return ret; }; const toPortNum = (p) => { const pNum = Number(p); if (isNaN(pNum) || !Number.isInteger(pNum) || pNum <= 0 || pNum >= 65536) { throw new Error(`Network service port ${p} is not a valid number`); } return pNum; }; for (const el of elems) { if (!NetworkService_1.isNetworkServiceElement(el) || el.props.scope !== "external") { continue; } const endpoint = el.props.endpoint && el.props.endpoint.target; if (!endpoint) continue; const ports = getPorts(endpoint); const proto = el.props.protocol || NetworkService_1.NetworkService.defaultProps.protocol; const ctrPort = el.props.targetPort || el.props.port; const hostPort = toPortNum(el.props.port); ports[`${ctrPort}/${proto.toLowerCase()}`] = hostPort; } return portMap; } /** * A component for mapping a group of abstract {@link Container}s and * {@link NetworkService}s to Docker {@link docker.DockerContainer | DockerContainer}s * and {@link docker.NetworkService}s. * * @remarks * This component is intended to be used to replace {@link Container} and * {@link NetworkService} components that are grouped together, as the * only children of a common parent in a pattern that looks like this: * ```tsx * <Service> * <Container ... /> * <Container ... /> * <NetworkService ... /> * </Service> * ``` * `ServiceContainerSet` maps those abstract components into Docker components * like this: * ```tsx * <Group> * <docker.DockerContainer ... > * <docker.DockerContainer ... > * <docker.NetworkService ... > * </Group> * ``` * An example style rule to do this is: * ```tsx * {Service} * {Adapt.rule((matchedProps) => { * const { handle, ...remainingProps } = matchedProps; * return <ServiceContainerSet {...remainingProps} />; * })} * ``` * * Currently, {@link docker.NetworkService} implements the {@link NetworkServiceInstance} * interface, but does not deploy a network proxy component. So the Docker * ServiceContainerSet component applies the network port configuration specified by * the {@link NetworkService}s to their target * {@link docker.DockerContainer | DockerContainer}s. * * @public */ class ServiceContainerSet extends core_1.DeferredComponent { build(helpers) { const children = core_1.childrenToArray(this.props.children); const portMap = getPortBindings(children); const mappedChildren = children.map((c) => { if (Container_1.isContainerElement(c)) { return mapContainer(c, this.props, helpers, portMap.get(c)); } if (NetworkService_1.isNetworkServiceElement(c)) { return mapNetworkService(c, this.props, helpers); } return c; }); return core_1.default.createElement(core_1.Group, { key: this.props.key }, mappedChildren); } } exports.ServiceContainerSet = ServiceContainerSet; //# sourceMappingURL=ServiceContainerSet.js.map