UNPKG

cdk8s-plus-25

Version:

cdk8s+ is a software development framework that provides high level abstractions for authoring Kubernetes applications. cdk8s-plus-25 synthesizes Kubernetes manifests for Kubernetes 1.25.0

214 lines 31.5 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.DeploymentStrategy = exports.PercentOrAbsolute = exports.Deployment = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const cdk8s_1 = require("cdk8s"); const container = require("./container"); const k8s = require("./imports/k8s"); const service = require("./service"); const workload = require("./workload"); /** * * A Deployment provides declarative updates for Pods and ReplicaSets. * * You describe a desired state in a Deployment, and the Deployment Controller changes the actual * state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove * existing Deployments and adopt all their resources with new Deployments. * * > Note: Do not manage ReplicaSets owned by a Deployment. Consider opening an issue in the main Kubernetes repository if your use case is not covered below. * * Use Case * * The following are typical use cases for Deployments: * * - Create a Deployment to rollout a ReplicaSet. The ReplicaSet creates Pods in the background. * Check the status of the rollout to see if it succeeds or not. * - Declare the new state of the Pods by updating the PodTemplateSpec of the Deployment. * A new ReplicaSet is created and the Deployment manages moving the Pods from the old ReplicaSet to the new one at a controlled rate. * Each new ReplicaSet updates the revision of the Deployment. * - Rollback to an earlier Deployment revision if the current state of the Deployment is not stable. * Each rollback updates the revision of the Deployment. * - Scale up the Deployment to facilitate more load. * - Pause the Deployment to apply multiple fixes to its PodTemplateSpec and then resume it to start a new rollout. * - Use the status of the Deployment as an indicator that a rollout has stuck. * - Clean up older ReplicaSets that you don't need anymore. * **/ class Deployment extends workload.Workload { constructor(scope, id, props = {}) { super(scope, id, props); this.resourceType = 'deployments'; this.hasAutoscaler = false; this.apiObject = new k8s.KubeDeployment(this, 'Resource', { metadata: props.metadata, spec: cdk8s_1.Lazy.any({ produce: () => this._toKube() }), }); this.minReady = props.minReady ?? cdk8s_1.Duration.seconds(0); this.progressDeadline = props.progressDeadline ?? cdk8s_1.Duration.seconds(600); if (this.progressDeadline.toSeconds() <= this.minReady.toSeconds()) { throw new Error(`'progressDeadline' (${this.progressDeadline.toSeconds()}s) must be greater than 'minReady' (${this.minReady.toSeconds()}s)`); } this.replicas = props.replicas; this.strategy = props.strategy ?? DeploymentStrategy.rollingUpdate(); if (this.isolate) { this.connections.isolate(); } } /** * Expose a deployment via a service. * * This is equivalent to running `kubectl expose deployment <deployment-name>`. * * @param options Options to determine details of the service and port exposed. */ exposeViaService(options = {}) { const myPorts = container.extractContainerPorts(this); const myPortNumbers = myPorts.map(p => p.number); const ports = options.ports ?? myPorts.map(p => ({ port: p.number, targetPort: p.number, protocol: p.protocol, name: p.name, })); if (ports.length === 0) { throw new Error(`Unable to expose deployment ${this.name} via a service: ` + 'Deployment port cannot be determined.' + 'Either pass \'ports\', or configure ports on the containers of the deployment'); } const portNames = ports.map(p => p.name); if (ports.length > 1 && portNames.includes(undefined)) { throw new Error(`Unable to expose deployment ${this.name} via a service: ` + 'When using multiple ports for a service, all ports must have port names so they are unambiguous.'); } // validate the ports are owned by our containers for (const port of ports) { const targetPort = port.targetPort ?? port.port; if (!myPortNumbers.includes(targetPort)) { throw new Error(`Unable to expose deployment ${this.name} via a service: Port ${targetPort} is not exposed by any container`); } } const metadata = { namespace: this.metadata.namespace }; if (options.name) { metadata.name = options.name; } return new service.Service(this, `${options.name ?? ''}Service`, { selector: this, ports, metadata, type: options.serviceType ?? service.ServiceType.CLUSTER_IP, }); } /** * Expose a deployment via an ingress. * * This will first expose the deployment with a service, and then expose the service via an ingress. * * @param path The ingress path to register under. * @param options Additional options. */ exposeViaIngress(path, options = {}) { const ser = this.exposeViaService(options); return ser.exposeViaIngress(path, options); } /** * @internal */ _toKube() { return { replicas: this.hasAutoscaler ? undefined : (this.replicas ?? 2), minReadySeconds: this.minReady.toSeconds(), progressDeadlineSeconds: this.progressDeadline.toSeconds(), template: { metadata: this.podMetadata.toJson(), spec: this._toPodSpec(), }, selector: this._toLabelSelector(), strategy: this.strategy._toKube(), }; } /** * @see IScalable.markHasAutoscaler() */ markHasAutoscaler() { this.hasAutoscaler = true; } /** * @see IScalable.toScalingTarget() */ toScalingTarget() { return { kind: this.apiObject.kind, apiVersion: this.apiObject.apiVersion, name: this.name, containers: this.containers, replicas: this.replicas, }; } } exports.Deployment = Deployment; _a = JSII_RTTI_SYMBOL_1; Deployment[_a] = { fqn: "cdk8s-plus-25.Deployment", version: "2.22.79" }; /** * Union like class repsenting either a ration in * percents or an absolute number. */ class PercentOrAbsolute { constructor(value) { this.value = value; } /** * Percent ratio. */ static percent(percent) { return new PercentOrAbsolute(`${percent}%`); } /** * Absolute number. */ static absolute(num) { return new PercentOrAbsolute(num); } isZero() { return this.value === PercentOrAbsolute.absolute(0).value || this.value === PercentOrAbsolute.percent(0).value; } } exports.PercentOrAbsolute = PercentOrAbsolute; _b = JSII_RTTI_SYMBOL_1; PercentOrAbsolute[_b] = { fqn: "cdk8s-plus-25.PercentOrAbsolute", version: "2.22.79" }; /** * Deployment strategies. */ class DeploymentStrategy { constructor(strategy) { this.strategy = strategy; } /** * All existing Pods are killed before new ones are created. * * @see https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#recreate-deployment */ static recreate() { return new DeploymentStrategy({ type: 'Recreate', }); } static rollingUpdate(options = {}) { const maxSurge = options.maxSurge ?? PercentOrAbsolute.percent(25); const maxUnavailable = options.maxUnavailable ?? PercentOrAbsolute.percent(25); if (maxSurge.isZero() && maxUnavailable.isZero()) { throw new Error('\'maxSurge\' and \'maxUnavailable\' cannot be both zero'); } return new DeploymentStrategy({ type: 'RollingUpdate', rollingUpdate: { maxSurge, maxUnavailable }, }); } /** * @internal */ _toKube() { return this.strategy; } } exports.DeploymentStrategy = DeploymentStrategy; _c = JSII_RTTI_SYMBOL_1; DeploymentStrategy[_c] = { fqn: "cdk8s-plus-25.DeploymentStrategy", version: "2.22.79" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBsb3ltZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaUNBQWtEO0FBRWxELHlDQUF5QztBQUV6QyxxQ0FBcUM7QUFFckMscUNBQXFDO0FBQ3JDLHVDQUF1QztBQWdGdkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMEJHO0FBQ0gsTUFBYSxVQUFXLFNBQVEsUUFBUSxDQUFDLFFBQVE7SUFnQy9DLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsUUFBeUIsRUFBRTtRQUNuRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUxWLGlCQUFZLEdBQUcsYUFBYSxDQUFDO1FBRXRDLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBSzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDeEQsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO1lBQ3hCLElBQUksRUFBRSxZQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1NBQ2xELENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsSUFBSSxnQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixJQUFJLGdCQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXhFLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDbEUsTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsSUFB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RUQsT0FBTyxJQUFJLGtCQUFrQixDQUFDO1lBQzVCLElBQUksRUFBRSxlQUFlO1lBQ3JCLGFBQWEsRUFBRSxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUU7U0FDNUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUlEOztPQUVHO0lBQ0ksT0FBTztRQUNaLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QixDQUFDOztBQW5DSCxnREFxQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBcGlPYmplY3QsIExhenksIER1cmF0aW9uIH0gZnJvbSAnY2RrOHMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgKiBhcyBjb250YWluZXIgZnJvbSAnLi9jb250YWluZXInO1xuaW1wb3J0IHsgSVNjYWxhYmxlLCBTY2FsaW5nVGFyZ2V0IH0gZnJvbSAnLi9ob3Jpem9udGFsLXBvZC1hdXRvc2NhbGVyJztcbmltcG9ydCAqIGFzIGs4cyBmcm9tICcuL2ltcG9ydHMvazhzJztcbmltcG9ydCAqIGFzIGluZ3Jlc3MgZnJvbSAnLi9pbmdyZXNzJztcbmltcG9ydCAqIGFzIHNlcnZpY2UgZnJvbSAnLi9zZXJ2aWNlJztcbmltcG9ydCAqIGFzIHdvcmtsb2FkIGZyb20gJy4vd29ya2xvYWQnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGBEZXBsb3ltZW50YC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBsb3ltZW50UHJvcHMgZXh0ZW5kcyB3b3JrbG9hZC5Xb3JrbG9hZFByb3BzIHtcblxuICAvKipcbiAgICogTnVtYmVyIG9mIGRlc2lyZWQgcG9kcy5cbiAgICpcbiAgICogQGRlZmF1bHQgMlxuICAgKi9cbiAgcmVhZG9ubHkgcmVwbGljYXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgc3RyYXRlZ3kgdXNlZCB0byByZXBsYWNlIG9sZCBQb2RzIGJ5IG5ldyBvbmVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFJvbGxpbmdVcGRhdGUgd2l0aCBtYXhTdXJnZSBhbmQgbWF4VW5hdmFpbGFibGUgc2V0IHRvIDI1JS5cbiAgICovXG4gIHJlYWRvbmx5IHN0cmF0ZWd5PzogRGVwbG95bWVudFN0cmF0ZWd5O1xuXG4gIC8qKlxuICAgKiBNaW5pbXVtIGR1cmF0aW9uIGZvciB3aGljaCBhIG5ld2x5IGNyZWF0ZWQgcG9kIHNob3VsZCBiZSByZWFkeSB3aXRob3V0XG4gICAqIGFueSBvZiBpdHMgY29udGFpbmVyIGNyYXNoaW5nLCBmb3IgaXQgdG8gYmUgY29uc2lkZXJlZCBhdmFpbGFibGUuXG4gICAqXG4gICAqIFplcm8gbWVhbnMgdGhlIHBvZCB3aWxsIGJlIGNvbnNpZGVyZWQgYXZhaWxhYmxlIGFzIHNvb24gYXMgaXQgaXMgcmVhZHkuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvd29ya2xvYWRzL2NvbnRyb2xsZXJzL2RlcGxveW1lbnQvI21pbi1yZWFkeS1zZWNvbmRzXG4gICAqIEBkZWZhdWx0IER1cmF0aW9uLnNlY29uZHMoMClcbiAgICovXG4gIHJlYWRvbmx5IG1pblJlYWR5PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIGR1cmF0aW9uIGZvciBhIGRlcGxveW1lbnQgdG8gbWFrZSBwcm9ncmVzcyBiZWZvcmUgaXRcbiAgICogaXMgY29uc2lkZXJlZCB0byBiZSBmYWlsZWQuIFRoZSBkZXBsb3ltZW50IGNvbnRyb2xsZXIgd2lsbCBjb250aW51ZVxuICAgKiB0byBwcm9jZXNzIGZhaWxlZCBkZXBsb3ltZW50cyBhbmQgYSBjb25kaXRpb24gd2l0aCBhIFByb2dyZXNzRGVhZGxpbmVFeGNlZWRlZFxuICAgKiByZWFzb24gd2lsbCBiZSBzdXJmYWNlZCBpbiB0aGUgZGVwbG95bWVudCBzdGF0dXMuXG4gICAqXG4gICAqIE5vdGUgdGhhdCBwcm9ncmVzcyB3aWxsIG5vdCBiZSBlc3RpbWF0ZWQgZHVyaW5nIHRoZSB0aW1lIGEgZGVwbG95bWVudCBpcyBwYXVzZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvd29ya2xvYWRzL2NvbnRyb2xsZXJzL2RlcGxveW1lbnQvI3Byb2dyZXNzLWRlYWRsaW5lLXNlY29uZHNcbiAgICogQGRlZmF1bHQgRHVyYXRpb24uc2Vjb25kcyg2MDApXG4gICAqL1xuICByZWFkb25seSBwcm9ncmVzc0RlYWRsaW5lPzogRHVyYXRpb247XG5cbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgRGVwbG95bWVudC5leHBvc2VWaWFTZXJ2aWNlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBsb3ltZW50RXhwb3NlVmlhU2VydmljZU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHBvcnRzIHRoYXQgdGhlIHNlcnZpY2Ugc2hvdWxkIGJpbmQgdG8uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZXh0cmFjdGVkIGZyb20gdGhlIGRlcGxveW1lbnQuXG4gICAqL1xuICByZWFkb25seSBwb3J0cz86IHNlcnZpY2UuU2VydmljZVBvcnRbXTtcblxuICAvKipcbiAgICogVGhlIHR5cGUgb2YgdGhlIGV4cG9zZWQgc2VydmljZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBDbHVzdGVySVAuXG4gICAqL1xuICByZWFkb25seSBzZXJ2aWNlVHlwZT86IHNlcnZpY2UuU2VydmljZVR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBzZXJ2aWNlIHRvIGV4cG9zZS5cbiAgICogSWYgeW91J2QgbGlrZSB0byBleHBvc2UgdGhlIGRlcGxveW1lbnQgbXVsdGlwbGUgdGltZXMsXG4gICAqIHlvdSBtdXN0IGV4cGxpY2l0bHkgc2V0IGEgbmFtZSBzdGFydGluZyBmcm9tIHRoZSBzZWNvbmQgZXhwb3NlIGNhbGwuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYXV0byBnZW5lcmF0ZWQuXG4gICAqL1xuICByZWFkb25seSBuYW1lPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGV4cG9zaW5nIGEgZGVwbG95bWVudCB2aWEgYW4gaW5ncmVzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFeHBvc2VEZXBsb3ltZW50VmlhSW5ncmVzc09wdGlvbnMgZXh0ZW5kcyBEZXBsb3ltZW50RXhwb3NlVmlhU2VydmljZU9wdGlvbnMsIHNlcnZpY2UuRXhwb3NlU2VydmljZVZpYUluZ3Jlc3NPcHRpb25zIHt9XG5cbi8qKlxuKlxuKiBBIERlcGxveW1lbnQgcHJvdmlkZXMgZGVjbGFyYXRpdmUgdXBkYXRlcyBmb3IgUG9kcyBhbmQgUmVwbGljYVNldHMuXG4qXG4qIFlvdSBkZXNjcmliZSBhIGRlc2lyZWQgc3RhdGUgaW4gYSBEZXBsb3ltZW50LCBhbmQgdGhlIERlcGxveW1lbnQgQ29udHJvbGxlciBjaGFuZ2VzIHRoZSBhY3R1YWxcbiogc3RhdGUgdG8gdGhlIGRlc2lyZWQgc3RhdGUgYXQgYSBjb250cm9sbGVkIHJhdGUuIFlvdSBjYW4gZGVmaW5lIERlcGxveW1lbnRzIHRvIGNyZWF0ZSBuZXcgUmVwbGljYVNldHMsIG9yIHRvIHJlbW92ZVxuKiBleGlzdGluZyBEZXBsb3ltZW50cyBhbmQgYWRvcHQgYWxsIHRoZWlyIHJlc291cmNlcyB3aXRoIG5ldyBEZXBsb3ltZW50cy5cbipcbiogPiBOb3RlOiBEbyBub3QgbWFuYWdlIFJlcGxpY2FTZXRzIG93bmVkIGJ5IGEgRGVwbG95bWVudC4gQ29uc2lkZXIgb3BlbmluZyBhbiBpc3N1ZSBpbiB0aGUgbWFpbiBLdWJlcm5ldGVzIHJlcG9zaXRvcnkgaWYgeW91ciB1c2UgY2FzZSBpcyBub3QgY292ZXJlZCBiZWxvdy5cbipcbiogVXNlIENhc2VcbipcbiogVGhlIGZvbGxvd2luZyBhcmUgdHlwaWNhbCB1c2UgY2FzZXMgZm9yIERlcGxveW1lbnRzOlxuKlxuKiAtIENyZWF0ZSBhIERlcGxveW1lbnQgdG8gcm9sbG91dCBhIFJlcGxpY2FTZXQuIFRoZSBSZXBsaWNhU2V0IGNyZWF0ZXMgUG9kcyBpbiB0aGUgYmFja2dyb3VuZC5cbiogICBDaGVjayB0aGUgc3RhdHVzIG9mIHRoZSByb2xsb3V0IHRvIHNlZSBpZiBpdCBzdWNjZWVkcyBvciBub3QuXG4qIC0gRGVjbGFyZSB0aGUgbmV3IHN0YXRlIG9mIHRoZSBQb2RzIGJ5IHVwZGF0aW5nIHRoZSBQb2RUZW1wbGF0ZVNwZWMgb2YgdGhlIERlcGxveW1lbnQuXG4qICAgQSBuZXcgUmVwbGljYVNldCBpcyBjcmVhdGVkIGFuZCB0aGUgRGVwbG95bWVudCBtYW5hZ2VzIG1vdmluZyB0aGUgUG9kcyBmcm9tIHRoZSBvbGQgUmVwbGljYVNldCB0byB0aGUgbmV3IG9uZSBhdCBhIGNvbnRyb2xsZWQgcmF0ZS5cbiogICBFYWNoIG5ldyBSZXBsaWNhU2V0IHVwZGF0ZXMgdGhlIHJldmlzaW9uIG9mIHRoZSBEZXBsb3ltZW50LlxuKiAtIFJvbGxiYWNrIHRvIGFuIGVhcmxpZXIgRGVwbG95bWVudCByZXZpc2lvbiBpZiB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgRGVwbG95bWVudCBpcyBub3Qgc3RhYmxlLlxuKiAgIEVhY2ggcm9sbGJhY2sgdXBkYXRlcyB0aGUgcmV2aXNpb24gb2YgdGhlIERlcGxveW1lbnQuXG4qIC0gU2NhbGUgdXAgdGhlIERlcGxveW1lbnQgdG8gZmFjaWxpdGF0ZSBtb3JlIGxvYWQuXG4qIC0gUGF1c2UgdGhlIERlcGxveW1lbnQgdG8gYXBwbHkgbXVsdGlwbGUgZml4ZXMgdG8gaXRzIFBvZFRlbXBsYXRlU3BlYyBhbmQgdGhlbiByZXN1bWUgaXQgdG8gc3RhcnQgYSBuZXcgcm9sbG91dC5cbiogLSBVc2UgdGhlIHN0YXR1cyBvZiB0aGUgRGVwbG95bWVudCBhcyBhbiBpbmRpY2F0b3IgdGhhdCBhIHJvbGxvdXQgaGFzIHN0dWNrLlxuKiAtIENsZWFuIHVwIG9sZGVyIFJlcGxpY2FTZXRzIHRoYXQgeW91IGRvbid0IG5lZWQgYW55bW9yZS5cbipcbioqL1xuZXhwb3J0IGNsYXNzIERlcGxveW1lbnQgZXh0ZW5kcyB3b3JrbG9hZC5Xb3JrbG9hZCBpbXBsZW1lbnRzIElTY2FsYWJsZSB7XG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiBkZXNpcmVkIHBvZHMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcmVwbGljYXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE1pbmltdW0gZHVyYXRpb24gZm9yIHdoaWNoIGEgbmV3bHkgY3JlYXRlZCBwb2Qgc2hvdWxkIGJlIHJlYWR5IHdpdGhvdXRcbiAgICogYW55IG9mIGl0cyBjb250YWluZXIgY3Jhc2hpbmcsIGZvciBpdCB0byBiZSBjb25zaWRlcmVkIGF2YWlsYWJsZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBtaW5SZWFkeTogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIGR1cmF0aW9uIGZvciBhIGRlcGxveW1lbnQgdG8gbWFrZSBwcm9ncmVzcyBiZWZvcmUgaXQgaXMgY29uc2lkZXJlZCB0byBiZSBmYWlsZWQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcHJvZ3Jlc3NEZWFkbGluZTogRHVyYXRpb247XG5cbiAgLypcbiAgICogVGhlIHVwZ3JhZGUgc3RyYXRlZ3kgb2YgdGhpcyBkZXBsb3ltZW50LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHN0cmF0ZWd5OiBEZXBsb3ltZW50U3RyYXRlZ3k7XG5cbiAgLyoqXG4gICAqIEBzZWUgYmFzZS5SZXNvdXJjZS5hcGlPYmplY3RcbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSBhcGlPYmplY3Q6IEFwaU9iamVjdDtcblxuICBwdWJsaWMgcmVhZG9ubHkgcmVzb3VyY2VUeXBlID0gJ2RlcGxveW1lbnRzJztcblxuICBwdWJsaWMgaGFzQXV0b3NjYWxlciA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBEZXBsb3ltZW50UHJvcHMgPSB7fSkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuXG4gICAgdGhpcy5hcGlPYmplY3QgPSBuZXcgazhzLkt1YmVEZXBsb3ltZW50KHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIG1ldGFkYXRhOiBwcm9wcy5tZXRhZGF0YSxcbiAgICAgIHNwZWM6IExhenkuYW55KHsgcHJvZHVjZTogKCkgPT4gdGhpcy5fdG9LdWJlKCkgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLm1pblJlYWR5ID0gcHJvcHMubWluUmVhZHkgPz8gRHVyYXRpb24uc2Vjb25kcygwKTtcbiAgICB0aGlzLnByb2dyZXNzRGVhZGxpbmUgPSBwcm9wcy5wcm9ncmVzc0RlYWRsaW5lID8/IER1cmF0aW9uLnNlY29uZHMoNjAwKTtcblxuICAgIGlmICh0aGlzLnByb2dyZXNzRGVhZGxpbmUudG9TZWNvbmRzKCkgPD0gdGhpcy5taW5SZWFkeS50b1NlY29uZHMoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAncHJvZ3Jlc3NEZWFkbGluZScgKCR7dGhpcy5wcm9ncmVzc0RlYWRsaW5lLnRvU2Vjb25kcygpfXMpIG11c3QgYmUgZ3JlYXRlciB0aGFuICdtaW5SZWFkeScgKCR7dGhpcy5taW5SZWFkeS50b1NlY29uZHMoKX1zKWApO1xuICAgIH1cblxuICAgIHRoaXMucmVwbGljYXMgPSBwcm9wcy5yZXBsaWNhcztcbiAgICB0aGlzLnN0cmF0ZWd5ID0gcHJvcHMuc3RyYXRlZ3kgPz8gRGVwbG95bWVudFN0cmF0ZWd5LnJvbGxpbmdVcGRhdGUoKTtcblxuICAgIGlmICh0aGlzLmlzb2xhdGUpIHtcbiAgICAgIHRoaXMuY29ubmVjdGlvbnMuaXNvbGF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBvc2UgYSBkZXBsb3ltZW50IHZpYSBhIHNlcnZpY2UuXG4gICAqXG4gICAqIFRoaXMgaXMgZXF1aXZhbGVudCB0byBydW5uaW5nIGBrdWJlY3RsIGV4cG9zZSBkZXBsb3ltZW50IDxkZXBsb3ltZW50LW5hbWU+YC5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyB0byBkZXRlcm1pbmUgZGV0YWlscyBvZiB0aGUgc2VydmljZSBhbmQgcG9ydCBleHBvc2VkLlxuICAgKi9cbiAgcHVibGljIGV4cG9zZVZpYVNlcnZpY2Uob3B0aW9uczogRGVwbG95bWVudEV4cG9zZVZpYVNlcnZpY2VPcHRpb25zID0ge30pOiBzZXJ2aWNlLlNlcnZpY2Uge1xuICAgIGNvbnN0IG15UG9ydHMgPSBjb250YWluZXIuZXh0cmFjdENvbnRhaW5lclBvcnRzKHRoaXMpO1xuICAgIGNvbnN0IG15UG9ydE51bWJlcnMgPSBteVBvcnRzLm1hcChwID0+IHAubnVtYmVyKTtcbiAgICBjb25zdCBwb3J0czogc2VydmljZS5TZXJ2aWNlUG9ydFtdID0gb3B0aW9ucy5wb3J0cyA/PyBteVBvcnRzLm1hcChwID0+ICh7XG4gICAgICBwb3J0OiBwLm51bWJlciwgdGFyZ2V0UG9ydDogcC5udW1iZXIsIHByb3RvY29sOiBwLnByb3RvY29sLCBuYW1lOiBwLm5hbWUsXG4gICAgfSkpO1xuICAgIGlmIChwb3J0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGV4cG9zZSBkZXBsb3ltZW50ICR7dGhpcy5uYW1lfSB2aWEgYSBzZXJ2aWNlOiBgXG4gICAgICAgICsgJ0RlcGxveW1lbnQgcG9ydCBjYW5ub3QgYmUgZGV0ZXJtaW5lZC4nXG4gICAgICAgICsgJ0VpdGhlciBwYXNzIFxcJ3BvcnRzXFwnLCBvciBjb25maWd1cmUgcG9ydHMgb24gdGhlIGNvbnRhaW5lcnMgb2YgdGhlIGRlcGxveW1lbnQnKTtcbiAgICB9XG4gICAgY29uc3QgcG9ydE5hbWVzID0gcG9ydHMubWFwKHAgPT4gcC5uYW1lKTtcbiAgICBpZiAocG9ydHMubGVuZ3RoID4gMSAmJiBwb3J0TmFtZXMuaW5jbHVkZXModW5kZWZpbmVkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZXhwb3NlIGRlcGxveW1lbnQgJHt0aGlzLm5hbWV9IHZpYSBhIHNlcnZpY2U6IGBcbiAgICAgICAgKyAnV2hlbiB1c2luZyBtdWx0aXBsZSBwb3J0cyBmb3IgYSBzZXJ2aWNlLCBhbGwgcG9ydHMgbXVzdCBoYXZlIHBvcnQgbmFtZXMgc28gdGhleSBhcmUgdW5hbWJpZ3VvdXMuJyk7XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgdGhlIHBvcnRzIGFyZSBvd25lZCBieSBvdXIgY29udGFpbmVyc1xuICAgIGZvciAoY29uc3QgcG9ydCBvZiBwb3J0cykge1xuICAgICAgY29uc3QgdGFyZ2V0UG9ydCA9IHBvcnQudGFyZ2V0UG9ydCA/PyBwb3J0LnBvcnQ7XG4gICAgICBpZiAoIW15UG9ydE51bWJlcnMuaW5jbHVkZXModGFyZ2V0UG9ydCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZXhwb3NlIGRlcGxveW1lbnQgJHt0aGlzLm5hbWV9IHZpYSBhIHNlcnZpY2U6IFBvcnQgJHt0YXJnZXRQb3J0fSBpcyBub3QgZXhwb3NlZCBieSBhbnkgY29udGFpbmVyYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWV0YWRhdGE6IGFueSA9IHsgbmFtZXNwYWNlOiB0aGlzLm1ldGFkYXRhLm5hbWVzcGFjZSB9O1xuICAgIGlmIChvcHRpb25zLm5hbWUpIHtcbiAgICAgIG1ldGFkYXRhLm5hbWUgPSBvcHRpb25zLm5hbWU7XG4gICAgfVxuICAgIHJldHVybiBuZXcgc2VydmljZS5TZXJ2aWNlKHRoaXMsIGAke29wdGlvbnMubmFtZSA/PyAnJ31TZXJ2aWNlYCwge1xuICAgICAgc2VsZWN0b3I6IHRoaXMsXG4gICAgICBwb3J0cyxcbiAgICAgIG1ldGFkYXRhLFxuICAgICAgdHlwZTogb3B0aW9ucy5zZXJ2aWNlVHlwZSA/PyBzZXJ2aWNlLlNlcnZpY2VUeXBlLkNMVVNURVJfSVAsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRXhwb3NlIGEgZGVwbG95bWVudCB2aWEgYW4gaW5ncmVzcy5cbiAgICpcbiAgICogVGhpcyB3aWxsIGZpcnN0IGV4cG9zZSB0aGUgZGVwbG95bWVudCB3aXRoIGEgc2VydmljZSwgYW5kIHRoZW4gZXhwb3NlIHRoZSBzZXJ2aWNlIHZpYSBhbiBpbmdyZXNzLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBUaGUgaW5ncmVzcyBwYXRoIHRvIHJlZ2lzdGVyIHVuZGVyLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBBZGRpdGlvbmFsIG9wdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgZXhwb3NlVmlhSW5ncmVzcyhwYXRoOiBzdHJpbmcsIG9wdGlvbnM6IEV4cG9zZURlcGxveW1lbnRWaWFJbmdyZXNzT3B0aW9ucyA9IHt9KTogaW5ncmVzcy5JbmdyZXNzIHtcbiAgICBjb25zdCBzZXIgPSB0aGlzLmV4cG9zZVZpYVNlcnZpY2Uob3B0aW9ucyk7XG4gICAgcmV0dXJuIHNlci5leHBvc2VWaWFJbmdyZXNzKHBhdGgsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF90b0t1YmUoKTogazhzLkRlcGxveW1lbnRTcGVjIHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVwbGljYXM6IHRoaXMuaGFzQXV0b3NjYWxlciA/IHVuZGVmaW5lZCA6ICh0aGlzLnJlcGxpY2FzID8/IDIpLFxuICAgICAgbWluUmVhZHlTZWNvbmRzOiB0aGlzLm1pblJlYWR5LnRvU2Vjb25kcygpLFxuICAgICAgcHJvZ3Jlc3NEZWFkbGluZVNlY29uZHM6IHRoaXMucHJvZ3Jlc3NEZWFkbGluZS50b1NlY29uZHMoKSxcbiAgICAgIHRlbXBsYXRlOiB7XG4gICAgICAgIG1ldGFkYXRhOiB0aGlzLnBvZE1ldGFkYXRhLnRvSnNvbigpLFxuICAgICAgICBzcGVjOiB0aGlzLl90b1BvZFNwZWMoKSxcbiAgICAgIH0sXG4gICAgICBzZWxlY3RvcjogdGhpcy5fdG9MYWJlbFNlbGVjdG9yKCksXG4gICAgICBzdHJhdGVneTogdGhpcy5zdHJhdGVneS5fdG9LdWJlKCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc2VlIElTY2FsYWJsZS5tYXJrSGFzQXV0b3NjYWxlcigpXG4gICAqL1xuICBwdWJsaWMgbWFya0hhc0F1dG9zY2FsZXIoKSB7XG4gICAgdGhpcy5oYXNBdXRvc2NhbGVyID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc2VlIElTY2FsYWJsZS50b1NjYWxpbmdUYXJnZXQoKVxuICAgKi9cbiAgcHVibGljIHRvU2NhbGluZ1RhcmdldCgpOiBTY2FsaW5nVGFyZ2V0IHtcbiAgICByZXR1cm4ge1xuICAgICAga2luZDogdGhpcy5hcGlPYmplY3Qua2luZCxcbiAgICAgIGFwaVZlcnNpb246IHRoaXMuYXBpT2JqZWN0LmFwaVZlcnNpb24sXG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBjb250YWluZXJzOiB0aGlzLmNvbnRhaW5lcnMsXG4gICAgICByZXBsaWNhczogdGhpcy5yZXBsaWNhcyxcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYERlcGxveW1lbnRTdHJhdGVneS5yb2xsaW5nVXBkYXRlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXBsb3ltZW50U3RyYXRlZ3lSb2xsaW5nVXBkYXRlT3B0aW9ucyB7XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBwb2RzIHRoYXQgY2FuIGJlIHNjaGVkdWxlZCBhYm92ZSB0aGUgZGVzaXJlZCBudW1iZXIgb2YgcG9kcy5cbiAgICogVmFsdWUgY2FuIGJlIGFuIGFic29sdXRlIG51bWJlciAoZXg6IDUpIG9yIGEgcGVyY2VudGFnZSBvZiBkZXNpcmVkIHBvZHMgKGV4OiAxMCUpLlxuICAgKiBBYnNvbHV0ZSBudW1iZXIgaXMgY2FsY3VsYXRlZCBmcm9tIHBlcmNlbnRhZ2UgYnkgcm91bmRpbmcgdXAuXG4gICAqIFRoaXMgY2FuIG5vdCBiZSAwIGlmIGBtYXhVbmF2YWlsYWJsZWAgaXMgMC5cbiAgICpcbiAgICogRXhhbXBsZTogd2hlbiB0aGlzIGlzIHNldCB0byAzMCUsIHRoZSBuZXcgUmVwbGljYVNldCBjYW4gYmUgc2NhbGVkIHVwIGltbWVkaWF0ZWx5IHdoZW4gdGhlIHJvbGxpbmcgdXBkYXRlXG4gICAqIHN0YXJ0cywgc3VjaCB0aGF0IHRoZSB0b3RhbCBudW1iZXIgb2Ygb2xkIGFuZCBuZXcgcG9kcyBkbyBub3QgZXhjZWVkIDEzMCUgb2YgZGVzaXJlZCBwb2RzLlxuICAgKiBPbmNlIG9sZCBwb2RzIGhhdmUgYmVlbiBraWxsZWQsIG5ldyBSZXBsaWNhU2V0IGNhbiBiZSBzY2FsZWQgdXAgZnVydGhlciwgZW5zdXJpbmcgdGhhdFxuICAgKiB0b3RhbCBudW1iZXIgb2YgcG9kcyBydW5uaW5nIGF0IGFueSB0aW1lIGR1cmluZyB0aGUgdXBkYXRlIGlzIGF0IG1vc3QgMTMwJSBvZiBkZXNpcmVkIHBvZHMuXG4gICAqXG4gICAqIEBkZWZhdWx0ICcyNSUnXG4gICAqL1xuICByZWFkb25seSBtYXhTdXJnZT86IFBlcmNlbnRPckFic29sdXRlO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgcG9kcyB0aGF0IGNhbiBiZSB1bmF2YWlsYWJsZSBkdXJpbmcgdGhlIHVwZGF0ZS5cbiAgICogVmFsdWUgY2FuIGJlIGFuIGFic29sdXRlIG51bWJlciAoZXg6IDUpIG9yIGEgcGVyY2VudGFnZSBvZiBkZXNpcmVkIHBvZHMgKGV4OiAxMCUpLlxuICAgKiBBYnNvbHV0ZSBudW1iZXIgaXMgY2FsY3VsYXRlZCBmcm9tIHBlcmNlbnRhZ2UgYnkgcm91bmRpbmcgZG93bi5cbiAgICogVGhpcyBjYW4gbm90IGJlIDAgaWYgYG1heFN1cmdlYCBpcyAwLlxuICAgKlxuICAgKiBFeGFtcGxlOiB3aGVuIHRoaXMgaXMgc2V0IHRvIDMwJSwgdGhlIG9sZCBSZXBsaWNhU2V0IGNhbiBiZSBzY2FsZWQgZG93biB0byA3MCUgb2YgZGVzaXJlZFxuICAgKiBwb2RzIGltbWVkaWF0ZWx5IHdoZW4gdGhlIHJvbGxpbmcgdXBkYXRlIHN0YXJ0cy4gT25jZSBuZXcgcG9kcyBhcmUgcmVhZHksIG9sZCBSZXBsaWNhU2V0IGNhblxuICAgKiBiZSBzY2FsZWQgZG93biBmdXJ0aGVyLCBmb2xsb3dlZCBieSBzY2FsaW5nIHVwIHRoZSBuZXcgUmVwbGljYVNldCwgZW5zdXJpbmcgdGhhdCB0aGUgdG90YWxcbiAgICogbnVtYmVyIG9mIHBvZHMgYXZhaWxhYmxlIGF0IGFsbCB0aW1lcyBkdXJpbmcgdGhlIHVwZGF0ZSBpcyBhdCBsZWFzdCA3MCUgb2YgZGVzaXJlZCBwb2RzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnMjUlJ1xuICAgKi9cbiAgcmVhZG9ubHkgbWF4VW5hdmFpbGFibGU/OiBQZXJjZW50T3JBYnNvbHV0ZTtcblxufVxuXG4vKipcbiAqIFVuaW9uIGxpa2UgY2xhc3MgcmVwc2VudGluZyBlaXRoZXIgYSByYXRpb24gaW5cbiAqIHBlcmNlbnRzIG9yIGFuIGFic29sdXRlIG51bWJlci5cbiAqL1xuZXhwb3J0IGNsYXNzIFBlcmNlbnRPckFic29sdXRlIHtcblxuICAvKipcbiAgICogUGVyY2VudCByYXRpby5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcGVyY2VudChwZXJjZW50OiBudW1iZXIpOiBQZXJjZW50T3JBYnNvbHV0ZSB7XG4gICAgcmV0dXJuIG5ldyBQZXJjZW50T3JBYnNvbHV0ZShgJHtwZXJjZW50fSVgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBYnNvbHV0ZSBudW1iZXIuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFic29sdXRlKG51bTogbnVtYmVyKTogUGVyY2VudE9yQWJzb2x1dGUge1xuICAgIHJldHVybiBuZXcgUGVyY2VudE9yQWJzb2x1dGUobnVtKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHZhbHVlOiBhbnkpIHt9XG5cbiAgcHVibGljIGlzWmVybygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZSA9PT0gUGVyY2VudE9yQWJzb2x1dGUuYWJzb2x1dGUoMCkudmFsdWUgfHwgdGhpcy52YWx1ZSA9PT0gUGVyY2VudE9yQWJzb2x1dGUucGVyY2VudCgwKS52YWx1ZTtcbiAgfVxuXG59XG5cbi8qKlxuICogRGVwbG95bWVudCBzdHJhdGVnaWVzLlxuICovXG5leHBvcnQgY2xhc3MgRGVwbG95bWVudFN0cmF0ZWd5IHtcblxuICAvKipcbiAgICogQWxsIGV4aXN0aW5nIFBvZHMgYXJlIGtpbGxlZCBiZWZvcmUgbmV3IG9uZXMgYXJlIGNyZWF0ZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvd29ya2xvYWRzL2NvbnRyb2xsZXJzL2RlcGxveW1lbnQvI3JlY3JlYXRlLWRlcGxveW1lbnRcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVjcmVhdGUoKTogRGVwbG95bWVudFN0cmF0ZWd5IHtcbiAgICByZXR1cm4gbmV3IERlcGxveW1lbnRTdHJhdGVneSh7XG4gICAgICB0eXBlOiAnUmVjcmVhdGUnLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyByb2xsaW5nVXBkYXRlKG9wdGlvbnM6IERlcGxveW1lbnRTdHJhdGVneVJvbGxpbmdVcGRhdGVPcHRpb25zID0ge30pOiBEZXBsb3ltZW50U3RyYXRlZ3kge1xuXG4gICAgY29uc3QgbWF4U3VyZ2UgPSBvcHRpb25zLm1heFN1cmdlID8/IFBlcmNlbnRPckFic29sdXRlLnBlcmNlbnQoMjUpO1xuICAgIGNvbnN0IG1heFVuYXZhaWxhYmxlID0gb3B0aW9ucy5tYXhVbmF2YWlsYWJsZSA/PyBQZXJjZW50T3JBYnNvbHV0ZS5wZXJjZW50KDI1KTtcblxuICAgIGlmIChtYXhTdXJnZS5pc1plcm8oKSAmJiBtYXhVbmF2YWlsYWJsZS5pc1plcm8oKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcXCdtYXhTdXJnZVxcJyBhbmQgXFwnbWF4VW5hdmFpbGFibGVcXCcgY2Fubm90IGJlIGJvdGggemVybycpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgRGVwbG95bWVudFN0cmF0ZWd5KHtcbiAgICAgIHR5cGU6ICdSb2xsaW5nVXBkYXRlJyxcbiAgICAgIHJvbGxpbmdVcGRhdGU6IHsgbWF4U3VyZ2UsIG1heFVuYXZhaWxhYmxlIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgc3RyYXRlZ3k6IGs4cy5EZXBsb3ltZW50U3RyYXRlZ3kpIHt9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF90b0t1YmUoKTogazhzLkRlcGxveW1lbnRTdHJhdGVneSB7XG4gICAgcmV0dXJuIHRoaXMuc3RyYXRlZ3k7XG4gIH1cblxufVxuIl19