cdk8s-plus-31 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.backportrc.json +17 -0
  2. package/.jsii +90235 -0
  3. package/CODE_OF_CONDUCT.md +3 -0
  4. package/CONTRIBUTING.md +185 -0
  5. package/DCO +34 -0
  6. package/LICENSE +202 -0
  7. package/NOTICE +1 -0
  8. package/OWNERS.md +5 -0
  9. package/README.md +32 -0
  10. package/SECURITY.md +5 -0
  11. package/cdk8s.yaml +8 -0
  12. package/docs/java.md +23855 -0
  13. package/docs/plus/config-map.md +98 -0
  14. package/docs/plus/container.md +133 -0
  15. package/docs/plus/cronjob.md +67 -0
  16. package/docs/plus/deployment.md +232 -0
  17. package/docs/plus/horizontal-pod-autoscaler.md +226 -0
  18. package/docs/plus/ingress.md +68 -0
  19. package/docs/plus/job.md +48 -0
  20. package/docs/plus/namespace.md +58 -0
  21. package/docs/plus/network-policy.md +341 -0
  22. package/docs/plus/pod.md +455 -0
  23. package/docs/plus/pv.md +82 -0
  24. package/docs/plus/pvc.md +77 -0
  25. package/docs/plus/rbac.md +104 -0
  26. package/docs/plus/secret.md +32 -0
  27. package/docs/plus/service-account.md +35 -0
  28. package/docs/plus/service.md +41 -0
  29. package/docs/plus/volume.md +38 -0
  30. package/docs/python.md +26079 -0
  31. package/docs/typescript.md +19565 -0
  32. package/git-hooks/README.md +9 -0
  33. package/git-hooks/prepare-commit-msg +18 -0
  34. package/git-hooks/setup.sh +10 -0
  35. package/lib/_action.d.ts +21 -0
  36. package/lib/_action.js +32 -0
  37. package/lib/api-resource.d.ts +298 -0
  38. package/lib/api-resource.js +430 -0
  39. package/lib/base.d.ts +79 -0
  40. package/lib/base.js +92 -0
  41. package/lib/config-map.d.ts +126 -0
  42. package/lib/config-map.js +159 -0
  43. package/lib/container.d.ts +1057 -0
  44. package/lib/container.js +845 -0
  45. package/lib/cron-job.d.ts +138 -0
  46. package/lib/cron-job.js +103 -0
  47. package/lib/daemon-set.d.ts +45 -0
  48. package/lib/daemon-set.js +55 -0
  49. package/lib/deployment.d.ts +223 -0
  50. package/lib/deployment.js +214 -0
  51. package/lib/handler.d.ts +62 -0
  52. package/lib/handler.js +54 -0
  53. package/lib/horizontal-pod-autoscaler.d.ts +500 -0
  54. package/lib/horizontal-pod-autoscaler.js +569 -0
  55. package/lib/imports/k8s.d.ts +21534 -0
  56. package/lib/imports/k8s.js +16496 -0
  57. package/lib/index.d.ts +26 -0
  58. package/lib/index.js +39 -0
  59. package/lib/ingress.d.ts +230 -0
  60. package/lib/ingress.js +246 -0
  61. package/lib/job.d.ts +64 -0
  62. package/lib/job.js +54 -0
  63. package/lib/namespace.d.ts +128 -0
  64. package/lib/namespace.js +109 -0
  65. package/lib/network-policy.d.ts +311 -0
  66. package/lib/network-policy.js +344 -0
  67. package/lib/pod.d.ts +1080 -0
  68. package/lib/pod.js +1139 -0
  69. package/lib/probe.d.ts +141 -0
  70. package/lib/probe.js +77 -0
  71. package/lib/pv.d.ts +375 -0
  72. package/lib/pv.js +273 -0
  73. package/lib/pvc.d.ts +163 -0
  74. package/lib/pvc.js +152 -0
  75. package/lib/role-binding.d.ts +138 -0
  76. package/lib/role-binding.js +165 -0
  77. package/lib/role.d.ts +268 -0
  78. package/lib/role.js +401 -0
  79. package/lib/secret.d.ts +195 -0
  80. package/lib/secret.js +185 -0
  81. package/lib/service-account.d.ts +83 -0
  82. package/lib/service-account.js +105 -0
  83. package/lib/service.d.ts +289 -0
  84. package/lib/service.js +182 -0
  85. package/lib/stateful-set.d.ts +169 -0
  86. package/lib/stateful-set.js +174 -0
  87. package/lib/utils.d.ts +4 -0
  88. package/lib/utils.js +34 -0
  89. package/lib/volume.d.ts +573 -0
  90. package/lib/volume.js +371 -0
  91. package/lib/workload.d.ts +121 -0
  92. package/lib/workload.js +122 -0
  93. package/node_modules/balanced-match/.github/FUNDING.yml +2 -0
  94. package/node_modules/balanced-match/LICENSE.md +21 -0
  95. package/node_modules/balanced-match/README.md +97 -0
  96. package/node_modules/balanced-match/index.js +62 -0
  97. package/node_modules/balanced-match/package.json +48 -0
  98. package/node_modules/concat-map/.travis.yml +4 -0
  99. package/node_modules/concat-map/LICENSE +18 -0
  100. package/node_modules/concat-map/README.markdown +62 -0
  101. package/node_modules/concat-map/example/map.js +6 -0
  102. package/node_modules/concat-map/index.js +13 -0
  103. package/node_modules/concat-map/package.json +43 -0
  104. package/node_modules/concat-map/test/map.js +39 -0
  105. package/node_modules/minimatch/LICENSE +15 -0
  106. package/node_modules/minimatch/README.md +230 -0
  107. package/node_modules/minimatch/minimatch.js +947 -0
  108. package/node_modules/minimatch/node_modules/brace-expansion/LICENSE +21 -0
  109. package/node_modules/minimatch/node_modules/brace-expansion/README.md +129 -0
  110. package/node_modules/minimatch/node_modules/brace-expansion/index.js +201 -0
  111. package/node_modules/minimatch/node_modules/brace-expansion/package.json +47 -0
  112. package/node_modules/minimatch/package.json +33 -0
  113. package/package.json +186 -0
  114. package/rotate.md +84 -0
@@ -0,0 +1,126 @@
1
+ import { ApiObject } from 'cdk8s';
2
+ import { Construct } from 'constructs';
3
+ import * as base from './base';
4
+ /**
5
+ * Properties for initialization of `ConfigMap`.
6
+ */
7
+ export interface ConfigMapProps extends base.ResourceProps {
8
+ /**
9
+ * BinaryData contains the binary data.
10
+ *
11
+ * Each key must consist of alphanumeric characters, '-', '_' or '.'.
12
+ * BinaryData can contain byte sequences that are not in the UTF-8 range. The
13
+ * keys stored in BinaryData must not overlap with the ones in the Data field,
14
+ * this is enforced during validation process.
15
+ *
16
+ * You can also add binary data using `configMap.addBinaryData()`.
17
+ */
18
+ readonly binaryData?: {
19
+ [key: string]: string;
20
+ };
21
+ /**
22
+ * Data contains the configuration data.
23
+ *
24
+ * Each key must consist of alphanumeric characters, '-', '_' or '.'. Values
25
+ * with non-UTF-8 byte sequences must use the BinaryData field. The keys
26
+ * stored in Data must not overlap with the keys in the BinaryData field, this
27
+ * is enforced during validation process.
28
+ *
29
+ * You can also add data using `configMap.addData()`.
30
+ */
31
+ readonly data?: {
32
+ [key: string]: string;
33
+ };
34
+ /**
35
+ * If set to true, ensures that data stored in the ConfigMap cannot be updated (only object metadata can be modified).
36
+ * If not set to true, the field can be modified at any time.
37
+ *
38
+ * @default false
39
+ */
40
+ readonly immutable?: boolean;
41
+ }
42
+ /**
43
+ * Represents a config map.
44
+ */
45
+ export interface IConfigMap extends base.IResource {
46
+ }
47
+ /**
48
+ * ConfigMap holds configuration data for pods to consume.
49
+ */
50
+ export declare class ConfigMap extends base.Resource implements IConfigMap {
51
+ /**
52
+ * Represents a ConfigMap created elsewhere.
53
+ */
54
+ static fromConfigMapName(scope: Construct, id: string, name: string): IConfigMap;
55
+ /**
56
+ * @see base.Resource.apiObject
57
+ */
58
+ protected readonly apiObject: ApiObject;
59
+ readonly resourceType = "configmaps";
60
+ private readonly _binaryData;
61
+ private readonly _data;
62
+ /**
63
+ * Whether or not this config map is immutable.
64
+ */
65
+ readonly immutable: boolean;
66
+ constructor(scope: Construct, id: string, props?: ConfigMapProps);
67
+ /**
68
+ * Adds a data entry to the config map.
69
+ * @param key The key
70
+ * @param value The value
71
+ *
72
+ * @throws if there is either a `data` or `binaryData` entry with the same key
73
+ */
74
+ addData(key: string, value: string): void;
75
+ /**
76
+ * The data associated with this config map.
77
+ *
78
+ * Returns an copy. To add data records, use `addData()` or `addBinaryData()`.
79
+ */
80
+ get data(): Record<string, string>;
81
+ /**
82
+ * Adds a binary data entry to the config map. BinaryData can contain byte
83
+ * sequences that are not in the UTF-8 range.
84
+ * @param key The key
85
+ * @param value The value
86
+ *
87
+ * @throws if there is either a `data` or `binaryData` entry with the same key
88
+ */
89
+ addBinaryData(key: string, value: string): void;
90
+ /**
91
+ * The binary data associated with this config map.
92
+ *
93
+ * Returns a copy. To add data records, use `addBinaryData()` or `addData()`.
94
+ */
95
+ get binaryData(): Record<string, string>;
96
+ /**
97
+ * Adds a file to the ConfigMap.
98
+ * @param localFile The path to the local file
99
+ * @param key The ConfigMap key (default to the file name).
100
+ */
101
+ addFile(localFile: string, key?: string): void;
102
+ /**
103
+ * Adds a directory to the ConfigMap.
104
+ * @param localDir A path to a local directory
105
+ * @param options Options
106
+ */
107
+ addDirectory(localDir: string, options?: AddDirectoryOptions): void;
108
+ private verifyKeyAvailable;
109
+ private synthesizeData;
110
+ private synthesizeBinaryData;
111
+ }
112
+ /**
113
+ * Options for `configmap.addDirectory()`
114
+ */
115
+ export interface AddDirectoryOptions {
116
+ /**
117
+ * A prefix to add to all keys in the config map.
118
+ * @default ""
119
+ */
120
+ readonly keyPrefix?: string;
121
+ /**
122
+ * Glob patterns to exclude when adding files.
123
+ * @default - include all files
124
+ */
125
+ readonly exclude?: string[];
126
+ }
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ConfigMap = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ const configmap = require("fs");
7
+ const path = require("path");
8
+ const cdk8s_1 = require("cdk8s");
9
+ const constructs_1 = require("constructs");
10
+ const minimatch_1 = require("minimatch");
11
+ const base = require("./base");
12
+ const k8s = require("./imports/k8s");
13
+ const utils_1 = require("./utils");
14
+ class ImportedConfigMap extends constructs_1.Construct {
15
+ constructor(scope, id, name) {
16
+ super(scope, id);
17
+ this.resourceType = 'configmaps';
18
+ this._name = name;
19
+ }
20
+ get name() {
21
+ return this._name;
22
+ }
23
+ get apiVersion() {
24
+ return k8s.KubeConfigMap.GVK.apiVersion;
25
+ }
26
+ get apiGroup() {
27
+ return '';
28
+ }
29
+ get kind() {
30
+ return k8s.KubeConfigMap.GVK.kind;
31
+ }
32
+ get resourceName() {
33
+ return this.name;
34
+ }
35
+ }
36
+ /**
37
+ * ConfigMap holds configuration data for pods to consume.
38
+ */
39
+ class ConfigMap extends base.Resource {
40
+ constructor(scope, id, props = {}) {
41
+ super(scope, id);
42
+ this.resourceType = 'configmaps';
43
+ this._binaryData = {};
44
+ this._data = {};
45
+ this.immutable = props.immutable ?? false;
46
+ this.apiObject = new k8s.KubeConfigMap(this, 'Resource', {
47
+ metadata: props.metadata,
48
+ // we need lazy here because we filter empty
49
+ data: cdk8s_1.Lazy.any({ produce: () => this.synthesizeData() }),
50
+ binaryData: cdk8s_1.Lazy.any({ produce: () => this.synthesizeBinaryData() }),
51
+ immutable: this.immutable,
52
+ });
53
+ for (const [k, v] of Object.entries(props.data ?? {})) {
54
+ this.addData(k, v);
55
+ }
56
+ for (const [k, v] of Object.entries(props.binaryData ?? {})) {
57
+ this.addBinaryData(k, v);
58
+ }
59
+ }
60
+ /**
61
+ * Represents a ConfigMap created elsewhere.
62
+ */
63
+ static fromConfigMapName(scope, id, name) {
64
+ return new ImportedConfigMap(scope, id, name);
65
+ }
66
+ /**
67
+ * Adds a data entry to the config map.
68
+ * @param key The key
69
+ * @param value The value
70
+ *
71
+ * @throws if there is either a `data` or `binaryData` entry with the same key
72
+ */
73
+ addData(key, value) {
74
+ this.verifyKeyAvailable(key);
75
+ this._data[key] = value;
76
+ }
77
+ /**
78
+ * The data associated with this config map.
79
+ *
80
+ * Returns an copy. To add data records, use `addData()` or `addBinaryData()`.
81
+ */
82
+ get data() {
83
+ return { ...this._data };
84
+ }
85
+ /**
86
+ * Adds a binary data entry to the config map. BinaryData can contain byte
87
+ * sequences that are not in the UTF-8 range.
88
+ * @param key The key
89
+ * @param value The value
90
+ *
91
+ * @throws if there is either a `data` or `binaryData` entry with the same key
92
+ */
93
+ addBinaryData(key, value) {
94
+ this.verifyKeyAvailable(key);
95
+ this._binaryData[key] = value;
96
+ }
97
+ /**
98
+ * The binary data associated with this config map.
99
+ *
100
+ * Returns a copy. To add data records, use `addBinaryData()` or `addData()`.
101
+ */
102
+ get binaryData() {
103
+ return { ...this._binaryData };
104
+ }
105
+ /**
106
+ * Adds a file to the ConfigMap.
107
+ * @param localFile The path to the local file
108
+ * @param key The ConfigMap key (default to the file name).
109
+ */
110
+ addFile(localFile, key) {
111
+ key = key ?? path.basename(localFile);
112
+ const value = configmap.readFileSync(localFile, 'utf-8');
113
+ this.addData(key, value);
114
+ }
115
+ /**
116
+ * Adds a directory to the ConfigMap.
117
+ * @param localDir A path to a local directory
118
+ * @param options Options
119
+ */
120
+ addDirectory(localDir, options = {}) {
121
+ const exclude = options.exclude ?? [];
122
+ const shouldInclude = (file) => {
123
+ for (const pattern of exclude) {
124
+ const mm = new minimatch_1.Minimatch(pattern);
125
+ if (mm.match(file)) {
126
+ return false;
127
+ }
128
+ }
129
+ return true;
130
+ };
131
+ const keyPrefix = options.keyPrefix ?? '';
132
+ for (const file of configmap.readdirSync(localDir)) {
133
+ const filePath = path.join(localDir, file);
134
+ if (configmap.statSync(filePath).isDirectory()) {
135
+ continue;
136
+ }
137
+ if (!shouldInclude(file)) {
138
+ continue;
139
+ }
140
+ const relativeFilePath = keyPrefix + file;
141
+ this.addFile(filePath, relativeFilePath);
142
+ }
143
+ }
144
+ verifyKeyAvailable(key) {
145
+ if (key in this._data || key in this._binaryData) {
146
+ throw new Error(`unable to add a ConfigMap entry with key "${key}". It is already used`);
147
+ }
148
+ }
149
+ synthesizeData() {
150
+ return utils_1.undefinedIfEmpty(this._data);
151
+ }
152
+ synthesizeBinaryData() {
153
+ return utils_1.undefinedIfEmpty(this._binaryData);
154
+ }
155
+ }
156
+ exports.ConfigMap = ConfigMap;
157
+ _a = JSII_RTTI_SYMBOL_1;
158
+ ConfigMap[_a] = { fqn: "cdk8s-plus-31.ConfigMap", version: "2.0.0" };
159
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLW1hcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25maWctbWFwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsZ0NBQWdDO0FBQ2hDLDZCQUE2QjtBQUM3QixpQ0FBd0M7QUFDeEMsMkNBQXVDO0FBQ3ZDLHlDQUFzQztBQUN0QywrQkFBK0I7QUFDL0IscUNBQXFDO0FBQ3JDLG1DQUEyQztBQStDM0MsTUFBTSxpQkFBa0IsU0FBUSxzQkFBUztJQU12QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLElBQVk7UUFDcEQsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUhILGlCQUFZLEdBQUcsWUFBWSxDQUFDO1FBSTFDLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxJQUFXLElBQUk7UUFDYixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVELElBQVcsVUFBVTtRQUNuQixPQUFPLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQztJQUMxQyxDQUFDO0lBRUQsSUFBVyxRQUFRO1FBQ2pCLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELElBQVcsSUFBSTtRQUNiLE9BQU8sR0FBRyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxJQUFXLFlBQVk7UUFDckIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ25CLENBQUM7Q0FFRjtBQUVEOztHQUVHO0FBQ0gsTUFBYSxTQUFVLFNBQVEsSUFBSSxDQUFDLFFBQVE7SUF3QjFDLFlBQW1CLEtBQWdCLEVBQUUsRUFBVSxFQUFFLFFBQXdCLEVBQUc7UUFDMUUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQVhILGlCQUFZLEdBQUcsWUFBWSxDQUFDO1FBRTNCLGdCQUFXLEdBQThCLEVBQUcsQ0FB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cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY29uZmlnbWFwIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBBcGlPYmplY3QsIExhenkgfSBmcm9tICdjZGs4cyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IE1pbmltYXRjaCB9IGZyb20gJ21pbmltYXRjaCc7XG5pbXBvcnQgKiBhcyBiYXNlIGZyb20gJy4vYmFzZSc7XG5pbXBvcnQgKiBhcyBrOHMgZnJvbSAnLi9pbXBvcnRzL2s4cyc7XG5pbXBvcnQgeyB1bmRlZmluZWRJZkVtcHR5IH0gZnJvbSAnLi91dGlscyc7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgaW5pdGlhbGl6YXRpb24gb2YgYENvbmZpZ01hcGAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29uZmlnTWFwUHJvcHMgZXh0ZW5kcyBiYXNlLlJlc291cmNlUHJvcHMge1xuICAvKipcbiAgICogQmluYXJ5RGF0YSBjb250YWlucyB0aGUgYmluYXJ5IGRhdGEuXG4gICAqXG4gICAqIEVhY2gga2V5IG11c3QgY29uc2lzdCBvZiBhbHBoYW51bWVyaWMgY2hhcmFjdGVycywgJy0nLCAnXycgb3IgJy4nLlxuICAgKiBCaW5hcnlEYXRhIGNhbiBjb250YWluIGJ5dGUgc2VxdWVuY2VzIHRoYXQgYXJlIG5vdCBpbiB0aGUgVVRGLTggcmFuZ2UuIFRoZVxuICAgKiBrZXlzIHN0b3JlZCBpbiBCaW5hcnlEYXRhIG11c3Qgbm90IG92ZXJsYXAgd2l0aCB0aGUgb25lcyBpbiB0aGUgRGF0YSBmaWVsZCxcbiAgICogdGhpcyBpcyBlbmZvcmNlZCBkdXJpbmcgdmFsaWRhdGlvbiBwcm9jZXNzLlxuICAgKlxuICAgKiBZb3UgY2FuIGFsc28gYWRkIGJpbmFyeSBkYXRhIHVzaW5nIGBjb25maWdNYXAuYWRkQmluYXJ5RGF0YSgpYC5cbiAgICovXG4gIHJlYWRvbmx5IGJpbmFyeURhdGE/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBEYXRhIGNvbnRhaW5zIHRoZSBjb25maWd1cmF0aW9uIGRhdGEuXG4gICAqXG4gICAqIEVhY2gga2V5IG11c3QgY29uc2lzdCBvZiBhbHBoYW51bWVyaWMgY2hhcmFjdGVycywgJy0nLCAnXycgb3IgJy4nLiBWYWx1ZXNcbiAgICogd2l0aCBub24tVVRGLTggYnl0ZSBzZXF1ZW5jZXMgbXVzdCB1c2UgdGhlIEJpbmFyeURhdGEgZmllbGQuIFRoZSBrZXlzXG4gICAqIHN0b3JlZCBpbiBEYXRhIG11c3Qgbm90IG92ZXJsYXAgd2l0aCB0aGUga2V5cyBpbiB0aGUgQmluYXJ5RGF0YSBmaWVsZCwgdGhpc1xuICAgKiBpcyBlbmZvcmNlZCBkdXJpbmcgdmFsaWRhdGlvbiBwcm9jZXNzLlxuICAgKlxuICAgKiBZb3UgY2FuIGFsc28gYWRkIGRhdGEgdXNpbmcgYGNvbmZpZ01hcC5hZGREYXRhKClgLlxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YT86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbiAgLyoqXG4gICAqIElmIHNldCB0byB0cnVlLCBlbnN1cmVzIHRoYXQgZGF0YSBzdG9yZWQgaW4gdGhlIENvbmZpZ01hcCBjYW5ub3QgYmUgdXBkYXRlZCAob25seSBvYmplY3QgbWV0YWRhdGEgY2FuIGJlIG1vZGlmaWVkKS5cbiAgICogSWYgbm90IHNldCB0byB0cnVlLCB0aGUgZmllbGQgY2FuIGJlIG1vZGlmaWVkIGF0IGFueSB0aW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaW1tdXRhYmxlPzogYm9vbGVhbjtcblxufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBjb25maWcgbWFwLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElDb25maWdNYXAgZXh0ZW5kcyBiYXNlLklSZXNvdXJjZSB7XG5cbn1cblxuY2xhc3MgSW1wb3J0ZWRDb25maWdNYXAgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJQ29uZmlnTWFwIHtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9uYW1lOiBzdHJpbmc7XG5cbiAgcHVibGljIHJlYWRvbmx5IHJlc291cmNlVHlwZSA9ICdjb25maWdtYXBzJztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuICAgIHRoaXMuX25hbWUgPSBuYW1lO1xuICB9XG5cbiAgcHVibGljIGdldCBuYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX25hbWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGFwaVZlcnNpb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gazhzLkt1YmVDb25maWdNYXAuR1ZLLmFwaVZlcnNpb247XG4gIH1cblxuICBwdWJsaWMgZ2V0IGFwaUdyb3VwKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgcHVibGljIGdldCBraW5kKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGs4cy5LdWJlQ29uZmlnTWFwLkdWSy5raW5kO1xuICB9XG5cbiAgcHVibGljIGdldCByZXNvdXJjZU5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lO1xuICB9XG5cbn1cblxuLyoqXG4gKiBDb25maWdNYXAgaG9sZHMgY29uZmlndXJhdGlvbiBkYXRhIGZvciBwb2RzIHRvIGNvbnN1bWUuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25maWdNYXAgZXh0ZW5kcyBiYXNlLlJlc291cmNlIGltcGxlbWVudHMgSUNvbmZpZ01hcCB7XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgYSBDb25maWdNYXAgY3JlYXRlZCBlbHNld2hlcmUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21Db25maWdNYXBOYW1lKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIG5hbWU6IHN0cmluZyk6IElDb25maWdNYXAge1xuICAgIHJldHVybiBuZXcgSW1wb3J0ZWRDb25maWdNYXAoc2NvcGUsIGlkLCBuYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc2VlIGJhc2UuUmVzb3VyY2UuYXBpT2JqZWN0XG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYXBpT2JqZWN0OiBBcGlPYmplY3Q7XG5cbiAgcHVibGljIHJlYWRvbmx5IHJlc291cmNlVHlwZSA9ICdjb25maWdtYXBzJztcblxuICBwcml2YXRlIHJlYWRvbmx5IF9iaW5hcnlEYXRhOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0geyB9O1xuICBwcml2YXRlIHJlYWRvbmx5IF9kYXRhOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0geyB9O1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGlzIGNvbmZpZyBtYXAgaXMgaW1tdXRhYmxlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGltbXV0YWJsZTogYm9vbGVhbjtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IENvbmZpZ01hcFByb3BzID0geyB9KSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHRoaXMuaW1tdXRhYmxlID0gcHJvcHMuaW1tdXRhYmxlID8/IGZhbHNlO1xuICAgIHRoaXMuYXBpT2JqZWN0ID0gbmV3IGs4cy5LdWJlQ29uZmlnTWFwKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIG1ldGFkYXRhOiBwcm9wcy5tZXRhZGF0YSxcblxuICAgICAgLy8gd2UgbmVlZCBsYXp5IGhlcmUgYmVjYXVzZSB3ZSBmaWx0ZXIgZW1wdHlcbiAgICAgIGRhdGE6IExhenkuYW55KHsgcHJvZHVjZTogKCkgPT4gdGhpcy5zeW50aGVzaXplRGF0YSgpIH0pLFxuICAgICAgYmluYXJ5RGF0YTogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLnN5bnRoZXNpemVCaW5hcnlEYXRhKCkgfSksXG4gICAgICBpbW11dGFibGU6IHRoaXMuaW1tdXRhYmxlLFxuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMocHJvcHMuZGF0YSA/PyB7IH0pKSB7XG4gICAgICB0aGlzLmFkZERhdGEoaywgdik7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMocHJvcHMuYmluYXJ5RGF0YSA/PyB7IH0pKSB7XG4gICAgICB0aGlzLmFkZEJpbmFyeURhdGEoaywgdik7XG4gICAgfVxuXG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGRhdGEgZW50cnkgdG8gdGhlIGNvbmZpZyBtYXAuXG4gICAqIEBwYXJhbSBrZXkgVGhlIGtleVxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlXG4gICAqXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgaXMgZWl0aGVyIGEgYGRhdGFgIG9yIGBiaW5hcnlEYXRhYCBlbnRyeSB3aXRoIHRoZSBzYW1lIGtleVxuICAgKi9cbiAgcHVibGljIGFkZERhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLnZlcmlmeUtleUF2YWlsYWJsZShrZXkpO1xuXG4gICAgdGhpcy5fZGF0YVtrZXldID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoaXMgY29uZmlnIG1hcC5cbiAgICpcbiAgICogUmV0dXJucyBhbiBjb3B5LiBUbyBhZGQgZGF0YSByZWNvcmRzLCB1c2UgYGFkZERhdGEoKWAgb3IgYGFkZEJpbmFyeURhdGEoKWAuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGRhdGEoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHsgLi4udGhpcy5fZGF0YSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBiaW5hcnkgZGF0YSBlbnRyeSB0byB0aGUgY29uZmlnIG1hcC4gQmluYXJ5RGF0YSBjYW4gY29udGFpbiBieXRlXG4gICAqIHNlcXVlbmNlcyB0aGF0IGFyZSBub3QgaW4gdGhlIFVURi04IHJhbmdlLlxuICAgKiBAcGFyYW0ga2V5IFRoZSBrZXlcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZVxuICAgKlxuICAgKiBAdGhyb3dzIGlmIHRoZXJlIGlzIGVpdGhlciBhIGBkYXRhYCBvciBgYmluYXJ5RGF0YWAgZW50cnkgd2l0aCB0aGUgc2FtZSBrZXlcbiAgICovXG4gIHB1YmxpYyBhZGRCaW5hcnlEYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy52ZXJpZnlLZXlBdmFpbGFibGUoa2V5KTtcblxuICAgIHRoaXMuX2JpbmFyeURhdGFba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiaW5hcnkgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhpcyBjb25maWcgbWFwLlxuICAgKlxuICAgKiBSZXR1cm5zIGEgY29weS4gVG8gYWRkIGRhdGEgcmVjb3JkcywgdXNlIGBhZGRCaW5hcnlEYXRhKClgIG9yIGBhZGREYXRhKClgLlxuICAgKi9cbiAgcHVibGljIGdldCBiaW5hcnlEYXRhKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiB7IC4uLnRoaXMuX2JpbmFyeURhdGEgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgZmlsZSB0byB0aGUgQ29uZmlnTWFwLlxuICAgKiBAcGFyYW0gbG9jYWxGaWxlIFRoZSBwYXRoIHRvIHRoZSBsb2NhbCBmaWxlXG4gICAqIEBwYXJhbSBrZXkgVGhlIENvbmZpZ01hcCBrZXkgKGRlZmF1bHQgdG8gdGhlIGZpbGUgbmFtZSkuXG4gICAqL1xuICBwdWJsaWMgYWRkRmlsZShsb2NhbEZpbGU6IHN0cmluZywga2V5Pzogc3RyaW5nKSB7XG4gICAga2V5ID0ga2V5ID8/IHBhdGguYmFzZW5hbWUobG9jYWxGaWxlKTtcbiAgICBjb25zdCB2YWx1ZSA9IGNvbmZpZ21hcC5yZWFkRmlsZVN5bmMobG9jYWxGaWxlLCAndXRmLTgnKTtcblxuICAgIHRoaXMuYWRkRGF0YShrZXksIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgZGlyZWN0b3J5IHRvIHRoZSBDb25maWdNYXAuXG4gICAqIEBwYXJhbSBsb2NhbERpciBBIHBhdGggdG8gYSBsb2NhbCBkaXJlY3RvcnlcbiAgICogQHBhcmFtIG9wdGlvbnMgT3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGFkZERpcmVjdG9yeShsb2NhbERpcjogc3RyaW5nLCBvcHRpb25zOiBBZGREaXJlY3RvcnlPcHRpb25zID0geyB9KSB7XG4gICAgY29uc3QgZXhjbHVkZSA9IG9wdGlvbnMuZXhjbHVkZSA/PyBbXTtcbiAgICBjb25zdCBzaG91bGRJbmNsdWRlID0gKGZpbGU6IHN0cmluZykgPT4ge1xuICAgICAgZm9yIChjb25zdCBwYXR0ZXJuIG9mIGV4Y2x1ZGUpIHtcbiAgICAgICAgY29uc3QgbW0gPSBuZXcgTWluaW1hdGNoKHBhdHRlcm4pO1xuICAgICAgICBpZiAobW0ubWF0Y2goZmlsZSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICBjb25zdCBrZXlQcmVmaXggPSBvcHRpb25zLmtleVByZWZpeCA/PyAnJztcbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgY29uZmlnbWFwLnJlYWRkaXJTeW5jKGxvY2FsRGlyKSkge1xuXG4gICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbihsb2NhbERpciwgZmlsZSk7XG5cbiAgICAgIGlmIChjb25maWdtYXAuc3RhdFN5bmMoZmlsZVBhdGgpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghc2hvdWxkSW5jbHVkZShmaWxlKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVsYXRpdmVGaWxlUGF0aCA9IGtleVByZWZpeCArIGZpbGU7XG4gICAgICB0aGlzLmFkZEZpbGUoZmlsZVBhdGgsIHJlbGF0aXZlRmlsZVBhdGgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmVyaWZ5S2V5QXZhaWxhYmxlKGtleTogc3RyaW5nKSB7XG4gICAgaWYgKGtleSBpbiB0aGlzLl9kYXRhIHx8IGtleSBpbiB0aGlzLl9iaW5hcnlEYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuYWJsZSB0byBhZGQgYSBDb25maWdNYXAgZW50cnkgd2l0aCBrZXkgXCIke2tleX1cIi4gSXQgaXMgYWxyZWFkeSB1c2VkYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzeW50aGVzaXplRGF0YSgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkSWZFbXB0eSh0aGlzLl9kYXRhKTtcbiAgfVxuXG4gIHByaXZhdGUgc3ludGhlc2l6ZUJpbmFyeURhdGEoKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZElmRW1wdHkodGhpcy5fYmluYXJ5RGF0YSk7XG4gIH1cbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgY29uZmlnbWFwLmFkZERpcmVjdG9yeSgpYFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFkZERpcmVjdG9yeU9wdGlvbnMge1xuICAvKipcbiAgICogQSBwcmVmaXggdG8gYWRkIHRvIGFsbCBrZXlzIGluIHRoZSBjb25maWcgbWFwLlxuICAgKiBAZGVmYXVsdCBcIlwiXG4gICAqL1xuICByZWFkb25seSBrZXlQcmVmaXg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEdsb2IgcGF0dGVybnMgdG8gZXhjbHVkZSB3aGVuIGFkZGluZyBmaWxlcy5cbiAgICogQGRlZmF1bHQgLSBpbmNsdWRlIGFsbCBmaWxlc1xuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZT86IHN0cmluZ1tdO1xufVxuIl19