From 8fa8612201a153b7979a71ac42bdca6337bdb416 Mon Sep 17 00:00:00 2001 From: sp98 Date: Tue, 27 Aug 2024 10:40:35 +0530 Subject: [PATCH 01/54] core: check for duplicate ceph fs pool names Only single pool will get created if there are multiple data pool entries with same name. This PR just adds a check to fail if duplicate pools are present. Signed-off-by: sp98 --- pkg/operator/ceph/file/filesystem.go | 23 +++++++++++++++++++++++ pkg/operator/ceph/file/filesystem_test.go | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/pkg/operator/ceph/file/filesystem.go b/pkg/operator/ceph/file/filesystem.go index 898875c6b7e6..8a35ab1a0231 100644 --- a/pkg/operator/ceph/file/filesystem.go +++ b/pkg/operator/ceph/file/filesystem.go @@ -144,6 +144,14 @@ func validateFilesystem(context *clusterd.Context, clusterInfo *cephclient.Clust if len(f.Spec.DataPools) == 0 { return nil } + + // Ensure duplicate pool names are not present in the spec. + if len(f.Spec.DataPools) > 1 { + if hasDuplicatePoolNames(f.Spec.DataPools) { + return errors.New("duplicate pool names in the data pool spec") + } + } + if err := cephpool.ValidatePoolSpec(context, clusterInfo, clusterSpec, &f.Spec.MetadataPool); err != nil { return errors.Wrap(err, "invalid metadata pool") } @@ -157,6 +165,21 @@ func validateFilesystem(context *clusterd.Context, clusterInfo *cephclient.Clust return nil } +func hasDuplicatePoolNames(poolSpecList []cephv1.NamedPoolSpec) bool { + poolNames := make(map[string]struct{}) + for _, poolSpec := range poolSpecList { + if poolSpec.Name != "" { + if _, has := poolNames[poolSpec.Name]; has { + logger.Errorf("duplicate pool name %q in the data pool spec", poolSpec.Name) + return true + } + poolNames[poolSpec.Name] = struct{}{} + } + } + + return false +} + // newFS creates a new instance of the file (MDS) service func newFS(name, namespace string) *Filesystem { return &Filesystem{ diff --git a/pkg/operator/ceph/file/filesystem_test.go b/pkg/operator/ceph/file/filesystem_test.go index ffe8aaf5dccd..856add3885eb 100644 --- a/pkg/operator/ceph/file/filesystem_test.go +++ b/pkg/operator/ceph/file/filesystem_test.go @@ -73,6 +73,26 @@ func TestValidateSpec(t *testing.T) { assert.Nil(t, validateFilesystem(context, clusterInfo, clusterSpec, fs)) } +func TestHasDuplicatePoolNames(t *testing.T) { + // PoolSpec with no duplicates + fs := &cephv1.CephFilesystem{ + Spec: cephv1.FilesystemSpec{ + DataPools: []cephv1.NamedPoolSpec{ + {Name: "pool1"}, + {Name: "pool2"}, + }, + }, + } + + result := hasDuplicatePoolNames(fs.Spec.DataPools) + assert.False(t, result) + + // add duplicate pool name in the spec. + fs.Spec.DataPools = append(fs.Spec.DataPools, cephv1.NamedPoolSpec{Name: "pool1"}) + result = hasDuplicatePoolNames(fs.Spec.DataPools) + assert.True(t, result) +} + func TestGenerateDataPoolNames(t *testing.T) { fs := &Filesystem{Name: "fake", Namespace: "fake"} fsSpec := cephv1.FilesystemSpec{ From 93179a41f37752b9f45621fc56301295c685a87c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 28 Aug 2024 09:58:26 +0200 Subject: [PATCH 02/54] ci: slightly rework the docs-check workflow This reworks the docs-check ci workflow in several ways: * It renames the make target 'check-docs' to the more systematic 'check.docs'. * It adds a 'docs'mode to the files validation script, and uses the script in `make check.docs`. Overall, the workflow and local make targets are more systematic and consistent with this change. Signed-off-by: Michael Adam --- .github/workflows/docs-check.yml | 2 +- Documentation/Contributing/documentation.md | 2 +- Makefile | 7 ++----- tests/scripts/validate_modified_files.sh | 6 +++++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index c060ce5d4b74..1a13e842d604 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -45,7 +45,7 @@ jobs: - name: Check helm-docs run: make check-helm-docs - name: Check docs - run: make check-docs + run: make check.docs - name: Install mkdocs and dependencies run: cd build/release/ && make deps.docs diff --git a/Documentation/Contributing/documentation.md b/Documentation/Contributing/documentation.md index ef9e1d370bdb..aa88f6a9e425 100644 --- a/Documentation/Contributing/documentation.md +++ b/Documentation/Contributing/documentation.md @@ -35,4 +35,4 @@ When previewing, now you can navigate your browser to [http://127.0.0.1:8000/](h ## Making docs [helm-docs](https://github.com/norwoodj/helm-docs) is a tool that generates the documentation for a helm chart automatically. If there are changes in the helm chart, the developer needs to run `make docs` (to run helm-docs) and check in the resulting autogenerated files. -To make it easy to check locally for uncommitted changes generated by `make docs`, an additional `make` target exists: simply running `make check-docs` will run the docs auto-generation and will complain if this produces uncommitted changes to doc files. It is therefore a good habit to always run `make check-docs` locally before creating or updating a PR. +To make it easy to check locally for uncommitted changes generated by `make docs`, an additional `make` target exists: simply running `make check.docs` will run the docs auto-generation and will complain if this produces uncommitted changes to doc files. It is therefore a good habit to always run `make check.docs` locally before creating or updating a PR. diff --git a/Makefile b/Makefile index 29d1c24839eb..825664cf7937 100644 --- a/Makefile +++ b/Makefile @@ -207,12 +207,9 @@ check-helm-docs: echo "Please run 'make helm-docs' locally, commit the updated docs, and push the change. See https://rook.io/docs/rook/latest/Contributing/documentation/#making-docs" ; \ exit 2 ; \ }; -check-docs: +check.docs: @$(MAKE) docs - @git diff --exit-code || { \ - echo "Please run 'make docs' locally, commit the updated docs, and push the change." ; \ - exit 2 ; \ - }; + @tests/scripts/validate_modified_files.sh docs docs-preview: ## Preview the documentation through mkdocs diff --git a/tests/scripts/validate_modified_files.sh b/tests/scripts/validate_modified_files.sh index 1b51d81ca9d7..27cdb13f7279 100755 --- a/tests/scripts/validate_modified_files.sh +++ b/tests/scripts/validate_modified_files.sh @@ -9,6 +9,7 @@ MOD_ERR="changes found by mod.check. You may need to run make clean" CRD_ERR="changes found by 'make crds'. please run 'make crds' locally and update your PR" BUILD_ERR="changes found by make build', please commit your go.sum or other changed files" HELM_ERR="changes found by 'make gen-rbac'. please run 'make gen-rbac' locally and update your PR" +DOCS_ERR="changes found by 'make docs'. please run 'make docs' locally and update your PR" ############# # FUNCTIONS # @@ -29,6 +30,9 @@ function validate(){ # MAIN # ######## case "$1" in + docs) + validate "$DOCS_ERR" + ;; codegen) validate "$CODEGEN_ERR" ;; @@ -45,6 +49,6 @@ case "$1" in validate "$HELM_ERR" ;; *) - echo $"Usage: $0 {codegen|modcheck|crd|build|gen-rbac}" + echo $"Usage: $0 {docs|codegen|modcheck|crd|build|gen-rbac}" exit 1 esac From 59175f0b408cbeae5531927a9cb9e760034bb221 Mon Sep 17 00:00:00 2001 From: Artem Torubarov Date: Fri, 6 Sep 2024 16:02:53 +0200 Subject: [PATCH 03/54] rgw: pool placement Signed-off-by: Artem Torubarov --- Documentation/CRDs/specification.md | 146 ++ .../Object-Storage-RGW/object-storage.md | 82 +- .../charts/rook-ceph/templates/resources.yaml | 132 +- deploy/examples/crds.yaml | 132 +- pkg/apis/ceph.rook.io/v1/types.go | 68 +- pkg/operator/ceph/object/admin.go | 12 +- pkg/operator/ceph/object/controller.go | 13 +- pkg/operator/ceph/object/json_helpers.go | 125 ++ pkg/operator/ceph/object/json_helpers_test.go | 509 +++++ pkg/operator/ceph/object/objectstore.go | 403 ++-- pkg/operator/ceph/object/objectstore_test.go | 815 ++++++-- pkg/operator/ceph/object/shared_pools.go | 510 +++++ pkg/operator/ceph/object/shared_pools_test.go | 1803 +++++++++++++++++ pkg/operator/ceph/object/zone/controller.go | 26 +- 14 files changed, 4421 insertions(+), 355 deletions(-) create mode 100644 pkg/operator/ceph/object/json_helpers.go create mode 100644 pkg/operator/ceph/object/json_helpers_test.go create mode 100644 pkg/operator/ceph/object/shared_pools.go create mode 100644 pkg/operator/ceph/object/shared_pools_test.go diff --git a/Documentation/CRDs/specification.md b/Documentation/CRDs/specification.md index 4e796082477e..662c8575c97f 100644 --- a/Documentation/CRDs/specification.md +++ b/Documentation/CRDs/specification.md @@ -9418,6 +9418,7 @@ string +(Optional)

The metadata pool used for creating RADOS namespaces in the object store

@@ -9429,6 +9430,7 @@ string +(Optional)

The data pool used for creating RADOS namespaces in the object store

@@ -9444,6 +9446,28 @@ bool

Whether the RADOS namespaces should be preserved on deletion of the object store

+ + +poolPlacements
+ + +[]PoolPlacementSpec + + + + +(Optional) +

PoolPlacements control which Pools are associated with a particular RGW bucket. +Once PoolPlacements are defined, RGW client will be able to associate pool +with ObjectStore bucket by providing “” during s3 bucket creation +or “X-Storage-Policy” header during swift container creation. +See: https://docs.ceph.com/en/latest/radosgw/placement/#placement-targets +PoolPlacement with name: “default” will be used as a default pool if no option +is provided during bucket creation. +If default placement is not provided, spec.sharedPools.dataPoolName and spec.sharedPools.MetadataPoolName will be used as default pools. +If spec.sharedPools are also empty, then RGW pools (spec.dataPool and spec.metadataPool) will be used as defaults.

+ +

ObjectStoreHostingSpec @@ -10624,6 +10648,49 @@ the triple using the matching operator

PlacementSpec is the placement for core ceph daemons part of the CephCluster CRD

+

PlacementStorageClassSpec +

+

+(Appears on:PoolPlacementSpec) +

+
+
+ + + + + + + + + + + + + + + + + +
FieldDescription
+name
+ +string + +
+

Name is the StorageClass name. Ceph allows arbitrary name for StorageClasses, +however most clients/libs insist on AWS names so it is recommended to use +one of the valid x-amz-storage-class values for better compatibility: +REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE +See AWS docs: https://aws.amazon.com/de/s3/storage-classes/

+
+dataPoolName
+ +string + +
+

DataPoolName is the data pool used to store ObjectStore objects data.

+

PoolMirroringInfo

@@ -10780,6 +10847,85 @@ StatesSpec +

PoolPlacementSpec +

+

+(Appears on:ObjectSharedPoolsSpec) +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+name
+ +string + +
+

Pool placement name. Name can be arbitrary. Placement with name “default” will be used as default.

+
+metadataPoolName
+ +string + +
+

The metadata pool used to store ObjectStore bucket index.

+
+dataPoolName
+ +string + +
+

The data pool used to store ObjectStore objects data.

+
+dataNonECPoolName
+ +string + +
+(Optional) +

The data pool used to store ObjectStore data that cannot use erasure coding (ex: multi-part uploads). +If dataPoolName is not erasure coded, then there is no need for dataNonECPoolName.

+
+storageClasses
+ + +[]PlacementStorageClassSpec + + +
+(Optional) +

StorageClasses can be selected by user to override dataPoolName during object creation. +Each placement has default STANDARD StorageClass pointing to dataPoolName. +This list allows defining additional StorageClasses on top of default STANDARD storage class.

+

PoolSpec

diff --git a/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md b/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md index 50bfcd176a20..4c291a0c2409 100644 --- a/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md +++ b/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md @@ -14,8 +14,9 @@ Rook can configure the Ceph Object Store for several different scenarios. See ea 1. Create a [local object store](#create-a-local-object-store-with-s3) with dedicated Ceph pools. This option is recommended if a single object store is required, and is the simplest to get started. 2. Create [one or more object stores with shared Ceph pools](#create-local-object-stores-with-shared-pools). This option is recommended when multiple object stores are required. -3. Connect to an [RGW service in an external Ceph cluster](#connect-to-an-external-object-store), rather than create a local object store. -4. Configure [RGW Multisite](#object-multisite) to synchronize buckets between object stores in different clusters. +3. Create [one or more object stores with pool placement targets and storage classes](#create-local-object-stores-with-pool-placements). This configuration allows Rook to provide different object placement options to object store clients. +4. Connect to an [RGW service in an external Ceph cluster](#connect-to-an-external-object-store), rather than create a local object store. +5. Configure [RGW Multisite](#object-multisite) to synchronize buckets between object stores in different clusters. !!! note Updating the configuration of an object store between these types is not supported. @@ -188,6 +189,83 @@ To consume the object store, continue below in the section to [Create a bucket]( Modify the default example object store name from `my-store` to the alternate name of the object store such as `store-a` in this example. +### Create Local Object Store(s) with pool placements + +!!! attention + This feature is experimental. + +This section contains a guide on how to configure [RGW's pool placement and storage classes](https://docs.ceph.com/en/reef/radosgw/placement/) with Rook. + +Object Storage API allows users to override where bucket data will be stored during bucket creation. With `` parameter in S3 API and `X-Storage-Policy` header in SWIFT. Similarly, users can override where object data will be stored by setting `X-Amz-Storage-Class` and `X-Object-Storage-Class` during object creation. + +To enable this feature, configure `poolPlacements` representing a list of possible bucket data locations. +Each `poolPlacement` must have: + +* a **unique** `name` to refer to it in `` or `X-Storage-Policy`. A placement with reserved name `default` will be used by default if no location constraint is provided. +* `dataPoolName` and `metadataPoolName` representing object data and metadata locations. In Rook, these data locations are backed by `CephBlockPool`. `poolPlacements` and `storageClasses` specs refer pools by name. This means that all pools should be defined in advance. Similarly to [sharedPools](#create-local-object-stores-with-shared-pools), the same pool can be reused across multiple ObjectStores and/or poolPlacements/storageClasses because of RADOS namespaces. Here, each pool will be namespaced with `..` key. +* **optional** `dataNonECPoolName` - extra pool for data that cannot use erasure coding (ex: multi-part uploads). If not set, `metadataPoolName` will be used. +* **optional** list of placement `storageClasses`. Classes defined per placement, which means that even classes of `default` placement will be available only within this placement and not others. Each placement will automatically have default storage class named `STANDARD`. `STANDARD` class always points to placement `dataPoolName` and cannot be removed or redefined. Each storage class must have: + * `name` (unique within placement). RGW allows arbitrary name for StorageClasses, however some clients/libs insist on AWS names so it is recommended to use one of the valid `x-amz-storage-class` values for better compatibility: `STANDARD | REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE`. See [AWS docs](https://aws.amazon.com/s3/storage-classes/). + * `dataPoolName` - overrides placement data pool when this class is selected by user. + +Example: Configure `CephObjectStore` with `default` placement pointing to `us` pools and placement `europe` pointing to pools in corresponding geographies. These geographical locations are only an example. Placement name can be arbitrary and could reflect the backing pool's replication factor, device class, or failure domain. This example also defines storage class `REDUCED_REDUNDANCY` for each placement. + +```yaml +apiVersion: ceph.rook.io/v1 +kind: CephObjectStore +metadata: + name: my-store + namespace: rook-ceph +spec: + gateway: + port: 80 + instances: 1 + sharedPools: + poolPlacements: + - name: default + metadataPoolName: "us-data-pool" + dataPoolName: "us-meta-pool" + storageClasses: + - name: REDUCED_REDUNDANCY + dataPoolName: "us-reduced-pool" + - name: europe + metadataPoolName: "eu-meta-pool" + dataPoolName: "eu-data-pool" + storageClasses: + - name: REDUCED_REDUNDANCY + dataPoolName: "eu-reduced-pool" +``` + +S3 clients can direct objects into the pools defined in the above. The example below uses the [s5cmd](https://github.com/peak/s5cmd) CLI tool which is pre-installed in the toolbox pod: + +```shell +# make bucket without location constraint -> will use "us" +s5cmd mb s3://bucket1 + +# put object to bucket1 without storage class -> end up in "us-data-pool" +s5cmd put obj s3://bucket1/obj + +# put object to bucket1 with "STANDARD" storage class -> end up in "us-data-pool" +s5cmd put obj s3://bucket1/obj --storage-class=STANDARD + +# put object to bucket1 with "REDUCED_REDUNDANCY" storage class -> end up in "us-reduced-pool" +s5cmd put obj s3://bucket1/obj --storage-class=REDUCED_REDUNDANCY + + +# make bucket with location constraint europe +s5cmd mb s3://bucket2 --region=my-store:europe + +# put object to bucket2 without storage class -> end up in "eu-data-pool" +s5cmd put obj s3://bucket2/obj + +# put object to bucket2 with "STANDARD" storage class -> end up in "eu-data-pool" +s5cmd put obj s3://bucket2/obj --storage-class=STANDARD + +# put object to bucket2 with "REDUCED_REDUNDANCY" storage class -> end up in "eu-reduced-pool" +s5cmd put obj s3://bucket2/obj --storage-class=REDUCED_REDUNDANCY + +``` + ### Connect to an External Object Store Rook can connect to existing RGW gateways to work in conjunction with the external mode of the `CephCluster` CRD. First, create a `rgw-admin-ops-user` user in the Ceph cluster with the necessary caps: diff --git a/deploy/charts/rook-ceph/templates/resources.yaml b/deploy/charts/rook-ceph/templates/resources.yaml index e7954efe7b9e..767e08498461 100644 --- a/deploy/charts/rook-ceph/templates/resources.yaml +++ b/deploy/charts/rook-ceph/templates/resources.yaml @@ -12316,12 +12316,72 @@ spec: x-kubernetes-validations: - message: object store shared metadata pool is immutable rule: self == oldSelf + poolPlacements: + description: |- + PoolPlacements control which Pools are associated with a particular RGW bucket. + Once PoolPlacements are defined, RGW client will be able to associate pool + with ObjectStore bucket by providing "" during s3 bucket creation + or "X-Storage-Policy" header during swift container creation. + See: https://docs.ceph.com/en/latest/radosgw/placement/#placement-targets + PoolPlacement with name: "default" will be used as a default pool if no option + is provided during bucket creation. + If default placement is not provided, spec.sharedPools.dataPoolName and spec.sharedPools.MetadataPoolName will be used as default pools. + If spec.sharedPools are also empty, then RGW pools (spec.dataPool and spec.metadataPool) will be used as defaults. + items: + properties: + dataNonECPoolName: + description: |- + The data pool used to store ObjectStore data that cannot use erasure coding (ex: multi-part uploads). + If dataPoolName is not erasure coded, then there is no need for dataNonECPoolName. + type: string + dataPoolName: + description: The data pool used to store ObjectStore objects data. + minLength: 1 + type: string + metadataPoolName: + description: The metadata pool used to store ObjectStore bucket index. + minLength: 1 + type: string + name: + description: Pool placement name. Name can be arbitrary. Placement with name "default" will be used as default. + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + storageClasses: + description: |- + StorageClasses can be selected by user to override dataPoolName during object creation. + Each placement has default STANDARD StorageClass pointing to dataPoolName. + This list allows defining additional StorageClasses on top of default STANDARD storage class. + items: + properties: + dataPoolName: + description: DataPoolName is the data pool used to store ObjectStore objects data. + minLength: 1 + type: string + name: + description: |- + Name is the StorageClass name. Ceph allows arbitrary name for StorageClasses, + however most clients/libs insist on AWS names so it is recommended to use + one of the valid x-amz-storage-class values for better compatibility: + REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE + See AWS docs: https://aws.amazon.com/de/s3/storage-classes/ + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + required: + - dataPoolName + - name + type: object + type: array + required: + - dataPoolName + - metadataPoolName + - name + type: object + type: array preserveRadosNamespaceDataOnDelete: description: Whether the RADOS namespaces should be preserved on deletion of the object store type: boolean - required: - - dataPoolName - - metadataPoolName type: object zone: description: The multisite info @@ -13178,12 +13238,72 @@ spec: x-kubernetes-validations: - message: object store shared metadata pool is immutable rule: self == oldSelf + poolPlacements: + description: |- + PoolPlacements control which Pools are associated with a particular RGW bucket. + Once PoolPlacements are defined, RGW client will be able to associate pool + with ObjectStore bucket by providing "" during s3 bucket creation + or "X-Storage-Policy" header during swift container creation. + See: https://docs.ceph.com/en/latest/radosgw/placement/#placement-targets + PoolPlacement with name: "default" will be used as a default pool if no option + is provided during bucket creation. + If default placement is not provided, spec.sharedPools.dataPoolName and spec.sharedPools.MetadataPoolName will be used as default pools. + If spec.sharedPools are also empty, then RGW pools (spec.dataPool and spec.metadataPool) will be used as defaults. + items: + properties: + dataNonECPoolName: + description: |- + The data pool used to store ObjectStore data that cannot use erasure coding (ex: multi-part uploads). + If dataPoolName is not erasure coded, then there is no need for dataNonECPoolName. + type: string + dataPoolName: + description: The data pool used to store ObjectStore objects data. + minLength: 1 + type: string + metadataPoolName: + description: The metadata pool used to store ObjectStore bucket index. + minLength: 1 + type: string + name: + description: Pool placement name. Name can be arbitrary. Placement with name "default" will be used as default. + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + storageClasses: + description: |- + StorageClasses can be selected by user to override dataPoolName during object creation. + Each placement has default STANDARD StorageClass pointing to dataPoolName. + This list allows defining additional StorageClasses on top of default STANDARD storage class. + items: + properties: + dataPoolName: + description: DataPoolName is the data pool used to store ObjectStore objects data. + minLength: 1 + type: string + name: + description: |- + Name is the StorageClass name. Ceph allows arbitrary name for StorageClasses, + however most clients/libs insist on AWS names so it is recommended to use + one of the valid x-amz-storage-class values for better compatibility: + REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE + See AWS docs: https://aws.amazon.com/de/s3/storage-classes/ + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + required: + - dataPoolName + - name + type: object + type: array + required: + - dataPoolName + - metadataPoolName + - name + type: object + type: array preserveRadosNamespaceDataOnDelete: description: Whether the RADOS namespaces should be preserved on deletion of the object store type: boolean - required: - - dataPoolName - - metadataPoolName type: object zoneGroup: description: The display name for the ceph users diff --git a/deploy/examples/crds.yaml b/deploy/examples/crds.yaml index 5978262293d4..9f7a3d225655 100644 --- a/deploy/examples/crds.yaml +++ b/deploy/examples/crds.yaml @@ -12307,12 +12307,72 @@ spec: x-kubernetes-validations: - message: object store shared metadata pool is immutable rule: self == oldSelf + poolPlacements: + description: |- + PoolPlacements control which Pools are associated with a particular RGW bucket. + Once PoolPlacements are defined, RGW client will be able to associate pool + with ObjectStore bucket by providing "" during s3 bucket creation + or "X-Storage-Policy" header during swift container creation. + See: https://docs.ceph.com/en/latest/radosgw/placement/#placement-targets + PoolPlacement with name: "default" will be used as a default pool if no option + is provided during bucket creation. + If default placement is not provided, spec.sharedPools.dataPoolName and spec.sharedPools.MetadataPoolName will be used as default pools. + If spec.sharedPools are also empty, then RGW pools (spec.dataPool and spec.metadataPool) will be used as defaults. + items: + properties: + dataNonECPoolName: + description: |- + The data pool used to store ObjectStore data that cannot use erasure coding (ex: multi-part uploads). + If dataPoolName is not erasure coded, then there is no need for dataNonECPoolName. + type: string + dataPoolName: + description: The data pool used to store ObjectStore objects data. + minLength: 1 + type: string + metadataPoolName: + description: The metadata pool used to store ObjectStore bucket index. + minLength: 1 + type: string + name: + description: Pool placement name. Name can be arbitrary. Placement with name "default" will be used as default. + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + storageClasses: + description: |- + StorageClasses can be selected by user to override dataPoolName during object creation. + Each placement has default STANDARD StorageClass pointing to dataPoolName. + This list allows defining additional StorageClasses on top of default STANDARD storage class. + items: + properties: + dataPoolName: + description: DataPoolName is the data pool used to store ObjectStore objects data. + minLength: 1 + type: string + name: + description: |- + Name is the StorageClass name. Ceph allows arbitrary name for StorageClasses, + however most clients/libs insist on AWS names so it is recommended to use + one of the valid x-amz-storage-class values for better compatibility: + REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE + See AWS docs: https://aws.amazon.com/de/s3/storage-classes/ + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + required: + - dataPoolName + - name + type: object + type: array + required: + - dataPoolName + - metadataPoolName + - name + type: object + type: array preserveRadosNamespaceDataOnDelete: description: Whether the RADOS namespaces should be preserved on deletion of the object store type: boolean - required: - - dataPoolName - - metadataPoolName type: object zone: description: The multisite info @@ -13166,12 +13226,72 @@ spec: x-kubernetes-validations: - message: object store shared metadata pool is immutable rule: self == oldSelf + poolPlacements: + description: |- + PoolPlacements control which Pools are associated with a particular RGW bucket. + Once PoolPlacements are defined, RGW client will be able to associate pool + with ObjectStore bucket by providing "" during s3 bucket creation + or "X-Storage-Policy" header during swift container creation. + See: https://docs.ceph.com/en/latest/radosgw/placement/#placement-targets + PoolPlacement with name: "default" will be used as a default pool if no option + is provided during bucket creation. + If default placement is not provided, spec.sharedPools.dataPoolName and spec.sharedPools.MetadataPoolName will be used as default pools. + If spec.sharedPools are also empty, then RGW pools (spec.dataPool and spec.metadataPool) will be used as defaults. + items: + properties: + dataNonECPoolName: + description: |- + The data pool used to store ObjectStore data that cannot use erasure coding (ex: multi-part uploads). + If dataPoolName is not erasure coded, then there is no need for dataNonECPoolName. + type: string + dataPoolName: + description: The data pool used to store ObjectStore objects data. + minLength: 1 + type: string + metadataPoolName: + description: The metadata pool used to store ObjectStore bucket index. + minLength: 1 + type: string + name: + description: Pool placement name. Name can be arbitrary. Placement with name "default" will be used as default. + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + storageClasses: + description: |- + StorageClasses can be selected by user to override dataPoolName during object creation. + Each placement has default STANDARD StorageClass pointing to dataPoolName. + This list allows defining additional StorageClasses on top of default STANDARD storage class. + items: + properties: + dataPoolName: + description: DataPoolName is the data pool used to store ObjectStore objects data. + minLength: 1 + type: string + name: + description: |- + Name is the StorageClass name. Ceph allows arbitrary name for StorageClasses, + however most clients/libs insist on AWS names so it is recommended to use + one of the valid x-amz-storage-class values for better compatibility: + REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE + See AWS docs: https://aws.amazon.com/de/s3/storage-classes/ + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + required: + - dataPoolName + - name + type: object + type: array + required: + - dataPoolName + - metadataPoolName + - name + type: object + type: array preserveRadosNamespaceDataOnDelete: description: Whether the RADOS namespaces should be preserved on deletion of the object store type: boolean - required: - - dataPoolName - - metadataPoolName type: object zoneGroup: description: The display name for the ceph users diff --git a/pkg/apis/ceph.rook.io/v1/types.go b/pkg/apis/ceph.rook.io/v1/types.go index 380c1f3cd23d..c817ac41ac73 100755 --- a/pkg/apis/ceph.rook.io/v1/types.go +++ b/pkg/apis/ceph.rook.io/v1/types.go @@ -1517,15 +1517,75 @@ type ObjectStoreSpec struct { type ObjectSharedPoolsSpec struct { // The metadata pool used for creating RADOS namespaces in the object store // +kubebuilder:validation:XValidation:message="object store shared metadata pool is immutable",rule="self == oldSelf" - MetadataPoolName string `json:"metadataPoolName"` + // +optional + MetadataPoolName string `json:"metadataPoolName,omitempty"` // The data pool used for creating RADOS namespaces in the object store // +kubebuilder:validation:XValidation:message="object store shared data pool is immutable",rule="self == oldSelf" - DataPoolName string `json:"dataPoolName"` + // +optional + DataPoolName string `json:"dataPoolName,omitempty"` // Whether the RADOS namespaces should be preserved on deletion of the object store // +optional PreserveRadosNamespaceDataOnDelete bool `json:"preserveRadosNamespaceDataOnDelete"` + + // PoolPlacements control which Pools are associated with a particular RGW bucket. + // Once PoolPlacements are defined, RGW client will be able to associate pool + // with ObjectStore bucket by providing "" during s3 bucket creation + // or "X-Storage-Policy" header during swift container creation. + // See: https://docs.ceph.com/en/latest/radosgw/placement/#placement-targets + // PoolPlacement with name: "default" will be used as a default pool if no option + // is provided during bucket creation. + // If default placement is not provided, spec.sharedPools.dataPoolName and spec.sharedPools.MetadataPoolName will be used as default pools. + // If spec.sharedPools are also empty, then RGW pools (spec.dataPool and spec.metadataPool) will be used as defaults. + // +optional + PoolPlacements []PoolPlacementSpec `json:"poolPlacements,omitempty"` +} + +type PoolPlacementSpec struct { + // Pool placement name. Name can be arbitrary. Placement with name "default" will be used as default. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9._/-]+$` + Name string `json:"name"` + + // The metadata pool used to store ObjectStore bucket index. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + MetadataPoolName string `json:"metadataPoolName"` + + // The data pool used to store ObjectStore objects data. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + DataPoolName string `json:"dataPoolName"` + + // The data pool used to store ObjectStore data that cannot use erasure coding (ex: multi-part uploads). + // If dataPoolName is not erasure coded, then there is no need for dataNonECPoolName. + // +optional + DataNonECPoolName string `json:"dataNonECPoolName,omitempty"` + + // StorageClasses can be selected by user to override dataPoolName during object creation. + // Each placement has default STANDARD StorageClass pointing to dataPoolName. + // This list allows defining additional StorageClasses on top of default STANDARD storage class. + // +optional + StorageClasses []PlacementStorageClassSpec `json:"storageClasses,omitempty"` +} + +type PlacementStorageClassSpec struct { + // Name is the StorageClass name. Ceph allows arbitrary name for StorageClasses, + // however most clients/libs insist on AWS names so it is recommended to use + // one of the valid x-amz-storage-class values for better compatibility: + // REDUCED_REDUNDANCY | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | GLACIER | DEEP_ARCHIVE | OUTPOSTS | GLACIER_IR | SNOW | EXPRESS_ONEZONE + // See AWS docs: https://aws.amazon.com/de/s3/storage-classes/ + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9._/-]+$` + Name string `json:"name"` + + // DataPoolName is the data pool used to store ObjectStore objects data. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + DataPoolName string `json:"dataPoolName"` } // ObjectHealthCheckSpec represents the health check of an object store @@ -2019,7 +2079,7 @@ type CephObjectZoneGroupList struct { // ObjectZoneGroupSpec represent the spec of an ObjectZoneGroup type ObjectZoneGroupSpec struct { - //The display name for the ceph users + // The display name for the ceph users Realm string `json:"realm"` } @@ -2050,7 +2110,7 @@ type CephObjectZoneList struct { // ObjectZoneSpec represent the spec of an ObjectZone type ObjectZoneSpec struct { - //The display name for the ceph users + // The display name for the ceph users ZoneGroup string `json:"zoneGroup"` // The metadata pool settings diff --git a/pkg/operator/ceph/object/admin.go b/pkg/operator/ceph/object/admin.go index 5e5a2596f515..67ab074a3b84 100644 --- a/pkg/operator/ceph/object/admin.go +++ b/pkg/operator/ceph/object/admin.go @@ -48,6 +48,14 @@ type Context struct { Zone string } +func (c *Context) nsName() string { + if c.clusterInfo == nil { + logger.Infof("unable to get namespaced name for rgw %s", c.Name) + return c.Name + } + return fmt.Sprintf("%s/%s", c.clusterInfo.Namespace, c.Name) +} + // AdminOpsContext holds the object store context as well as information for connecting to the admin // ops API. type AdminOpsContext struct { @@ -101,9 +109,7 @@ const ( rgwAdminOpsUserCaps = "buckets=*;users=*;usage=read;metadata=read;zone=read" ) -var ( - rgwAdminOpsUserDisplayName = "RGW Admin Ops User" -) +var rgwAdminOpsUserDisplayName = "RGW Admin Ops User" // NewContext creates a new object store context. func NewContext(context *clusterd.Context, clusterInfo *cephclient.ClusterInfo, name string) *Context { diff --git a/pkg/operator/ceph/object/controller.go b/pkg/operator/ceph/object/controller.go index 651978ec9204..82e8b128c820 100644 --- a/pkg/operator/ceph/object/controller.go +++ b/pkg/operator/ceph/object/controller.go @@ -441,12 +441,19 @@ func (r *ReconcileCephObjectStore) reconcileCreateObjectStore(cephObjectStore *c return r.setFailedStatus(k8sutil.ObservedGenerationNotAvailable, namespacedName, "failed to set endpoint", err) } + err = ValidateObjectStorePoolsConfig(cephObjectStore.Spec.MetadataPool, cephObjectStore.Spec.DataPool, cephObjectStore.Spec.SharedPools) + if err != nil { + return r.setFailedStatus(k8sutil.ObservedGenerationNotAvailable, namespacedName, "invalid pool configuration", err) + } // Reconcile Pool Creation if !cephObjectStore.Spec.IsMultisite() { logger.Info("reconciling object store pools") - err = ConfigurePools(objContext, r.clusterSpec, cephObjectStore.Spec.MetadataPool, cephObjectStore.Spec.DataPool, cephObjectStore.Spec.SharedPools) - if err != nil { - return r.setFailedStatus(k8sutil.ObservedGenerationNotAvailable, namespacedName, "failed to create object pools", err) + + if IsNeedToCreateObjectStorePools(cephObjectStore.Spec.SharedPools) { + err = CreateObjectStorePools(objContext, r.clusterSpec, cephObjectStore.Spec.MetadataPool, cephObjectStore.Spec.DataPool) + if err != nil { + return r.setFailedStatus(k8sutil.ObservedGenerationNotAvailable, namespacedName, "failed to create object pools", err) + } } } diff --git a/pkg/operator/ceph/object/json_helpers.go b/pkg/operator/ceph/object/json_helpers.go new file mode 100644 index 000000000000..719339e7db2a --- /dev/null +++ b/pkg/operator/ceph/object/json_helpers.go @@ -0,0 +1,125 @@ +package object + +import ( + "encoding/json" + "fmt" + "strings" +) + +// getObjProperty - helper function to manipulate JSON Objects. +// returns nested property of json object. +// Example: +// +// obj = {"a":{"b":"foo"}} +// // will return "foo" +// getObjProperty(obj,"a","b") +func getObjProperty[T string | map[string]interface{} | []interface{}](obj map[string]interface{}, path ...string) (T, error) { + var res T + if len(path) == 0 { + return res, fmt.Errorf("json property path is empty") + } + + for i, p := range path { + val, ok := obj[p] + if !ok { + return res, fmt.Errorf("json property %q not found", strings.Join(path[:i+1], ".")) + } + last := i == len(path)-1 + if last { + // last path segment: get result + res, ok = val.(T) + if !ok { + return res, fmt.Errorf("json property %q is not a %T, got %+v", strings.Join(path, "."), res, val) + } + return res, nil + } + // walk to the next obj in the path + obj, ok = val.(map[string]interface{}) + if !ok { + return res, fmt.Errorf("json property %q is not an object, got %+v", strings.Join(path[:i+1], "."), val) + } + } + // not reachable + return res, fmt.Errorf("json property %q not found", strings.Join(path, ".")) +} + +// setObjProperty - helper function to manipulate JSON Objects. +// sets value to json object nested field and returns previous value if presented. +// Example: +// +// obj = {"a":{"b":"foo"}} +// // will replace "foo" with "bar" and return "foo" +// setObjProperty(obj,"bar","a","b") +func setObjProperty[T string | []string | map[string]interface{} | []interface{}](obj map[string]interface{}, val T, path ...string) (T, error) { + var prev T + if len(path) == 0 { + return prev, fmt.Errorf("json property path is empty") + } + for i, p := range path { + last := i == len(path)-1 + if last { + // last path segment: set result and return prev value + prevVal, ok := obj[p] + if ok { + prevRes, ok := prevVal.(T) + if ok { + prev = prevRes + } else { + // in go json all arrays are []interface{}, extra conversion for typed arrays (e.g. []string) needed: + p := new(T) + if castJson(prevVal, p) { + prev = *p + } + } + } + obj[p] = val + return prev, nil + } + // walk to the next obj in the path + next, ok := obj[p] + if !ok { + return prev, fmt.Errorf("json property %q is not found", strings.Join(path[:i+1], ".")) + } + obj, ok = next.(map[string]interface{}) + if !ok { + return prev, fmt.Errorf("json property %q is not an object, got %+v", strings.Join(path[:i+1], "."), next) + } + } + // not reachable + return prev, fmt.Errorf("json property %q not found", strings.Join(path, ".")) +} + +// castJson - helper function to manipulate JSON Objects. +// Tries to cast any type to any type by converting to JSON and back. +// Returns true on success. +func castJson(in, out interface{}) bool { + bytes, err := json.Marshal(in) + if err != nil { + return false + } + err = json.Unmarshal(bytes, out) + return err == nil +} + +// toObj - helper function to manipulate JSON Objects. +// Casts any go struct to map representing JSON object. +func toObj(val interface{}) (map[string]interface{}, error) { + bytes, err := json.Marshal(val) + if err != nil { + return nil, err + } + obj := map[string]interface{}{} + return obj, json.Unmarshal(bytes, &obj) +} + +// deepCopyJson - helper function to manipulate JSON Objects. +// Makes deep copy of json object by converting to JSON and back. +func deepCopyJson(in map[string]interface{}) (map[string]interface{}, error) { + bytes, err := json.Marshal(in) + if err != nil { + return nil, err + } + res := map[string]interface{}{} + err = json.Unmarshal(bytes, &res) + return res, err +} diff --git a/pkg/operator/ceph/object/json_helpers_test.go b/pkg/operator/ceph/object/json_helpers_test.go new file mode 100644 index 000000000000..9448c107067c --- /dev/null +++ b/pkg/operator/ceph/object/json_helpers_test.go @@ -0,0 +1,509 @@ +package object + +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_getObjPropertyStr(t *testing.T) { + type args struct { + json string + path []string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "success", + args: args{ + json: `{"a":{"b":"val"}}`, + path: []string{ + "a", "b", + }, + }, + want: "val", + wantErr: false, + }, + { + name: "success: empty str", + args: args{ + json: `{"a":{"b":""}}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: false, + }, + { + name: "err: empty json", + args: args{ + json: `{}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: true, + }, + { + name: "err: is obj", + args: args{ + json: `{"a":{"b":{"val":"val"}}}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: true, + }, + { + name: "err: is arr", + args: args{ + json: `{"a":{"b":["val1","val2"]}}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: true, + }, + { + name: "err: is bool", + args: args{ + json: `{"a":{"b":true}}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: true, + }, + { + name: "err: is num", + args: args{ + json: `{"a":{"b":5}}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: true, + }, + { + name: "err: is missing", + args: args{ + json: `{"a":{"c":"val"}}`, + path: []string{ + "a", "b", + }, + }, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + obj := map[string]interface{}{} + _ = json.Unmarshal([]byte(tt.args.json), &obj) + got, err := getObjProperty[string](obj, tt.args.path...) + if (err != nil) != tt.wantErr { + t.Errorf("getObjProperty() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getObjProperty() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_getObjPropertyObjArr(t *testing.T) { + type args struct { + json string + path []string + } + tests := []struct { + name string + args args + want []interface{} + wantErr bool + }{ + { + name: "success", + args: args{ + json: `{"a":{"b":[ + {"c":"val1"}, + {"d":"val2"} + ]}}`, + path: []string{ + "a", "b", + }, + }, + want: []interface{}{ + map[string]interface{}{"c": "val1"}, + map[string]interface{}{"d": "val2"}, + }, + wantErr: false, + }, + { + name: "err: empty json", + args: args{ + json: `{}`, + path: []string{ + "a", "b", + }, + }, + wantErr: true, + }, + { + name: "err: is obj", + args: args{ + json: `{"a":{"b":{"val":"val"}}}`, + path: []string{ + "a", "b", + }, + }, + wantErr: true, + }, + { + name: "err: is bool", + args: args{ + json: `{"a":{"b":true}}`, + path: []string{ + "a", "b", + }, + }, + wantErr: true, + }, + { + name: "err: is num", + args: args{ + json: `{"a":{"b":5}}`, + path: []string{ + "a", "b", + }, + }, + wantErr: true, + }, + { + name: "err: is missing", + args: args{ + json: `{"a":{"c":"val"}}`, + path: []string{ + "a", "b", + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + obj := map[string]interface{}{} + _ = json.Unmarshal([]byte(tt.args.json), &obj) + got, err := getObjProperty[[]interface{}](obj, tt.args.path...) + if (err != nil) != tt.wantErr { + t.Errorf("getObjProperty() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getObjProperty() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_setObjProperty(t *testing.T) { + type args struct { + json string + val string + path []string + } + tests := []struct { + name string + args args + wantPrev string + wantJSON string + wantErr bool + }{ + { + name: "replace val", + args: args{ + json: `{"a":{"b":"val"}}`, + val: "new val", + path: []string{ + "a", "b", + }, + }, + wantPrev: "val", + wantJSON: `{"a":{"b":"new val"}}`, + wantErr: false, + }, + { + name: "same val", + args: args{ + json: `{"a":{"b":"val"}}`, + val: "val", + path: []string{ + "a", "b", + }, + }, + wantPrev: "val", + wantJSON: `{"a":{"b":"val"}}`, + wantErr: false, + }, + { + name: "add val", + args: args{ + json: `{"a":{"b":"val"}}`, + val: "val2", + path: []string{ + "a", "c", + }, + }, + wantPrev: "", + wantJSON: `{"a":{"b":"val","c":"val2"}}`, + wantErr: false, + }, + { + name: "add root val", + args: args{ + json: `{"a":{"b":"val"}}`, + val: "val2", + path: []string{ + "c", + }, + }, + wantPrev: "", + wantJSON: `{"a":{"b":"val"},"c":"val2"}`, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + obj := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.json), &obj) + assert.NoError(t, err) + prev, err := setObjProperty(obj, tt.args.val, tt.args.path...) + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + assert.EqualValues(t, tt.wantPrev, prev) + bytes, err := json.Marshal(obj) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantJSON, string(bytes)) + }) + } +} +func Test_setObjPropertyObj(t *testing.T) { + type args struct { + json string + val map[string]interface{} + path []string + } + tests := []struct { + name string + args args + wantPrev map[string]interface{} + wantJSON string + wantErr bool + }{ + { + name: "add obj", + args: args{ + json: `{"a":{"b":{}}}`, + val: map[string]interface{}{"c": "val1"}, + path: []string{ + "a", "b", + }, + }, + wantPrev: map[string]interface{}{}, + wantJSON: `{"a":{"b":{"c":"val1"}}}`, + wantErr: false, + }, + { + name: "set obj", + args: args{ + json: `{"a":{"b":{"c": "val1"}}}`, + val: map[string]interface{}{"d": "val2"}, + path: []string{ + "a", "b", + }, + }, + wantPrev: map[string]interface{}{"c": "val1"}, + wantJSON: `{"a":{"b":{"d":"val2"}}}`, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + obj := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.json), &obj) + assert.NoError(t, err) + prev, err := setObjProperty(obj, tt.args.val, tt.args.path...) + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + assert.EqualValues(t, tt.wantPrev, prev) + bytes, err := json.Marshal(obj) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantJSON, string(bytes)) + }) + } +} + +func Test_setObjPropertyArr(t *testing.T) { + type args struct { + json string + val []interface{} + path []string + } + tests := []struct { + name string + args args + wantPrev []interface{} + wantJSON string + wantErr bool + }{ + { + name: "set obj arr", + args: args{ + json: `{"a":{"b":{}}}`, + val: []interface{}{ + map[string]interface{}{"c": "val1"}, + map[string]interface{}{"d": "val2"}, + }, + path: []string{ + "a", "b", + }, + }, + wantPrev: nil, + wantJSON: `{"a":{"b":[{"c":"val1"},{"d":"val2"}]}}`, + wantErr: false, + }, + { + name: "add obj arr", + args: args{ + json: `{"a":{"b":[{"c": "val"}]}}`, + val: []interface{}{ + map[string]interface{}{"d": "val1"}, + map[string]interface{}{"e": "val2"}, + }, + path: []string{ + "a", "b", + }, + }, + wantPrev: []interface{}{ + map[string]interface{}{"c": "val"}, + }, + wantJSON: `{"a":{"b":[{"d":"val1"},{"e":"val2"}]}}`, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + obj := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.json), &obj) + assert.NoError(t, err) + prev, err := setObjProperty(obj, tt.args.val, tt.args.path...) + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + assert.EqualValues(t, tt.wantPrev, prev) + bytes, err := json.Marshal(obj) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantJSON, string(bytes)) + }) + } +} +func Test_setObjPropertyStrArr(t *testing.T) { + type args struct { + json string + val []string + path []string + } + tests := []struct { + name string + args args + wantPrev []string + wantJSON string + wantErr bool + }{ + { + name: "add str arr", + args: args{ + json: `{"a":{"b":{}}}`, + val: []string{"c", "d"}, + path: []string{ + "a", "b", + }, + }, + wantPrev: nil, + wantJSON: `{"a":{"b":["c","d"]}}`, + wantErr: false, + }, + { + name: "set str arr", + args: args{ + json: `{"a":{"b":["val"]}}`, + val: []string{"c", "d"}, + path: []string{ + "a", "b", + }, + }, + wantPrev: []string{"val"}, + wantJSON: `{"a":{"b":["c","d"]}}`, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + obj := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.json), &obj) + assert.NoError(t, err) + prev, err := setObjProperty(obj, tt.args.val, tt.args.path...) + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + assert.EqualValues(t, tt.wantPrev, prev) + bytes, err := json.Marshal(obj) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantJSON, string(bytes)) + }) + } +} + +func Test_deepCopyJson(t *testing.T) { + in := map[string]interface{}{ + "key": []interface{}{"1", "2", "3"}, + } + inCopy, err := deepCopyJson(in) + assert.NoError(t, err) + assert.EqualValues(t, in, inCopy) + + assert.EqualValues(t, []interface{}{"1", "2", "3"}, in["key"]) + assert.EqualValues(t, []interface{}{"1", "2", "3"}, inCopy["key"]) + + inCopy["key"].([]interface{})[1] = "7" + + assert.EqualValues(t, []interface{}{"1", "2", "3"}, in["key"]) + assert.EqualValues(t, []interface{}{"1", "7", "3"}, inCopy["key"]) +} diff --git a/pkg/operator/ceph/object/objectstore.go b/pkg/operator/ceph/object/objectstore.go index bf194f4f40e4..794419ac8498 100644 --- a/pkg/operator/ceph/object/objectstore.go +++ b/pkg/operator/ceph/object/objectstore.go @@ -21,7 +21,7 @@ import ( "encoding/json" "fmt" "os" - "path" + "reflect" "sort" "strconv" "strings" @@ -209,7 +209,6 @@ func deleteSingleSiteRealmAndPools(objContext *Context, spec cephv1.ObjectStoreS // This is used for quickly getting the name of the realm, zone group, and zone for an object-store to pass into a Context func getMultisiteForObjectStore(ctx context.Context, clusterdContext *clusterd.Context, spec *cephv1.ObjectStoreSpec, namespace, name string) (string, string, string, error) { - if spec.IsExternal() { // In https://github.com/rook/rook/issues/6342, it was determined that // a multisite context isn't needed for external mode CephObjectStores. @@ -749,16 +748,8 @@ func missingPools(context *Context) ([]string, error) { return missingPools, nil } -func ConfigurePools(context *Context, cluster *cephv1.ClusterSpec, metadataPool, dataPool cephv1.PoolSpec, sharedPools cephv1.ObjectSharedPoolsSpec) error { - if sharedPoolsSpecified(sharedPools) { - if !EmptyPool(dataPool) || !EmptyPool(metadataPool) { - return fmt.Errorf("object store shared pools can only be specified if the metadata and data pools are not specified") - } - // Shared pools are configured elsewhere - return nil - } - - if EmptyPool(dataPool) && EmptyPool(metadataPool) { +func CreateObjectStorePools(context *Context, cluster *cephv1.ClusterSpec, metadataPool, dataPool cephv1.PoolSpec) error { + if EmptyPool(dataPool) || EmptyPool(metadataPool) { logger.Info("no pools specified for the CR, checking for their existence...") missingPools, err := missingPools(context) if err != nil { @@ -793,77 +784,60 @@ func ConfigurePools(context *Context, cluster *cephv1.ClusterSpec, metadataPool, return nil } -func sharedPoolsSpecified(sharedPools cephv1.ObjectSharedPoolsSpec) bool { - return sharedPools.DataPoolName != "" && sharedPools.MetadataPoolName != "" -} - func ConfigureSharedPoolsForZone(objContext *Context, sharedPools cephv1.ObjectSharedPoolsSpec) error { - if !sharedPoolsSpecified(sharedPools) { - logger.Debugf("no shared pools to configure for store %q", objContext.Name) + if sharedPools.DataPoolName == "" && sharedPools.MetadataPoolName == "" && len(sharedPools.PoolPlacements) == 0 { + logger.Debugf("no shared pools to configure for store %q", objContext.nsName()) return nil } + logger.Infof("configuring shared pools for object store %q", objContext.nsName()) if err := sharedPoolsExist(objContext, sharedPools); err != nil { return errors.Wrapf(err, "object store cannot be configured until shared pools exist") } - // retrieve the zone config - logger.Infof("Retrieving zone %q", objContext.Zone) - realmArg := fmt.Sprintf("--rgw-realm=%s", objContext.Realm) - zoneGroupArg := fmt.Sprintf("--rgw-zonegroup=%s", objContext.ZoneGroup) - zoneArg := "--rgw-zone=" + objContext.Zone - args := []string{"zone", "get", realmArg, zoneGroupArg, zoneArg} - - output, err := RunAdminCommandNoMultisite(objContext, true, args...) + zoneConfig, err := getZoneJSON(objContext) if err != nil { - return errors.Wrap(err, "failed to get zone") + return err } - - logger.Debugf("Zone config is currently:\n%s", output) - - var zoneConfig map[string]interface{} - err = json.Unmarshal([]byte(output), &zoneConfig) + zoneUpdated, err := adjustZoneDefaultPools(zoneConfig, sharedPools) if err != nil { - return errors.Wrap(err, "failed to unmarshal zone") - } - - metadataPrefix := fmt.Sprintf("%s:%s.", sharedPools.MetadataPoolName, objContext.Name) - dataPrefix := fmt.Sprintf("%s:%s.", sharedPools.DataPoolName, objContext.Name) - expectedDataPool := dataPrefix + "buckets.data" - if dataPoolIsExpected(objContext, zoneConfig, expectedDataPool) { - logger.Debugf("Data pool already set as expected to %q", expectedDataPool) - return nil - } - - logger.Infof("Updating rados namespace configuration for zone %q", objContext.Zone) - if err := applyExpectedRadosNamespaceSettings(zoneConfig, metadataPrefix, dataPrefix, expectedDataPool); err != nil { - return errors.Wrap(err, "failed to configure rados namespaces") + return err } - - configBytes, err := json.Marshal(zoneConfig) + zoneUpdated, err = adjustZonePlacementPools(zoneUpdated, sharedPools) if err != nil { - return errors.Wrap(err, "failed to serialize zone config") + return err } - logger.Debugf("Raw zone settings to apply: %s", string(configBytes)) + hasZoneChanged := !reflect.DeepEqual(zoneConfig, zoneUpdated) - configFilename := path.Join(objContext.Context.ConfigDir, objContext.Name+".zonecfg") - if err := os.WriteFile(configFilename, configBytes, 0600); err != nil { - return errors.Wrap(err, "failed to write zonfig config file") + zoneGroupConfig, err := getZoneGroupJSON(objContext) + if err != nil { + return err } - defer os.Remove(configFilename) - - args = []string{"zone", "set", zoneArg, "--infile=" + configFilename, realmArg, zoneGroupArg} - output, err = RunAdminCommandNoMultisite(objContext, false, args...) + zoneGroupUpdated, err := adjustZoneGroupPlacementTargets(zoneGroupConfig, zoneUpdated) if err != nil { - return errors.Wrap(err, "failed to set zone config") + return err } - logger.Debugf("Zone set results=%s", output) + hasZoneGroupChanged := !reflect.DeepEqual(zoneGroupConfig, zoneGroupUpdated) - if err = zoneUpdateWorkaround(objContext, output, expectedDataPool); err != nil { - return errors.Wrap(err, "failed to apply zone set workaround") + // persist configuration updates: + if hasZoneChanged { + logger.Infof("zone config changed: performing zone config updates for %s", objContext.Zone) + updatedZoneResult, err := updateZoneJSON(objContext, zoneUpdated) + if err != nil { + return fmt.Errorf("unable to persist zone config update for %s: %w", objContext.Zone, err) + } + if err = zoneUpdateWorkaround(objContext, zoneUpdated, updatedZoneResult); err != nil { + return fmt.Errorf("failed to apply zone set workaround: %w", err) + } + } + if hasZoneGroupChanged { + logger.Infof("zonegroup config changed: performing zonegroup config updates for %s", objContext.ZoneGroup) + _, err = updateZoneGroupJSON(objContext, zoneGroupUpdated) + if err != nil { + return fmt.Errorf("unable to persist zonegroup config update for %s: %w", objContext.ZoneGroup, err) + } } - logger.Infof("Successfully configured RADOS namespaces for object store %q", objContext.Name) return nil } @@ -872,139 +846,226 @@ func sharedPoolsExist(objContext *Context, sharedPools cephv1.ObjectSharedPoolsS if err != nil { return errors.Wrapf(err, "failed to list pools") } - foundMetadataPool := false - foundDataPool := false + existing := make(map[string]struct{}, len(existingPools)) for _, pool := range existingPools { - if pool.Name == sharedPools.MetadataPoolName { - foundMetadataPool = true - } - if pool.Name == sharedPools.DataPoolName { - foundDataPool = true - } + existing[pool.Name] = struct{}{} } + // sharedPools.MetadataPoolName, DataPoolName, and sharedPools.PoolPlacements.DataNonECPoolName are optional. + // ignore optional pools with empty name: + existing[""] = struct{}{} - if !foundMetadataPool && !foundDataPool { - return fmt.Errorf("pools do not exist: %q and %q", sharedPools.MetadataPoolName, sharedPools.DataPoolName) + if _, ok := existing[sharedPools.MetadataPoolName]; !ok { + return fmt.Errorf("sharedPool do not exist: %s", sharedPools.MetadataPoolName) } - if !foundMetadataPool { - return fmt.Errorf("metadata pool does not exist: %q", sharedPools.MetadataPoolName) + if _, ok := existing[sharedPools.DataPoolName]; !ok { + return fmt.Errorf("sharedPool do not exist: %s", sharedPools.DataPoolName) } - if !foundDataPool { - return fmt.Errorf("data pool does not exist: %q", sharedPools.DataPoolName) + + for _, pp := range sharedPools.PoolPlacements { + if _, ok := existing[pp.MetadataPoolName]; !ok { + return fmt.Errorf("sharedPool does not exist: pool %s for placement %s", pp.MetadataPoolName, pp.Name) + } + if _, ok := existing[pp.DataPoolName]; !ok { + return fmt.Errorf("sharedPool do not exist: pool %s for placement %s", pp.DataPoolName, pp.Name) + } + if _, ok := existing[pp.DataNonECPoolName]; !ok { + return fmt.Errorf("sharedPool do not exist: pool %s for placement %s", pp.DataNonECPoolName, pp.Name) + } + for _, sc := range pp.StorageClasses { + if _, ok := existing[sc.DataPoolName]; !ok { + return fmt.Errorf("sharedPool do not exist: pool %s for StorageClass %s", sc.DataPoolName, sc.Name) + } + } } - logger.Info("verified shared pools exist") return nil } -func applyExpectedRadosNamespaceSettings(zoneConfig map[string]interface{}, metadataPrefix, dataPrefix, dataPool string) error { - // Update the necessary fields for RAODS namespaces - zoneConfig["domain_root"] = metadataPrefix + "meta.root" - zoneConfig["control_pool"] = metadataPrefix + "control" - zoneConfig["gc_pool"] = metadataPrefix + "log.gc" - zoneConfig["lc_pool"] = metadataPrefix + "log.lc" - zoneConfig["log_pool"] = metadataPrefix + "log" - zoneConfig["intent_log_pool"] = metadataPrefix + "log.intent" - zoneConfig["usage_log_pool"] = metadataPrefix + "log.usage" - zoneConfig["roles_pool"] = metadataPrefix + "meta.roles" - zoneConfig["reshard_pool"] = metadataPrefix + "log.reshard" - zoneConfig["user_keys_pool"] = metadataPrefix + "meta.users.keys" - zoneConfig["user_email_pool"] = metadataPrefix + "meta.users.email" - zoneConfig["user_swift_pool"] = metadataPrefix + "meta.users.swift" - zoneConfig["user_uid_pool"] = metadataPrefix + "meta.users.uid" - zoneConfig["otp_pool"] = metadataPrefix + "otp" - zoneConfig["notif_pool"] = metadataPrefix + "log.notif" - - placementPools, ok := zoneConfig["placement_pools"].([]interface{}) - if !ok { - return fmt.Errorf("failed to parse placement_pools") +func adjustZoneDefaultPools(zone map[string]interface{}, spec cephv1.ObjectSharedPoolsSpec) (map[string]interface{}, error) { + name, err := getObjProperty[string](zone, "name") + if err != nil { + return nil, fmt.Errorf("unable to get zone name: %w", err) } - if len(placementPools) == 0 { - return fmt.Errorf("no placement pools") + + zone, err = deepCopyJson(zone) + if err != nil { + return nil, fmt.Errorf("unable to deep copy zone %s: %w", name, err) + } + + defaultMetaPool := getDefaultMetadataPool(spec) + if defaultMetaPool == "" { + // default pool is not presented in shared pool spec + return zone, nil + } + // add zone namespace to metadata pool to safely share accorss rgw instances or zones. + // in non-multisite case zone name equals to rgw instance name + defaultMetaPool = defaultMetaPool + ":" + name + zonePoolNSSuffix := map[string]string{ + "domain_root": ".meta.root", + "control_pool": ".control", + "gc_pool": ".log.gc", + "lc_pool": ".log.lc", + "log_pool": ".log", + "intent_log_pool": ".log.intent", + "usage_log_pool": ".log.usage", + "roles_pool": ".meta.roles", + "reshard_pool": ".log.reshard", + "user_keys_pool": ".meta.users.keys", + "user_email_pool": ".meta.users.email", + "user_swift_pool": ".meta.users.swift", + "user_uid_pool": ".meta.users.uid", + "otp_pool": ".otp", + "notif_pool": ".log.notif", + } + for pool, nsSuffix := range zonePoolNSSuffix { + // replace rgw internal index pools with namespaced metadata pool + namespacedPool := defaultMetaPool + nsSuffix + prev, err := setObjProperty(zone, namespacedPool, pool) + if err != nil { + return nil, fmt.Errorf("unable to set pool %s for zone %s: %w", pool, name, err) + } + if namespacedPool != prev { + logger.Debugf("update shared pool %s for zone %s: %s -> %s", pool, name, prev, namespacedPool) + } } - placementPool, ok := placementPools[0].(map[string]interface{}) - if !ok { - return fmt.Errorf("failed to parse placement_pools[0]") + return zone, nil +} + +// There was a radosgw-admin bug that was preventing the RADOS namespace from being applied +// for the data pool. The fix is included in Reef v18.2.3 or newer, and v19.2.0. +// The workaround is to run a "radosgw-admin zone placement modify" command to apply +// the desired data pool config. +// After Reef (v18) support is removed, this method will be dead code. +func zoneUpdateWorkaround(objContext *Context, expectedZone, gotZone map[string]interface{}) error { + // Update the necessary fields for RAODS namespaces + // If the radosgw-admin fix is in the release, the data pool is already applied and we skip the workaround. + expected, err := getObjProperty[[]interface{}](expectedZone, "placement_pools") + if err != nil { + return err } - placementVals, ok := placementPool["val"].(map[string]interface{}) - if !ok { - return fmt.Errorf("failed to parse placement_pools[0].val") + got, err := getObjProperty[[]interface{}](gotZone, "placement_pools") + if err != nil { + return err } - placementVals["index_pool"] = metadataPrefix + "buckets.index" - // The extra pool is for omap data for multi-part uploads, so we use - // the metadata pool instead of the data pool. - placementVals["data_extra_pool"] = metadataPrefix + "buckets.non-ec" - storageClasses, ok := placementVals["storage_classes"].(map[string]interface{}) - if !ok { - return fmt.Errorf("failed to parse storage_classes") + if len(expected) != len(got) { + // should not happen + return fmt.Errorf("placements were not applied to zone config: expected %+v, got %+v", expected, got) } - stdStorageClass, ok := storageClasses["STANDARD"].(map[string]interface{}) - if !ok { - return fmt.Errorf("failed to parse storage_classes.STANDARD") + + // update pool placements one-by-one if needed + for i, expPl := range expected { + expPoolObj, ok := expPl.(map[string]interface{}) + if !ok { + return fmt.Errorf("unable to cast pool placement to object: %+v", expPl) + } + expPoolName, err := getObjProperty[string](expPoolObj, "key") + if err != nil { + return fmt.Errorf("unable to get pool placement name: %w", err) + } + + gotPoolObj, ok := got[i].(map[string]interface{}) + if !ok { + return fmt.Errorf("unable to cast pool placement to object: %+v", got[i]) + } + gotPoolName, err := getObjProperty[string](gotPoolObj, "key") + if err != nil { + return fmt.Errorf("unable to get pool placement name: %w", err) + } + + if expPoolName != gotPoolName { + // should not happen + return fmt.Errorf("placements were not applied to zone config: expected %+v, got %+v", expected, got) + } + err = zoneUpdatePlacementWorkaround(objContext, gotPoolName, expPoolObj, gotPoolObj) + if err != nil { + return fmt.Errorf("unable to do zone update workaround for placement %q: %w", gotPoolName, err) + } } - stdStorageClass["data_pool"] = dataPool return nil } -func dataPoolIsExpected(objContext *Context, zoneConfig map[string]interface{}, expectedDataPool string) bool { - placementPools, ok := zoneConfig["placement_pools"].([]interface{}) - if !ok { - return false +func zoneUpdatePlacementWorkaround(objContext *Context, placementID string, expect, got map[string]interface{}) error { + args := []string{ + "zone", "placement", "modify", + "--rgw-realm=" + objContext.Realm, + "--rgw-zonegroup=" + objContext.ZoneGroup, + "--rgw-zone=" + objContext.Zone, + "--placement-id", placementID, } - placementPool, ok := placementPools[0].(map[string]interface{}) - if !ok { - return false + // check index and data pools + needsWorkaround := false + expPool, err := getObjProperty[string](expect, "val", "index_pool") + if err != nil { + return err } - placementVals, ok := placementPool["val"].(map[string]interface{}) - if !ok { - return false + gotPool, err := getObjProperty[string](got, "val", "index_pool") + if err != nil { + return err } - storageClasses, ok := placementVals["storage_classes"].(map[string]interface{}) - if !ok { - return false + if expPool != gotPool { + logger.Infof("do zone update workaround for zone %s, placement %s index pool: %s -> %s", objContext.Zone, placementID, gotPool, expPool) + args = append(args, "--index-pool="+expPool) + needsWorkaround = true } - stdStorageClass, ok := storageClasses["STANDARD"].(map[string]interface{}) - if !ok { - return false + expPool, err = getObjProperty[string](expect, "val", "data_extra_pool") + if err != nil { + return err } - logger.Infof("data pool is currently set to %q", stdStorageClass["data_pool"]) - return stdStorageClass["data_pool"] == expectedDataPool -} - -// There was a radosgw-admin bug that was preventing the RADOS namespace from being applied -// for the data pool. The fix is included in Reef v18.2.3 or newer, and v19.2.0. -// The workaround is to run a "radosgw-admin zone placement modify" command to apply -// the desired data pool config. -// After Reef (v18) support is removed, this method will be dead code. -func zoneUpdateWorkaround(objContext *Context, zoneOutput, expectedDataPool string) error { - var zoneConfig map[string]interface{} - err := json.Unmarshal([]byte(zoneOutput), &zoneConfig) + gotPool, err = getObjProperty[string](got, "val", "data_extra_pool") if err != nil { - return errors.Wrap(err, "failed to unmarshal zone") + return err } - // Update the necessary fields for RAODS namespaces - // If the radosgw-admin fix is in the release, the data pool is already applied and we skip the workaround. - if dataPoolIsExpected(objContext, zoneConfig, expectedDataPool) { - logger.Infof("data pool was already set as expected to %q, workaround not needed", expectedDataPool) - return nil + if expPool != gotPool { + logger.Infof("do zone update workaround for zone %s, placement %s data extra pool: %s -> %s", objContext.Zone, placementID, gotPool, expPool) + args = append(args, "--data-extra-pool="+expPool) + needsWorkaround = true } - logger.Infof("Setting data pool to %q", expectedDataPool) - args := []string{"zone", "placement", "modify", - "--rgw-realm=" + objContext.Realm, - "--rgw-zonegroup=" + objContext.ZoneGroup, - "--rgw-zone=" + objContext.Name, - "--placement-id", "default-placement", - "--storage-class", "STANDARD", - "--data-pool=" + expectedDataPool, + if needsWorkaround { + _, err = RunAdminCommandNoMultisite(objContext, false, args...) + if err != nil { + return errors.Wrap(err, "failed to set zone config") + } } - - output, err := RunAdminCommandNoMultisite(objContext, false, args...) + expSC, err := getObjProperty[map[string]interface{}](expect, "val", "storage_classes") if err != nil { - return errors.Wrap(err, "failed to set zone config") + return err + } + gotSC, err := getObjProperty[map[string]interface{}](got, "val", "storage_classes") + if err != nil { + return err } - logger.Debugf("zone placement modify output=%s", output) - logger.Info("zone placement for the data pool was applied successfully") + + // check storage classes data pools + for sc := range expSC { + expDP, err := getObjProperty[string](expSC, sc, "data_pool") + if err != nil { + return err + } + gotDP, err := getObjProperty[string](gotSC, sc, "data_pool") + if err != nil { + return err + } + if expDP == gotDP { + continue + } + logger.Infof("do zone update workaround for zone %s, placement %s storage-class %s pool: %s -> %s", objContext.Zone, placementID, sc, gotDP, expDP) + args = []string{ + "zone", "placement", "modify", + "--rgw-realm=" + objContext.Realm, + "--rgw-zonegroup=" + objContext.ZoneGroup, + "--rgw-zone=" + objContext.Zone, + "--placement-id", placementID, + "--storage-class", sc, + "--data-pool=" + expDP, + } + output, err := RunAdminCommandNoMultisite(objContext, false, args...) + if err != nil { + return errors.Wrap(err, "failed to set zone config") + } + logger.Debugf("zone placement modify output=%s", output) + } + return nil } @@ -1333,3 +1394,17 @@ func CheckIfZonePresentInZoneGroup(objContext *Context) (bool, error) { } return false, nil } + +// ValidateObjectStorePoolsConfig returns error if given ObjectStore pool configuration is inconsistent. +func ValidateObjectStorePoolsConfig(metadataPool, dataPool cephv1.PoolSpec, sharedPools cephv1.ObjectSharedPoolsSpec) error { + if err := validatePoolPlacements(sharedPools.PoolPlacements); err != nil { + return err + } + if !EmptyPool(dataPool) && sharedPools.DataPoolName != "" { + return fmt.Errorf("invalidObjStorePoolCofig: object store dataPool and sharedPools.dataPool=%s are mutually exclusive. Only one of them can be set.", sharedPools.DataPoolName) + } + if !EmptyPool(metadataPool) && sharedPools.MetadataPoolName != "" { + return fmt.Errorf("invalidObjStorePoolCofig: object store metadataPool and sharedPools.metadataPool=%s are mutually exclusive. Only one of them can be set.", sharedPools.MetadataPoolName) + } + return nil +} diff --git a/pkg/operator/ceph/object/objectstore_test.go b/pkg/operator/ceph/object/objectstore_test.go index 33d33059629c..7c0d16c851c4 100644 --- a/pkg/operator/ceph/object/objectstore_test.go +++ b/pkg/operator/ceph/object/objectstore_test.go @@ -1,5 +1,4 @@ -/* -Copyright 2016 The Rook Authors. All rights reserved. +/* Copyright 2016 The Rook Authors. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,8 +17,8 @@ package object import ( "context" - "encoding/json" "fmt" + "os" "strings" "syscall" "testing" @@ -112,6 +111,85 @@ const ( "realm_id": "e7f176c6-d207-459c-aa04-c3334300ddc6", "notif_pool": "rgw-meta-pool:store-a.log.notif" }` + objectZoneSharedPoolsJsonTempl = `{ + "id": "c1a20ed9-6370-4abd-b78c-bdf0da2a8dbb", + "name": "store-a", + "domain_root": "%[1]s:store-a.meta.root", + "control_pool": "%[1]s:store-a.control", + "gc_pool": "%[1]s:store-a.log.gc", + "lc_pool": "%[1]s:store-a.log.lc", + "log_pool": "%[1]s:store-a.log", + "intent_log_pool": "%[1]s:store-a.log.intent", + "usage_log_pool": "%[1]s:store-a.log.usage", + "roles_pool": "%[1]s:store-a.meta.roles", + "reshard_pool": "%[1]s:store-a.log.reshard", + "user_keys_pool": "%[1]s:store-a.meta.users.keys", + "user_email_pool": "%[1]s:store-a.meta.users.email", + "user_swift_pool": "%[1]s:store-a.meta.users.swift", + "user_uid_pool": "%[1]s:store-a.meta.users.uid", + "otp_pool": "%[1]s:store-a.otp", + "system_key": { + "access_key": "", + "secret_key": "" + }, + "placement_pools": [ + { + "key": "default-placement", + "val": { + "data_extra_pool": "%[1]s:store-a.buckets.non-ec", + "index_pool": "%[1]s:store-a.buckets.index", + "index_type": 0, + "inline_data": true, + "storage_classes": { + "STANDARD": { + "data_pool": "%[2]s:store-a.buckets.data" + } + } + } + } + ], + "realm_id": "e7f176c6-d207-459c-aa04-c3334300ddc6", + "notif_pool": "%[1]s:store-a.log.notif" +}` + + objectZonegroupJson = `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "store-a", + "api_name": "test", + "is_master": true, + "endpoints": [ + "https://rook-ceph-rgw-test.rook-ceph.svc:443" + ], + "hostnames": [], + "hostnames_s3website": [], + "master_zone": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "zones": [ + { + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "endpoints": [ + "https://rook-ceph-rgw-test.rook-ceph.svc:443" + ] + } + ], + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd", + "sync_policy": { + "groups": [] + }, + "enabled_features": [ + "resharding" + ] +}` //#nosec G101 -- The credentials are just for the unit tests access_key = "VFKF8SSU9L3L2UR03Z8C" @@ -149,183 +227,68 @@ func TestReconcileRealm(t *testing.T) { assert.Nil(t, err) } -func TestApplyExpectedRadosNamespaceSettings(t *testing.T) { - dataPoolName := "testdatapool" - metaPrefix := "testmeta" - dataPrefix := "testdata" - var zoneConfig map[string]interface{} - - t.Run("fail when input empty", func(t *testing.T) { - input := map[string]interface{}{} - err := applyExpectedRadosNamespaceSettings(input, metaPrefix, dataPrefix, dataPoolName) - assert.Error(t, err) - assert.True(t, strings.Contains(err.Error(), "placement_pools")) - }) - t.Run("valid input", func(t *testing.T) { - assert.NoError(t, json.Unmarshal([]byte(objectZoneJson), &zoneConfig)) - assert.NoError(t, applyExpectedRadosNamespaceSettings(zoneConfig, metaPrefix, dataPrefix, dataPoolName)) - // validate a sampling of the updated fields - assert.Equal(t, metaPrefix+"log.notif", zoneConfig["notif_pool"]) - placementPools := zoneConfig["placement_pools"].([]interface{}) - placementPool := placementPools[0].(map[string]interface{}) - placementVals := placementPool["val"].(map[string]interface{}) - storageClasses := placementVals["storage_classes"].(map[string]interface{}) - stdStorageClass := storageClasses["STANDARD"].(map[string]interface{}) - assert.Equal(t, dataPoolName, stdStorageClass["data_pool"]) - }) - t.Run("placement pools empty", func(t *testing.T) { - // remove expected sections of the json and confirm that it returns an error without throwing an exception - emptyPlacementPoolsJson := `{ - "otp_pool": "rgw-meta-pool:store-a.otp", - "placement_pools": [] - }` - assert.NoError(t, json.Unmarshal([]byte(emptyPlacementPoolsJson), &zoneConfig)) - err := applyExpectedRadosNamespaceSettings(zoneConfig, metaPrefix, dataPrefix, dataPoolName) - assert.Error(t, err) - assert.True(t, strings.Contains(err.Error(), "no placement pools")) - }) - t.Run("placement pool value missing", func(t *testing.T) { - missingPoolValueJson := `{ - "otp_pool": "rgw-meta-pool:store-a.otp", - "placement_pools": [ - { - "key": "default-placement" - } - ] - }` - assert.NoError(t, json.Unmarshal([]byte(missingPoolValueJson), &zoneConfig)) - err := applyExpectedRadosNamespaceSettings(zoneConfig, metaPrefix, dataPrefix, dataPoolName) - assert.Error(t, err) - assert.Contains(t, err.Error(), "placement_pools[0].val") - }) - t.Run("storage classes missing", func(t *testing.T) { - storageClassesMissing := `{ - "otp_pool": "rgw-meta-pool:store-a.otp", - "placement_pools": [ - { - "key": "default-placement", - "val": { - "index_pool": "rgw-meta-pool:store-a.buckets.index" - } - } - ] - }` - assert.NoError(t, json.Unmarshal([]byte(storageClassesMissing), &zoneConfig)) - err := applyExpectedRadosNamespaceSettings(zoneConfig, metaPrefix, dataPrefix, dataPoolName) - assert.Error(t, err) - assert.Contains(t, err.Error(), "storage_classes") - }) - t.Run("standard storage class missing", func(t *testing.T) { - standardSCMissing := `{ - "otp_pool": "rgw-meta-pool:store-a.otp", - "placement_pools": [ - { - "key": "default-placement", - "val": { - "index_pool": "rgw-meta-pool:store-a.buckets.index", - "storage_classes": { - "BAD": { - "data_pool": "rgw-data-pool:store-a.buckets.data" - } - } - } - } - ] - }` - assert.NoError(t, json.Unmarshal([]byte(standardSCMissing), &zoneConfig)) - err := applyExpectedRadosNamespaceSettings(zoneConfig, metaPrefix, dataPrefix, dataPoolName) - assert.Error(t, err) - assert.Contains(t, err.Error(), "storage_classes.STANDARD") - }) - t.Run("no config missing", func(t *testing.T) { - nothingMissing := `{ - "otp_pool": "rgw-meta-pool:store-a.otp", - "placement_pools": [ - { - "key": "default-placement", - "val": { - "index_pool": "rgw-meta-pool:store-a.buckets.index", - "storage_classes": { - "STANDARD": { - "data_pool": "rgw-data-pool:store-a.buckets.data" - } - } - } - } - ] - }` - assert.NoError(t, json.Unmarshal([]byte(nothingMissing), &zoneConfig)) - err := applyExpectedRadosNamespaceSettings(zoneConfig, metaPrefix, dataPrefix, dataPoolName) - assert.NoError(t, err) - }) -} - -func TestSharedPoolsExist(t *testing.T) { - executor := &exectest.MockExecutor{} - poolJson := "" - mockExecutorFuncOutput := func(command string, args ...string) (string, error) { - logger.Infof("Command: %s %v", command, args) - if args[0] == "osd" && args[1] == "lspools" { - return poolJson, nil - } - return "", errors.Errorf("unexpected ceph command %q", args) - } - executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) { - return mockExecutorFuncOutput(command, args...) - } - context := &Context{Context: &clusterd.Context{Executor: executor}, Name: "myobj", clusterInfo: client.AdminTestClusterInfo("mycluster")} - sharedPools := cephv1.ObjectSharedPoolsSpec{ - MetadataPoolName: "metapool", - DataPoolName: "datapool", - } - poolJson = `[{"poolnum":1,"poolname":".mgr"},{"poolnum":13,"poolname":".rgw.root"}, - {"poolnum":14,"poolname":"rgw-meta-pool"},{"poolnum":15,"poolname":"rgw-data-pool"}]` - err := sharedPoolsExist(context, sharedPools) - assert.Error(t, err) - assert.Contains(t, err.Error(), "pools do not exist") - - sharedPools.MetadataPoolName = "rgw-meta-pool" - err = sharedPoolsExist(context, sharedPools) - assert.Error(t, err) - assert.Contains(t, err.Error(), "data pool does not exist") - - sharedPools.DataPoolName = "rgw-data-pool" - sharedPools.MetadataPoolName = "bad-pool" - err = sharedPoolsExist(context, sharedPools) - assert.Error(t, err) - assert.Contains(t, err.Error(), "metadata pool does not exist") - - sharedPools.MetadataPoolName = "rgw-meta-pool" - err = sharedPoolsExist(context, sharedPools) - assert.NoError(t, err) -} - func TestConfigureStoreWithSharedPools(t *testing.T) { - dataPoolAlreadySet := "datapool:store-a.buckets.data" + sharedMetaPoolAlreadySet, sharedDataPoolAlreadySet := "", "" zoneGetCalled := false zoneSetCalled := false + zoneGroupGetCalled := false + zoneGroupSetCalled := false placementModifyCalled := false mockExecutorFuncOutput := func(command string, args ...string) (string, error) { logger.Infof("Command: %s %v", command, args) if args[0] == "osd" && args[1] == "lspools" { - return `[{"poolnum":14,"poolname":"test-meta"},{"poolnum":15,"poolname":"test-data"}]`, nil + return `[{"poolnum":14,"poolname":"test-meta"},{"poolnum":15,"poolname":"test-data"},{"poolnum":16,"poolname":"fast-meta"},{"poolnum":17,"poolname":"fast-data"}]`, nil } return "", errors.Errorf("unexpected ceph command %q", args) } + executorFuncTimeout := func(timeout time.Duration, command string, args ...string) (string, error) { logger.Infof("CommandTimeout: %s %v", command, args) if args[0] == "zone" { if args[1] == "get" { zoneGetCalled = true - replaceDataPool := "rgw-data-pool:store-a.buckets.data" - return strings.Replace(objectZoneJson, replaceDataPool, dataPoolAlreadySet, -1), nil + if sharedDataPoolAlreadySet == "" && sharedMetaPoolAlreadySet == "" { + replaceDataPool := "rgw-data-pool:store-a.buckets.data" + return strings.Replace(objectZoneJson, replaceDataPool, "datapool:store-a.buckets.data", -1), nil + } + return fmt.Sprintf(objectZoneSharedPoolsJsonTempl, sharedMetaPoolAlreadySet, sharedDataPoolAlreadySet), nil } else if args[1] == "set" { zoneSetCalled = true + for _, arg := range args { + if !strings.HasPrefix(arg, "--infile=") { + continue + } + file := strings.TrimPrefix(arg, "--infile=") + inBytes, err := os.ReadFile(file) + if err != nil { + panic(err) + } + return string(inBytes), nil + } return objectZoneJson, nil } else if args[1] == "placement" && args[2] == "modify" { placementModifyCalled = true return objectZoneJson, nil } + } else if args[0] == "zonegroup" { + if args[1] == "get" { + zoneGroupGetCalled = true + return objectZonegroupJson, nil + } else if args[1] == "set" { + zoneGroupSetCalled = true + for _, arg := range args { + if !strings.HasPrefix(arg, "--infile=") { + continue + } + file := strings.TrimPrefix(arg, "--infile=") + inBytes, err := os.ReadFile(file) + if err != nil { + panic(err) + } + return string(inBytes), nil + } + return objectZonegroupJson, nil + } } return "", errors.Errorf("unexpected ceph command %q", args) } @@ -351,6 +314,8 @@ func TestConfigureStoreWithSharedPools(t *testing.T) { assert.False(t, zoneGetCalled) assert.False(t, zoneSetCalled) assert.False(t, placementModifyCalled) + assert.False(t, zoneGroupGetCalled) + assert.False(t, zoneGroupSetCalled) }) t.Run("configure the zone", func(t *testing.T) { sharedPools := cephv1.ObjectSharedPoolsSpec{ @@ -361,7 +326,27 @@ func TestConfigureStoreWithSharedPools(t *testing.T) { assert.NoError(t, err) assert.True(t, zoneGetCalled) assert.True(t, zoneSetCalled) - assert.True(t, placementModifyCalled) + assert.False(t, placementModifyCalled) // mock returns applied namespases, no workaround needed + assert.True(t, zoneGroupGetCalled) + assert.False(t, zoneGroupSetCalled) // zone group is set only if extra pool placements specified + }) + t.Run("configure with default placement", func(t *testing.T) { + sharedPools := cephv1.ObjectSharedPoolsSpec{ + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: defaultPlacementName, + MetadataPoolName: "test-meta", + DataPoolName: "test-data", + }, + }, + } + err := ConfigureSharedPoolsForZone(context, sharedPools) + assert.NoError(t, err) + assert.True(t, zoneGetCalled) + assert.True(t, zoneSetCalled) + assert.False(t, placementModifyCalled) // mock returns applied namespases, no workaround needed + assert.True(t, zoneGroupGetCalled) + assert.False(t, zoneGroupSetCalled) // zone group is set only if extra pool placements specified }) t.Run("data pool already set", func(t *testing.T) { // Simulate that the data pool has already been set and the zone update can be skipped @@ -369,15 +354,40 @@ func TestConfigureStoreWithSharedPools(t *testing.T) { MetadataPoolName: "test-meta", DataPoolName: "test-data", } - dataPoolAlreadySet = fmt.Sprintf("%s:%s.buckets.data", sharedPools.DataPoolName, context.Zone) + sharedMetaPoolAlreadySet, sharedDataPoolAlreadySet = "test-meta", "test-data" zoneGetCalled = false zoneSetCalled = false placementModifyCalled = false err := ConfigureSharedPoolsForZone(context, sharedPools) assert.True(t, zoneGetCalled) assert.False(t, zoneSetCalled) - assert.False(t, placementModifyCalled) + assert.False(t, placementModifyCalled) // mock returns applied namespases, no workaround needed assert.NoError(t, err) + assert.True(t, zoneGroupGetCalled) + assert.False(t, zoneGroupSetCalled) + }) + t.Run("configure with extra placement", func(t *testing.T) { + sharedPools := cephv1.ObjectSharedPoolsSpec{ + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: defaultPlacementName, + MetadataPoolName: "test-meta", + DataPoolName: "test-data", + }, + { + Name: "fast", + MetadataPoolName: "fast-meta", + DataPoolName: "fast-data", + }, + }, + } + err := ConfigureSharedPoolsForZone(context, sharedPools) + assert.NoError(t, err) + assert.True(t, zoneGetCalled) + assert.True(t, zoneSetCalled) + assert.False(t, placementModifyCalled) // mock returns applied namespases, no workaround needed + assert.True(t, zoneGroupGetCalled) + assert.True(t, zoneGroupSetCalled) }) } @@ -1482,3 +1492,486 @@ func TestListsAreEqual(t *testing.T) { }) } } + +func TestValidateObjectStorePoolsConfig(t *testing.T) { + type args struct { + metadataPool cephv1.PoolSpec + dataPool cephv1.PoolSpec + sharedPools cephv1.ObjectSharedPoolsSpec + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: nothing is set", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{}, + }, + wantErr: false, + }, + { + name: "valid: only metadata pool set", + args: args{ + metadataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{}, + }, + wantErr: false, + }, + { + name: "valid: only data pool set", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{}, + }, + wantErr: false, + }, + { + name: "valid: only metadata and data pools set", + args: args{ + metadataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + dataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{}, + }, + wantErr: false, + }, + { + name: "valid: only shared metadata pool set", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "test", + DataPoolName: "", + }, + }, + wantErr: false, + }, + { + name: "valid: only shared data pool set", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "test", + }, + }, + wantErr: false, + }, + { + name: "valid: only shared data and metaData pools set", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "test", + DataPoolName: "test", + }, + }, + wantErr: false, + }, + { + name: "valid: shared meta and non-shared data", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "test", + DataPoolName: "", + }, + }, + wantErr: false, + }, + { + name: "valid: shared data and non-shared meta", + args: args{ + metadataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "test", + }, + }, + wantErr: false, + }, + { + name: "invalid: shared and non-shared meta set", + args: args{ + metadataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + dataPool: cephv1.PoolSpec{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "test", + DataPoolName: "", + }, + }, + wantErr: true, + }, + { + name: "invalid: shared and non-shared data set", + args: args{ + metadataPool: cephv1.PoolSpec{}, + dataPool: cephv1.PoolSpec{ + FailureDomain: "host", + Replicated: cephv1.ReplicatedSpec{Size: 3}, + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "test", + }, + }, + wantErr: true, + }, + { + name: "invalid: placements invalid", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "same_name", + MetadataPoolName: "", + DataPoolName: "", + DataNonECPoolName: "", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + { + Name: "same_name", + MetadataPoolName: "", + DataPoolName: "", + DataNonECPoolName: "", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateObjectStorePoolsConfig(tt.args.metadataPool, tt.args.dataPool, tt.args.sharedPools); (err != nil) != tt.wantErr { + t.Errorf("ValidateObjectStorePoolsConfig() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_sharedPoolsExist(t *testing.T) { + type args struct { + existsInCluster []string + sharedPools cephv1.ObjectSharedPoolsSpec + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "all pool exists", + args: args{ + existsInCluster: []string{ + "meta", + "data", + "placement-meta", + "placement-data", + "placement-data-non-ec", + "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "meta pool not exists", + args: args{ + existsInCluster: []string{ + // "meta", + "data", + "placement-meta", + "placement-data", + "placement-data-non-ec", + "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "data pool not exists", + args: args{ + existsInCluster: []string{ + "meta", + // "data", + "placement-meta", + "placement-data", + "placement-data-non-ec", + "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "placement meta pool not exists", + args: args{ + existsInCluster: []string{ + "meta", + "data", + // "placement-meta", + "placement-data", + "placement-data-non-ec", + "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "placement data pool not exists", + args: args{ + existsInCluster: []string{ + "meta", + "data", + "placement-meta", + // "placement-data", + "placement-data-non-ec", + "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "placement data non ec pool not exists", + args: args{ + existsInCluster: []string{ + "meta", + "data", + "placement-meta", + "placement-data", + // "placement-data-non-ec", + "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "placement storage class pool not exists", + args: args{ + existsInCluster: []string{ + "meta", + "data", + "placement-meta", + "placement-data", + "placement-data-non-ec", + // "placement-sc-data", + }, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "placement-meta", + DataPoolName: "placement-data", + DataNonECPoolName: "placement-data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "placement-sc-data", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "empty pool names ignored", + args: args{ + existsInCluster: []string{}, + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "", + DataPoolName: "", + DataNonECPoolName: "", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "sc", + DataPoolName: "", + }, + }, + }, + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + executor := &exectest.MockExecutor{} + mockExecutorFuncOutput := func(command string, args ...string) (string, error) { + if args[0] == "osd" && args[1] == "lspools" { + pools := make([]string, len(tt.args.existsInCluster)) + for i, p := range tt.args.existsInCluster { + pools[i] = fmt.Sprintf(`{"poolnum":%d,"poolname":%q}`, i+1, p) + } + poolJson := fmt.Sprintf(`[%s]`, strings.Join(pools, ",")) + return poolJson, nil + } + return "", errors.Errorf("unexpected ceph command %q", args) + } + executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) { + return mockExecutorFuncOutput(command, args...) + } + context := &Context{Context: &clusterd.Context{Executor: executor}, Name: "myobj", clusterInfo: client.AdminTestClusterInfo("mycluster")} + + if err := sharedPoolsExist(context, tt.args.sharedPools); (err != nil) != tt.wantErr { + t.Errorf("sharedPoolsExist() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/operator/ceph/object/shared_pools.go b/pkg/operator/ceph/object/shared_pools.go new file mode 100644 index 000000000000..0ab62b8d71d1 --- /dev/null +++ b/pkg/operator/ceph/object/shared_pools.go @@ -0,0 +1,510 @@ +package object + +import ( + "encoding/json" + "fmt" + "os" + "path" + "sort" + + "github.com/pkg/errors" + cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" +) + +const ( + defaultPlacementName = "default" + defaultPlacementCephConfigName = "default-placement" + defaultPlacementStorageClass = "STANDARD" +) + +func IsNeedToCreateObjectStorePools(sharedPools cephv1.ObjectSharedPoolsSpec) bool { + for _, pp := range sharedPools.PoolPlacements { + if pp.Name == defaultPlacementName { + // No need to create pools. External pools from default placement will be used + return false + } + } + if sharedPools.MetadataPoolName != "" && sharedPools.DataPoolName != "" { + // No need to create pools. Shared pools will be used + return false + } + return true +} + +func validatePoolPlacements(placements []cephv1.PoolPlacementSpec) error { + names := make(map[string]struct{}, len(placements)) + for _, p := range placements { + if _, ok := names[p.Name]; ok { + return fmt.Errorf("invalidObjStorePoolCofig: invalid placement %s: placement names must be unique", p.Name) + } + names[p.Name] = struct{}{} + if err := validatePoolPlacementStorageClasses(p.StorageClasses); err != nil { + return fmt.Errorf("invalidObjStorePoolCofig: invalid placement %s: %w", p.Name, err) + } + } + return nil +} + +func validatePoolPlacementStorageClasses(scList []cephv1.PlacementStorageClassSpec) error { + names := make(map[string]struct{}, len(scList)) + for _, sc := range scList { + if sc.Name == defaultPlacementStorageClass { + return fmt.Errorf("invalid placement StorageClass %q: %q name is reserved", sc.Name, defaultPlacementStorageClass) + } + if _, ok := names[sc.Name]; ok { + return fmt.Errorf("invalid placement StorageClass %q: name must be unique", sc.Name) + } + names[sc.Name] = struct{}{} + } + return nil +} + +func adjustZonePlacementPools(zone map[string]interface{}, spec cephv1.ObjectSharedPoolsSpec) (map[string]interface{}, error) { + name, err := getObjProperty[string](zone, "name") + if err != nil { + return nil, fmt.Errorf("unable to get zone name: %w", err) + } + + //deep copy source zone + zone, err = deepCopyJson(zone) + if err != nil { + return nil, fmt.Errorf("unable to deep copy config for zone %s: %w", name, err) + } + + placements, err := getObjProperty[[]interface{}](zone, "placement_pools") + if err != nil { + return nil, fmt.Errorf("unable to get pool placements for zone %s: %w", name, err) + } + + fromSpec := toZonePlacementPools(spec, name) + + inConfig := map[string]struct{}{} + idxToRemove := map[int]struct{}{} + for i, p := range placements { + pObj, ok := p.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("unable to cast pool placement to object for zone %s: %+v", name, p) + } + placementID, err := getObjProperty[string](pObj, "key") + if err != nil { + return nil, fmt.Errorf("unable to get pool placement name for zone %s: %w", name, err) + } + // check if placement should be removed + if _, inSpec := fromSpec[placementID]; !inSpec && placementID != defaultPlacementCephConfigName { + // remove placement if it is not in spec, but don't remove default placement + idxToRemove[i] = struct{}{} + continue + } + // update placement with values from spec: + if pSpec, inSpec := fromSpec[placementID]; inSpec { + _, err = setObjProperty(pObj, pSpec.Val.IndexPool, "val", "index_pool") + if err != nil { + return nil, fmt.Errorf("unable to set index pool to pool placement %q for zone %q: %w", placementID, name, err) + } + _, err = setObjProperty(pObj, pSpec.Val.DataExtraPool, "val", "data_extra_pool") + if err != nil { + return nil, fmt.Errorf("unable to set data extra pool to pool placement %q for zone %q: %w", placementID, name, err) + } + scObj, err := toObj(pSpec.Val.StorageClasses) + if err != nil { + return nil, fmt.Errorf("unable convert to pool placement %q storage class for zone %q: %w", placementID, name, err) + } + + _, err = setObjProperty(pObj, scObj, "val", "storage_classes") + if err != nil { + return nil, fmt.Errorf("unable to set storage classes to pool placement %q for zone %q: %w", placementID, name, err) + } + inConfig[placementID] = struct{}{} + } + } + if len(idxToRemove) != 0 { + //delete placements from slice + updated := make([]interface{}, 0, len(placements)-len(idxToRemove)) + for i := range placements { + if _, ok := idxToRemove[i]; ok { + //remove + continue + } + updated = append(updated, placements[i]) + } + placements = updated + } + + // add new placements from spec: + for placementID, p := range fromSpec { + if _, ok := inConfig[placementID]; ok { + //already in config + continue + } + pObj, err := toObj(p) + if err != nil { + return nil, fmt.Errorf("unable convert pool placement %q for zone %q: %w", placementID, name, err) + } + placements = append(placements, pObj) + } + + _, err = setObjProperty(zone, placements, "placement_pools") + if err != nil { + return nil, fmt.Errorf("unable to set pool placements for zone %q: %w", name, err) + } + return zone, nil +} + +func getDefaultMetadataPool(spec cephv1.ObjectSharedPoolsSpec) string { + for _, p := range spec.PoolPlacements { + if p.Name == defaultPlacementName { + return p.MetadataPoolName + } + } + return spec.MetadataPoolName +} + +// toZonePlacementPools converts pool placement CRD definition to zone config json format structures +func toZonePlacementPools(spec cephv1.ObjectSharedPoolsSpec, ns string) map[string]ZonePlacementPool { + hasDefault := false + res := make(map[string]ZonePlacementPool, len(spec.PoolPlacements)+1) + for _, pp := range spec.PoolPlacements { + name := pp.Name + if pp.Name == defaultPlacementName { + hasDefault = true + name = defaultPlacementCephConfigName + } + res[name] = toZonePlacementPool(pp, ns) + } + if !hasDefault && spec.DataPoolName != "" && spec.MetadataPoolName != "" { + // set shared pools as default if no default placement was provided + res[defaultPlacementCephConfigName] = ZonePlacementPool{ + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + // The extra pool is for omap data for multi-part uploads, so we use + // the metadata pool instead of the data pool. + DataExtraPool: spec.MetadataPoolName + ":" + ns + ".buckets.non-ec", + IndexPool: spec.MetadataPoolName + ":" + ns + ".buckets.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: spec.DataPoolName + ":" + ns + ".buckets.data", + }, + }, + // Workaround: radosgw-admin set zone json command sets incorrect default value for placement inline_data field. + // So we should set default value (true) explicitly. + // See: https://tracker.ceph.com/issues/67933 + InlineData: true, + }, + } + } + return res +} + +func toZonePlacementPool(spec cephv1.PoolPlacementSpec, ns string) ZonePlacementPool { + placementNS := ns + if spec.Name != defaultPlacementName { + placementNS += "." + spec.Name + } + // The extra pool is for omap data for multi-part uploads, so we use + // the metadata pool instead of the data pool. + nonECPool := spec.MetadataPoolName + ":" + placementNS + ".data.non-ec" + if spec.DataNonECPoolName != "" { + nonECPool = spec.DataNonECPoolName + ":" + placementNS + ".data.non-ec" + } + + res := ZonePlacementPool{ + Key: spec.Name, + Val: ZonePlacementPoolVal{ + DataExtraPool: nonECPool, + IndexPool: spec.MetadataPoolName + ":" + placementNS + ".index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: spec.DataPoolName + ":" + placementNS + ".data", + }, + }, + // Workaround: radosgw-admin set zone json command sets incorrect default value for placement inline_data field. + // So we should set default value (true) explicitly. + // See: https://tracker.ceph.com/issues/67933 + InlineData: true, + }, + } + if res.Key == defaultPlacementName { + res.Key = defaultPlacementCephConfigName + } + for _, v := range spec.StorageClasses { + res.Val.StorageClasses[v.Name] = ZonePlacementStorageClass{ + DataPool: v.DataPoolName + ":" + ns + "." + v.Name, + } + } + return res +} + +func adjustZoneGroupPlacementTargets(group, zone map[string]interface{}) (map[string]interface{}, error) { + name, err := getObjProperty[string](group, "name") + if err != nil { + return nil, fmt.Errorf("unable to get zonegroup name: %w", err) + } + + //deep copy source group + group, err = deepCopyJson(group) + if err != nil { + return nil, fmt.Errorf("unable to deep copy config for zonegroup %s: %w", name, err) + } + + _, err = setObjProperty(group, defaultPlacementCephConfigName, "default_placement") + if err != nil { + return nil, fmt.Errorf("unable to set default_placement for zonegroup %s: %w", name, err) + } + + desiredTargets, err := createPlacementTargetsFromZonePoolPlacements(zone) + if err != nil { + return nil, fmt.Errorf("unable to create targets from placements for zonegroup %q: %w", name, err) + } + currentTargets, err := getObjProperty[[]interface{}](group, "placement_targets") + if err != nil { + return nil, fmt.Errorf("unable to get targets from placements for zonegroup %q: %w", name, err) + } + + applied := map[string]struct{}{} + idxToRemove := map[int]struct{}{} + for i, target := range currentTargets { + tObj, ok := target.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("unable to cast placement target to object for zonegroup %q: %+v", name, target) + } + tName, err := getObjProperty[string](tObj, "name") + if err != nil { + return nil, fmt.Errorf("unable to get placement target name for zonegroup %q: %w", name, err) + } + // update target: + if desired, ok := desiredTargets[tName]; ok { + sc := []interface{}{} + ok = castJson(desired.StorageClasses, &sc) + if ok { + _, err = setObjProperty(tObj, sc, "storage_classes") + } else { + _, err = setObjProperty(tObj, desired.StorageClasses, "storage_classes") + } + if err != nil { + return nil, fmt.Errorf("unable to set storage classes to pool placement target %q for zonegroup %q: %w", tName, name, err) + } + applied[tName] = struct{}{} + } else { + // remove target + idxToRemove[i] = struct{}{} + continue + } + } + if len(idxToRemove) != 0 { + //delete targets from slice + updated := make([]interface{}, 0, len(currentTargets)-len(idxToRemove)) + for i := range currentTargets { + if _, ok := idxToRemove[i]; ok { + //remove + continue + } + updated = append(updated, currentTargets[i]) + } + currentTargets = updated + } + + // add new targets: + for targetName, target := range desiredTargets { + if _, ok := applied[targetName]; ok { + //already in config + continue + } + tObj, err := toObj(target) + if err != nil { + return nil, fmt.Errorf("unable convert placement target %q for zonegroup %q: %w", targetName, name, err) + } + currentTargets = append(currentTargets, tObj) + } + + _, err = setObjProperty(group, currentTargets, "placement_targets") + if err != nil { + return nil, fmt.Errorf("unable to set placement targets for zonegroup %q: %w", name, err) + } + + return group, nil +} + +func createPlacementTargetsFromZonePoolPlacements(zone map[string]interface{}) (map[string]ZonegroupPlacementTarget, error) { + zoneName, err := getObjProperty[string](zone, "name") + if err != nil { + return nil, fmt.Errorf("unable to get zone name: %w", err) + } + + zonePoolPlacements, err := getObjProperty[[]interface{}](zone, "placement_pools") + if err != nil { + return nil, fmt.Errorf("unable to get pool placements for zone %q: %w", zoneName, err) + } + + res := make(map[string]ZonegroupPlacementTarget, len(zonePoolPlacements)) + for _, pp := range zonePoolPlacements { + ppObj, ok := pp.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("unable to cast zone pool placement to json obj for zone %q: %+v", zoneName, pp) + } + name, err := getObjProperty[string](ppObj, "key") + if err != nil { + return nil, fmt.Errorf("unable to get pool placement key for zone %q: %w", zoneName, err) + } + storClasses, err := getObjProperty[map[string]interface{}](ppObj, "val", "storage_classes") + if err != nil { + return nil, fmt.Errorf("unable to get pool placement storage classes for zone %q: %w", zoneName, err) + } + target := ZonegroupPlacementTarget{ + Name: name, + } + for sc := range storClasses { + target.StorageClasses = append(target.StorageClasses, sc) + } + sort.Strings(target.StorageClasses) + res[name] = target + } + return res, nil +} + +func getZoneJSON(objContext *Context) (map[string]interface{}, error) { + if objContext.Realm == "" { + return nil, fmt.Errorf("get zone: object store realm is missing from context") + } + realmArg := fmt.Sprintf("--rgw-realm=%s", objContext.Realm) + + if objContext.Zone == "" { + return nil, fmt.Errorf("get zone: object store zone is missing from context") + } + zoneArg := fmt.Sprintf("--rgw-zone=%s", objContext.Zone) + + logger.Debugf("get zone: rgw-realm=%s, rgw-zone=%s", objContext.Realm, objContext.Zone) + + jsonStr, err := RunAdminCommandNoMultisite(objContext, true, "zone", "get", realmArg, zoneArg) + if err != nil { + // This handles the case where the pod we use to exec command (act as a proxy) is not found/ready yet + // The caller can nicely handle the error and not overflow the op logs with misleading error messages + if kerrors.IsNotFound(err) { + return nil, err + } + return nil, errors.Wrap(err, "failed to get rgw zone group") + } + logger.Debugf("get zone success: rgw-realm=%s, rgw-zone=%s, res=%s", objContext.Realm, objContext.Zone, jsonStr) + res := map[string]interface{}{} + return res, json.Unmarshal([]byte(jsonStr), &res) +} + +func getZoneGroupJSON(objContext *Context) (map[string]interface{}, error) { + if objContext.Realm == "" { + return nil, fmt.Errorf("get zonegroup: object store realm is missing from context") + } + realmArg := fmt.Sprintf("--rgw-realm=%s", objContext.Realm) + + if objContext.Zone == "" { + return nil, fmt.Errorf("get zonegroup: object store zone is missing from context") + } + zoneArg := fmt.Sprintf("--rgw-zone=%s", objContext.Zone) + + if objContext.ZoneGroup == "" { + return nil, fmt.Errorf("get zonegroup: object store zonegroup is missing from context") + } + zoneGroupArg := fmt.Sprintf("--rgw-zonegroup=%s", objContext.ZoneGroup) + + logger.Debugf("get zonegroup: rgw-realm=%s, rgw-zone=%s, rgw-zonegroup=%s", objContext.Realm, objContext.Zone, objContext.ZoneGroup) + jsonStr, err := RunAdminCommandNoMultisite(objContext, true, "zonegroup", "get", realmArg, zoneGroupArg, zoneArg) + if err != nil { + // This handles the case where the pod we use to exec command (act as a proxy) is not found/ready yet + // The caller can nicely handle the error and not overflow the op logs with misleading error messages + if kerrors.IsNotFound(err) { + return nil, err + } + return nil, errors.Wrap(err, "failed to get rgw zone group") + } + logger.Debugf("get zonegroup success: rgw-realm=%s, rgw-zone=%s, rgw-zonegroup=%s, res=%s", objContext.Realm, objContext.Zone, objContext.ZoneGroup, jsonStr) + res := map[string]interface{}{} + return res, json.Unmarshal([]byte(jsonStr), &res) +} + +func updateZoneJSON(objContext *Context, zone map[string]interface{}) (map[string]interface{}, error) { + if objContext.Realm == "" { + return nil, fmt.Errorf("update zone: object store realm is missing from context") + } + realmArg := fmt.Sprintf("--rgw-realm=%s", objContext.Realm) + + if objContext.Zone == "" { + return nil, fmt.Errorf("update zone: object store zone is missing from context") + } + zoneArg := fmt.Sprintf("--rgw-zone=%s", objContext.Zone) + + configBytes, err := json.Marshal(zone) + if err != nil { + return nil, err + } + configFilename := path.Join(objContext.Context.ConfigDir, objContext.Name+".zonecfg") + if err := os.WriteFile(configFilename, configBytes, 0600); err != nil { + return nil, errors.Wrap(err, "failed to write zone config file") + } + defer os.Remove(configFilename) + + args := []string{"zone", "set", zoneArg, "--infile=" + configFilename, realmArg} + updatedBytes, err := RunAdminCommandNoMultisite(objContext, false, args...) + if err != nil { + return nil, errors.Wrap(err, "failed to set zone config") + } + logger.Debugf("update zone: %s json config updated value from %q to %q", objContext.Zone, string(configBytes), string(updatedBytes)) + updated := map[string]interface{}{} + err = json.Unmarshal([]byte(updatedBytes), &updated) + return updated, err +} + +func updateZoneGroupJSON(objContext *Context, group map[string]interface{}) (map[string]interface{}, error) { + if objContext.Realm == "" { + return nil, fmt.Errorf("update zonegroup: object store realm is missing from context") + } + realmArg := fmt.Sprintf("--rgw-realm=%s", objContext.Realm) + + if objContext.Zone == "" { + return nil, fmt.Errorf("update zonegroup: object store zone is missing from context") + } + zoneArg := fmt.Sprintf("--rgw-zone=%s", objContext.Zone) + + if objContext.ZoneGroup == "" { + return nil, fmt.Errorf("update zonegroup: object store zonegroup is missing from context") + } + zoneGroupArg := fmt.Sprintf("--rgw-zonegroup=%s", objContext.ZoneGroup) + + configBytes, err := json.Marshal(group) + if err != nil { + return nil, err + } + configFilename := path.Join(objContext.Context.ConfigDir, objContext.Name+".zonegroupcfg") + if err := os.WriteFile(configFilename, configBytes, 0600); err != nil { + return nil, errors.Wrap(err, "failed to write zonegroup config file") + } + defer os.Remove(configFilename) + + args := []string{"zonegroup", "set", zoneArg, "--infile=" + configFilename, realmArg, zoneGroupArg} + updatedBytes, err := RunAdminCommandNoMultisite(objContext, false, args...) + if err != nil { + return nil, errors.Wrap(err, "failed to set zone config") + } + updated := map[string]interface{}{} + err = json.Unmarshal([]byte(updatedBytes), &updated) + return updated, err +} + +type ZonegroupPlacementTarget struct { + Name string `json:"name"` + StorageClasses []string `json:"storage_classes"` +} + +type ZonePlacementPool struct { + Key string `json:"key"` + Val ZonePlacementPoolVal `json:"val"` +} + +type ZonePlacementPoolVal struct { + DataExtraPool string `json:"data_extra_pool"` + IndexPool string `json:"index_pool"` + StorageClasses map[string]ZonePlacementStorageClass `json:"storage_classes"` + InlineData bool `json:"inline_data"` +} + +type ZonePlacementStorageClass struct { + DataPool string `json:"data_pool"` +} diff --git a/pkg/operator/ceph/object/shared_pools_test.go b/pkg/operator/ceph/object/shared_pools_test.go new file mode 100644 index 000000000000..33f3e6ed2484 --- /dev/null +++ b/pkg/operator/ceph/object/shared_pools_test.go @@ -0,0 +1,1803 @@ +package object + +import ( + "encoding/json" + "reflect" + "testing" + + cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1" + "github.com/stretchr/testify/assert" +) + +func Test_validatePoolPlacements(t *testing.T) { + type args struct { + placements []cephv1.PoolPlacementSpec + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: names unique", + args: args{ + placements: []cephv1.PoolPlacementSpec{ + { + Name: "name1", + MetadataPoolName: "", // handled by CRD validation + DataPoolName: "", // handled by CRD validation + DataNonECPoolName: "", // handled by CRD validation + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + { + Name: "name2", + MetadataPoolName: "", // handled by CRD validation + DataPoolName: "", // handled by CRD validation + DataNonECPoolName: "", // handled by CRD validation + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + wantErr: false, + }, + { + name: "invalid: duplicate names", + args: args{ + placements: []cephv1.PoolPlacementSpec{ + { + Name: "name", + MetadataPoolName: "", // handled by CRD validation + DataPoolName: "", // handled by CRD validation + DataNonECPoolName: "", // handled by CRD validation + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + { + Name: "name", + MetadataPoolName: "", // handled by CRD validation + DataPoolName: "", // handled by CRD validation + DataNonECPoolName: "", // handled by CRD validation + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validatePoolPlacements(tt.args.placements); (err != nil) != tt.wantErr { + t.Errorf("validatePoolPlacements() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_validatePoolPlacementStorageClasses(t *testing.T) { + type args struct { + scList []cephv1.PlacementStorageClassSpec + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: unique names", + args: args{ + scList: []cephv1.PlacementStorageClassSpec{ + { + Name: "STANDARD_IA", + DataPoolName: "", // handled by CRD validation + }, + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "", // handled by CRD validation + }, + }, + }, + wantErr: false, + }, + { + name: "invalid: cannot override STANDARD", + args: args{ + scList: []cephv1.PlacementStorageClassSpec{ + { + Name: "STANDARD", + DataPoolName: "", // handled by CRD validation + }, + }, + }, + wantErr: true, + }, + { + name: "invalid: duplicate names", + args: args{ + scList: []cephv1.PlacementStorageClassSpec{ + { + Name: "STANDARD_IA", + DataPoolName: "", // handled by CRD validation + }, + { + Name: "STANDARD_IA", + DataPoolName: "", // handled by CRD validation + }, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := validatePoolPlacementStorageClasses(tt.args.scList); (err != nil) != tt.wantErr { + t.Errorf("validatePoolPlacementStorageClasses() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestIsNeedToCreateObjectStorePools(t *testing.T) { + type args struct { + sharedPools cephv1.ObjectSharedPoolsSpec + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "no need: both shared pools set", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{}, + }, + }, + want: false, + }, + { + name: "no need: default placement is set", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "default", + MetadataPoolName: "", // handled by CRD validation + DataPoolName: "", // handled by CRD validation + DataNonECPoolName: "", // handled by CRD validation + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + want: false, + }, + { + name: "need: only meta shared pool set", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{}, + }, + }, + want: true, + }, + { + name: "need: only data shared pool set", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{}, + }, + }, + want: true, + }, + { + name: "need: nothing is set", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{}, + }, + }, + want: true, + }, + { + name: "need: no default placement is set", + args: args{ + sharedPools: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "fast", + MetadataPoolName: "", // handled by CRD validation + DataPoolName: "", // handled by CRD validation + DataNonECPoolName: "", // handled by CRD validation + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsNeedToCreateObjectStorePools(tt.args.sharedPools); got != tt.want { + t.Errorf("IsNeedToCreateObjectStorePools() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_getDefaultMetadataPool(t *testing.T) { + type args struct { + spec cephv1.ObjectSharedPoolsSpec + } + tests := []struct { + name string + args args + want string + }{ + { + name: "default placement is returned", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "some_name", + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec1", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + { + Name: defaultPlacementName, + MetadataPoolName: "meta2", + DataPoolName: "data2", + DataNonECPoolName: "data-non-ec2", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + want: "meta2", + }, + { + name: "default placement override shared pool", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta-shared", + DataPoolName: "data-shared", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "some_name", + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec1", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + { + Name: defaultPlacementName, + MetadataPoolName: "meta2", + DataPoolName: "data2", + DataNonECPoolName: "data-non-ec2", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + want: "meta2", + }, + { + name: "shared pool returned if default placement not set", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta-shared", + DataPoolName: "data-shared", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "some_name", + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec1", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + want: "meta-shared", + }, + { + name: "no pool returned", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "data-shared", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "some_name", + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec1", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := getDefaultMetadataPool(tt.args.spec); got != tt.want { + t.Errorf("getDefaultMetadataPool() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_toZonePlacementPool(t *testing.T) { + type args struct { + spec cephv1.PoolPlacementSpec + ns string + } + tests := []struct { + name string + args args + want ZonePlacementPool + }{ + { + name: "map default placement without non-ec to config", + args: args{ + spec: cephv1.PoolPlacementSpec{ + Name: defaultPlacementName, + MetadataPoolName: "meta", + DataPoolName: "data", + DataNonECPoolName: "", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + ns: "ns", + }, + want: ZonePlacementPool{ + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + DataExtraPool: "meta:ns.data.non-ec", + IndexPool: "meta:ns.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data:ns.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:ns.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + { + name: "map default placement to config", + args: args{ + spec: cephv1.PoolPlacementSpec{ + Name: defaultPlacementName, + MetadataPoolName: "meta", + DataPoolName: "data", + DataNonECPoolName: "repl", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + ns: "ns", + }, + want: ZonePlacementPool{ + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + DataExtraPool: "repl:ns.data.non-ec", + IndexPool: "meta:ns.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data:ns.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:ns.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + { + name: "map default placement without extra SC to config", + args: args{ + spec: cephv1.PoolPlacementSpec{ + Name: defaultPlacementName, + MetadataPoolName: "meta", + DataPoolName: "data", + DataNonECPoolName: "repl", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + ns: "ns", + }, + want: ZonePlacementPool{ + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + DataExtraPool: "repl:ns.data.non-ec", + IndexPool: "meta:ns.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data:ns.data", + }, + }, + InlineData: true, + }, + }, + }, + { + name: "map non-default placement without non-ec to config", + args: args{ + spec: cephv1.PoolPlacementSpec{ + Name: "placement", + MetadataPoolName: "meta", + DataPoolName: "data", + DataNonECPoolName: "", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + ns: "ns", + }, + want: ZonePlacementPool{ + Key: "placement", + Val: ZonePlacementPoolVal{ + DataExtraPool: "meta:ns.placement.data.non-ec", + IndexPool: "meta:ns.placement.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data:ns.placement.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:ns.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + { + name: "map non-default placement to config", + args: args{ + spec: cephv1.PoolPlacementSpec{ + Name: "placement", + MetadataPoolName: "meta", + DataPoolName: "data", + DataNonECPoolName: "repl", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + ns: "ns", + }, + want: ZonePlacementPool{ + Key: "placement", + Val: ZonePlacementPoolVal{ + DataExtraPool: "repl:ns.placement.data.non-ec", + IndexPool: "meta:ns.placement.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data:ns.placement.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:ns.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, toZonePlacementPool(tt.args.spec, tt.args.ns)) + }) + } +} + +func Test_toZonePlacementPools(t *testing.T) { + type args struct { + spec cephv1.ObjectSharedPoolsSpec + ns string + } + tests := []struct { + name string + args args + want map[string]ZonePlacementPool + }{ + { + name: "backward compatible with prev shared pools", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + }, + ns: "rgw-instance", + }, + want: map[string]ZonePlacementPool{ + defaultPlacementCephConfigName: { + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + DataExtraPool: "meta:rgw-instance.buckets.non-ec", + IndexPool: "meta:rgw-instance.buckets.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + "STANDARD": { + DataPool: "data:rgw-instance.buckets.data", + }, + }, + InlineData: true, + }, + }, + }, + }, + { + name: "default placement overrides shared pools", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: defaultPlacementName, + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + }, + }, + ns: "rgw-instance", + }, + want: map[string]ZonePlacementPool{ + defaultPlacementCephConfigName: { + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + DataExtraPool: "data-non-ec:rgw-instance.data.non-ec", + IndexPool: "meta1:rgw-instance.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data1:rgw-instance.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:rgw-instance.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + }, + { + name: "no default set", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + }, + }, + ns: "rgw-instance", + }, + want: map[string]ZonePlacementPool{ + "placement": { + Key: "placement", + Val: ZonePlacementPoolVal{ + DataExtraPool: "data-non-ec:rgw-instance.placement.data.non-ec", + IndexPool: "meta1:rgw-instance.placement.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data1:rgw-instance.placement.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:rgw-instance.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + }, + { + name: "default shared and placement", + args: args{ + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta", + DataPoolName: "data", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "placement", + MetadataPoolName: "meta1", + DataPoolName: "data1", + DataNonECPoolName: "data-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }, + }, + }, + ns: "rgw-instance", + }, + want: map[string]ZonePlacementPool{ + defaultPlacementCephConfigName: { + Key: defaultPlacementCephConfigName, + Val: ZonePlacementPoolVal{ + DataExtraPool: "meta:rgw-instance.buckets.non-ec", + IndexPool: "meta:rgw-instance.buckets.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + "STANDARD": { + DataPool: "data:rgw-instance.buckets.data", + }, + }, + InlineData: true, + }, + }, + "placement": { + Key: "placement", + Val: ZonePlacementPoolVal{ + DataExtraPool: "data-non-ec:rgw-instance.placement.data.non-ec", + IndexPool: "meta1:rgw-instance.placement.index", + StorageClasses: map[string]ZonePlacementStorageClass{ + defaultPlacementStorageClass: { + DataPool: "data1:rgw-instance.placement.data", + }, + "REDUCED_REDUNDANCY": { + DataPool: "reduced:rgw-instance.REDUCED_REDUNDANCY", + }, + }, + InlineData: true, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, toZonePlacementPools(tt.args.spec, tt.args.ns)) + }) + } +} + +func Test_adjustZoneDefaultPools(t *testing.T) { + type args struct { + beforeJSON string + spec cephv1.ObjectSharedPoolsSpec + } + tests := []struct { + name string + args args + wantJSON string + wantChanged bool + wantErr bool + }{ + { + name: "nothing changed if default shared pool not set", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "DomainRoot", + "control_pool": "ControlPool", + "gc_pool": "GcPool", + "lc_pool": "LcPool", + "log_pool": "LogPool", + "intent_log_pool": "IntentLogPool", + "usage_log_pool": "UsageLogPool", + "roles_pool": "RolesPool", + "reshard_pool": "ReshardPool", + "user_keys_pool": "UserKeysPool", + "user_email_pool": "UserEmailPool", + "user_swift_pool": "UserSwiftPool", + "user_uid_pool": "UserUIDPool", + "otp_pool": "OtpPool", + "notif_pool": "NotifPool", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "non-default", + MetadataPoolName: "meta", + DataPoolName: "data", + }, + }, + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "DomainRoot", + "control_pool": "ControlPool", + "gc_pool": "GcPool", + "lc_pool": "LcPool", + "log_pool": "LogPool", + "intent_log_pool": "IntentLogPool", + "usage_log_pool": "UsageLogPool", + "roles_pool": "RolesPool", + "reshard_pool": "ReshardPool", + "user_keys_pool": "UserKeysPool", + "user_email_pool": "UserEmailPool", + "user_swift_pool": "UserSwiftPool", + "user_uid_pool": "UserUIDPool", + "otp_pool": "OtpPool", + "notif_pool": "NotifPool", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + wantChanged: false, + wantErr: false, + }, + { + name: "shared pool set", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "DomainRoot", + "control_pool": "ControlPool", + "gc_pool": "GcPool", + "lc_pool": "LcPool", + "log_pool": "LogPool", + "intent_log_pool": "IntentLogPool", + "usage_log_pool": "UsageLogPool", + "roles_pool": "RolesPool", + "reshard_pool": "ReshardPool", + "user_keys_pool": "UserKeysPool", + "user_email_pool": "UserEmailPool", + "user_swift_pool": "UserSwiftPool", + "user_uid_pool": "UserUIDPool", + "otp_pool": "OtpPool", + "notif_pool": "NotifPool", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta-pool", + DataPoolName: "data-pool", + PreserveRadosNamespaceDataOnDelete: false, + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "meta-pool:test.meta.root", + "control_pool": "meta-pool:test.control", + "gc_pool": "meta-pool:test.log.gc", + "lc_pool": "meta-pool:test.log.lc", + "log_pool": "meta-pool:test.log", + "intent_log_pool": "meta-pool:test.log.intent", + "usage_log_pool": "meta-pool:test.log.usage", + "roles_pool": "meta-pool:test.meta.roles", + "reshard_pool": "meta-pool:test.log.reshard", + "user_keys_pool": "meta-pool:test.meta.users.keys", + "user_email_pool": "meta-pool:test.meta.users.email", + "user_swift_pool": "meta-pool:test.meta.users.swift", + "user_uid_pool": "meta-pool:test.meta.users.uid", + "otp_pool": "meta-pool:test.otp", + "notif_pool": "meta-pool:test.log.notif", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + wantChanged: true, + wantErr: false, + }, + { + name: "config equals to spec: no changes needed", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "meta-pool:test.meta.root", + "control_pool": "meta-pool:test.control", + "gc_pool": "meta-pool:test.log.gc", + "lc_pool": "meta-pool:test.log.lc", + "log_pool": "meta-pool:test.log", + "intent_log_pool": "meta-pool:test.log.intent", + "usage_log_pool": "meta-pool:test.log.usage", + "roles_pool": "meta-pool:test.meta.roles", + "reshard_pool": "meta-pool:test.log.reshard", + "user_keys_pool": "meta-pool:test.meta.users.keys", + "user_email_pool": "meta-pool:test.meta.users.email", + "user_swift_pool": "meta-pool:test.meta.users.swift", + "user_uid_pool": "meta-pool:test.meta.users.uid", + "otp_pool": "meta-pool:test.otp", + "notif_pool": "meta-pool:test.log.notif", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta-pool", + DataPoolName: "data-pool", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{}, + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "meta-pool:test.meta.root", + "control_pool": "meta-pool:test.control", + "gc_pool": "meta-pool:test.log.gc", + "lc_pool": "meta-pool:test.log.lc", + "log_pool": "meta-pool:test.log", + "intent_log_pool": "meta-pool:test.log.intent", + "usage_log_pool": "meta-pool:test.log.usage", + "roles_pool": "meta-pool:test.meta.roles", + "reshard_pool": "meta-pool:test.log.reshard", + "user_keys_pool": "meta-pool:test.meta.users.keys", + "user_email_pool": "meta-pool:test.meta.users.email", + "user_swift_pool": "meta-pool:test.meta.users.swift", + "user_uid_pool": "meta-pool:test.meta.users.uid", + "otp_pool": "meta-pool:test.otp", + "notif_pool": "meta-pool:test.log.notif", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +} +`, + wantChanged: false, + wantErr: false, + }, + { + name: "default placement pool overrides shared pool", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "DomainRoot", + "control_pool": "ControlPool", + "gc_pool": "GcPool", + "lc_pool": "LcPool", + "log_pool": "LogPool", + "intent_log_pool": "IntentLogPool", + "usage_log_pool": "UsageLogPool", + "roles_pool": "RolesPool", + "reshard_pool": "ReshardPool", + "user_keys_pool": "UserKeysPool", + "user_email_pool": "UserEmailPool", + "user_swift_pool": "UserSwiftPool", + "user_uid_pool": "UserUIDPool", + "otp_pool": "OtpPool", + "notif_pool": "NotifPool", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "shared-meta-pool", + DataPoolName: "shared-data-pool", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: defaultPlacementName, + MetadataPoolName: "meta-pool", + DataPoolName: "data-pool", + }, + }, + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "domain_root": "meta-pool:test.meta.root", + "control_pool": "meta-pool:test.control", + "gc_pool": "meta-pool:test.log.gc", + "lc_pool": "meta-pool:test.log.lc", + "log_pool": "meta-pool:test.log", + "intent_log_pool": "meta-pool:test.log.intent", + "usage_log_pool": "meta-pool:test.log.usage", + "roles_pool": "meta-pool:test.meta.roles", + "reshard_pool": "meta-pool:test.log.reshard", + "user_keys_pool": "meta-pool:test.meta.users.keys", + "user_email_pool": "meta-pool:test.meta.users.email", + "user_swift_pool": "meta-pool:test.meta.users.swift", + "user_uid_pool": "meta-pool:test.meta.users.uid", + "otp_pool": "meta-pool:test.otp", + "notif_pool": "meta-pool:test.log.notif", + "system_key": { + "access_key": "AccessKey", + "secret_key": "SecretKey" + }, + "placement_pools": [], + "realm_id": "29e28253-be54-4581-90dd-206020d2fcdd" +}`, + wantChanged: true, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + srcZone := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.beforeJSON), &srcZone) + assert.NoError(t, err) + changedZone, err := adjustZoneDefaultPools(srcZone, tt.args.spec) + + // check that source was not modified + orig := map[string]interface{}{} + jErr := json.Unmarshal([]byte(tt.args.beforeJSON), &orig) + assert.NoError(t, jErr) + assert.EqualValues(t, orig, srcZone, "src was not modified") + + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.wantChanged, !reflect.DeepEqual(srcZone, changedZone)) + bytes, err := json.Marshal(&changedZone) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantJSON, string(bytes)) + }) + } +} + +func Test_adjustZonePlacementPools(t *testing.T) { + type args struct { + beforeJSON string + spec cephv1.ObjectSharedPoolsSpec + } + tests := []struct { + name string + args args + wantJSON string + wantChanged bool + wantErr bool + }{ + { + name: "no changes: shared spec not set", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 0, + "inline_data": true + } + } + ] +}`, + spec: cephv1.ObjectSharedPoolsSpec{}, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 0, + "inline_data": true + } + } + ] +}`, + wantChanged: false, + wantErr: false, + }, + { + name: "no changes: spec equal to config", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "meta-pool:test.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "data-pool:test.buckets.data" + } + }, + "data_extra_pool": "meta-pool:test.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + } + ] +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "meta-pool", + DataPoolName: "data-pool", + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "meta-pool:test.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "data-pool:test.buckets.data" + } + }, + "data_extra_pool": "meta-pool:test.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + } + ] +}`, + wantChanged: false, + wantErr: false, + }, + { + name: "default placement is preserved when non-default placement added", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + } + ] +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{{ + Name: "fast", + MetadataPoolName: "fast-meta", + DataPoolName: "fast-data", + DataNonECPoolName: "fast-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{ + { + Name: "REDUCED_REDUNDANCY", + DataPoolName: "reduced", + }, + }, + }}, + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + }, + { + "key": "fast", + "val": { + "index_pool": "fast-meta:test.fast.index", + "storage_classes": { + "STANDARD": { + "data_pool": "fast-data:test.fast.data" + }, + "REDUCED_REDUNDANCY": { + "data_pool": "reduced:test.REDUCED_REDUNDANCY" + } + }, + "data_extra_pool": "fast-non-ec:test.fast.data.non-ec", + "inline_data": true + } + } + + ] +}`, + wantChanged: true, + wantErr: false, + }, + { + name: "delete placement", + args: args{ + beforeJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + }, + { + "key": "fast", + "val": { + "index_pool": "fast-meta:test.fast.index", + "storage_classes": { + "STANDARD": { + "data_pool": "fast-data:test.fast.data" + } + }, + "data_extra_pool": "fast-non-ec:test.fast.data.non-ec", + "index_type": 0, + "inline_data": true + } + }, + { + "key": "slow", + "val": { + "index_pool": "slow-meta:test.slow.index", + "storage_classes": { + "STANDARD": { + "data_pool": "slow-data:test.slow.data" + } + }, + "data_extra_pool": "slow-non-ec:test.slow.data.non-ec", + "index_type": 0, + "inline_data": false + } + } + ] +}`, + spec: cephv1.ObjectSharedPoolsSpec{ + MetadataPoolName: "", + DataPoolName: "", + PreserveRadosNamespaceDataOnDelete: false, + PoolPlacements: []cephv1.PoolPlacementSpec{ + { + Name: "slow", + MetadataPoolName: "slow-meta", + DataPoolName: "slow-data", + DataNonECPoolName: "slow-non-ec", + StorageClasses: []cephv1.PlacementStorageClassSpec{}, + }, + }, + }, + }, + wantJSON: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + }, + { + "key": "slow", + "val": { + "index_pool": "slow-meta:test.slow.index", + "storage_classes": { + "STANDARD": { + "data_pool": "slow-data:test.slow.data" + } + }, + "data_extra_pool": "slow-non-ec:test.slow.data.non-ec", + "index_type": 0, + "inline_data": false + } + } + ] +}`, + wantChanged: true, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + srcZone := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.beforeJSON), &srcZone) + assert.NoError(t, err) + changedZone, err := adjustZonePlacementPools(srcZone, tt.args.spec) + // check that source zone was not modified: + orig := map[string]interface{}{} + jErr := json.Unmarshal([]byte(tt.args.beforeJSON), &orig) + assert.NoError(t, jErr) + assert.EqualValues(t, srcZone, orig, "source obj was not modified") + + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + bytes, err := json.Marshal(&changedZone) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantJSON, string(bytes)) + + assert.EqualValues(t, tt.wantChanged, !reflect.DeepEqual(srcZone, changedZone)) + }) + } +} + +func Test_adjustZoneGroupPlacementTargets(t *testing.T) { + type args struct { + zone string + groupBefore string + } + tests := []struct { + name string + args args + wantGroup string + wantChanged bool + wantErr bool + }{ + { + name: "nothing changed", + args: args{ + groupBefore: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + zone: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + } + ] +}`, + }, + wantGroup: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + wantChanged: false, + wantErr: false, + }, + { + name: "default changed", + args: args{ + groupBefore: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "some-placement", + "enabled_features": [ + "resharding" + ] +}`, + zone: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + } + ] +}`, + }, + wantGroup: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + wantChanged: true, + wantErr: false, + }, + { + name: "storage class added", + args: args{ + groupBefore: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + zone: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + }, + "REDUCED_REDUNDANCY": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + } + ] +}`, + }, + wantGroup: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "REDUCED_REDUNDANCY","STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + wantChanged: true, + wantErr: false, + }, + { + name: "placement added", + args: args{ + groupBefore: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + zone: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + }, + "REDUCED_REDUNDANCY": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec" + } + }, + { + "key": "slow", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec" + } + } + ] +}`, + }, + wantGroup: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "REDUCED_REDUNDANCY","STANDARD" + ] + }, + { + "name": "slow", + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + wantChanged: true, + wantErr: false, + }, + { + name: "placement and sc removed", + args: args{ + groupBefore: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "REDUCED_REDUNDANCY","STANDARD" + ] + }, + { + "name": "slow", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + zone: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec" + } + } + ] +}`, + }, + wantGroup: `{ + "id": "610c9e3d-19e7-40b0-9f88-03319c4bc65a", + "name": "test", + "placement_targets": [ + { + "name": "default-placement", + "tags": [], + "storage_classes": [ + "STANDARD" + ] + } + ], + "default_placement": "default-placement", + "enabled_features": [ + "resharding" + ] +}`, + wantChanged: true, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + zj := map[string]interface{}{} + err := json.Unmarshal([]byte(tt.args.zone), &zj) + assert.NoError(t, err) + srcGroup := map[string]interface{}{} + err = json.Unmarshal([]byte(tt.args.groupBefore), &srcGroup) + assert.NoError(t, err) + changedGroup, err := adjustZoneGroupPlacementTargets(srcGroup, zj) + + orig := map[string]interface{}{} + jErr := json.Unmarshal([]byte(tt.args.groupBefore), &orig) + assert.NoError(t, jErr) + assert.EqualValues(t, orig, srcGroup, "src was not modified") + + if tt.wantErr { + assert.Error(t, err) + return + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.wantChanged, !reflect.DeepEqual(srcGroup, changedGroup)) + bytes, err := json.Marshal(changedGroup) + assert.NoError(t, err) + assert.JSONEq(t, tt.wantGroup, string(bytes)) + }) + } +} + +func Test_createPlacementTargetsFromZonePoolPlacements(t *testing.T) { + type args struct { + zone string + } + tests := []struct { + name string + args args + want map[string]ZonegroupPlacementTarget + wantErr bool + }{ + { + name: "", + args: args{ + zone: `{ + "id": "f539c2c0-e1ed-4c42-9294-41742352eeae", + "name": "test", + "placement_pools": [ + { + "key": "default-placement", + "val": { + "index_pool": "test.rgw.buckets.index", + "storage_classes": { + "STANDARD": { + "data_pool": "test.rgw.buckets.data" + }, + "REDUCED_REDUNDANCY": { + "data_pool": "test.rgw.buckets.data" + } + }, + "data_extra_pool": "test.rgw.buckets.non-ec", + "index_type": 5, + "inline_data": true + } + }, + { + "key": "slow", + "val": { + "index_pool": "slow-meta:test.slow.index", + "storage_classes": { + "STANDARD": { + "data_pool": "slow-data:test.slow.data" + } + }, + "data_extra_pool": "slow-non-ec:test.slow.data.non-ec", + "index_type": 0, + "inline_data": true + } + } + ] +}`, + }, + want: map[string]ZonegroupPlacementTarget{ + "default-placement": { + Name: "default-placement", + StorageClasses: []string{"REDUCED_REDUNDANCY", "STANDARD"}, + }, + "slow": { + Name: "slow", + StorageClasses: []string{"STANDARD"}, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + zo := map[string]interface{}{} + _ = json.Unmarshal([]byte(tt.args.zone), &zo) + got, err := createPlacementTargetsFromZonePoolPlacements(zo) + if (err != nil) != tt.wantErr { + t.Errorf("createPlacementTargetsFromZonePoolPlacements() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("createPlacementTargetsFromZonePoolPlacements() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/operator/ceph/object/zone/controller.go b/pkg/operator/ceph/object/zone/controller.go index 8d787b06340d..e809caaac55e 100644 --- a/pkg/operator/ceph/object/zone/controller.go +++ b/pkg/operator/ceph/object/zone/controller.go @@ -289,16 +289,22 @@ func (r *ReconcileObjectZone) createorUpdateCephZone(zone *cephv1.CephObjectZone func (r *ReconcileObjectZone) createPoolsAndZone(objContext *object.Context, zone *cephv1.CephObjectZone, realmName string, zoneIsMaster bool) error { // create pools for zone logger.Debugf("creating pools ceph zone %q", zone.Name) + err := object.ValidateObjectStorePoolsConfig(zone.Spec.MetadataPool, zone.Spec.DataPool, zone.Spec.SharedPools) + if err != nil { + return fmt.Errorf("invalid zone pools config: %w", err) + } + if object.IsNeedToCreateObjectStorePools(zone.Spec.SharedPools) { + err = object.CreateObjectStorePools(objContext, r.clusterSpec, zone.Spec.MetadataPool, zone.Spec.DataPool) + if err != nil { + return fmt.Errorf("unable to create pools for zone: %w", err) + } + logger.Debugf("created pools ceph zone %q", zone.Name) + } + realmArg := fmt.Sprintf("--rgw-realm=%s", realmName) zoneGroupArg := fmt.Sprintf("--rgw-zonegroup=%s", zone.Spec.ZoneGroup) zoneArg := fmt.Sprintf("--rgw-zone=%s", zone.Name) - err := object.ConfigurePools(objContext, r.clusterSpec, zone.Spec.MetadataPool, zone.Spec.DataPool, zone.Spec.SharedPools) - if err != nil { - return errors.Wrapf(err, "failed to create pools for zone %v", zone.Name) - } - logger.Debugf("created pools ceph zone %q", zone.Name) - accessKeyArg, secretKeyArg, err := object.GetRealmKeyArgs(r.opManagerContext, r.context, realmName, zone.Namespace) if err != nil { return errors.Wrap(err, "failed to get keys for realm") @@ -326,6 +332,12 @@ func (r *ReconcileObjectZone) createPoolsAndZone(objContext *object.Context, zon return errors.Wrapf(err, "failed to configure rados namespaces for zone") } + // Commit rgw zone config changes + err = object.CommitConfigChanges(objContext) + if err != nil { + return errors.Wrapf(err, "failed to commit zone config changes") + } + return nil } @@ -412,6 +424,7 @@ func (r *ReconcileObjectZone) updateStatus(observedGeneration int64, name types. } logger.Debugf("object zone %q status updated to %q", name, status) } + func (r *ReconcileObjectZone) deleteZone(objContext *object.Context) error { realmArg := fmt.Sprintf("--rgw-realm=%s", objContext.Realm) // zoneGroupArg := fmt.Sprintf("--rgw-zonegroup=%s", objContext.ZoneGroup) @@ -481,6 +494,7 @@ func decodePoolPrefixfromZone(data string) (string, error) { s := strings.Split(domain.DomainRoot, ".rgw.") return s[0], err } + func (r *ReconcileObjectZone) deleteCephObjectZone(zone *cephv1.CephObjectZone, realmName string) (reconcile.Result, error) { logger.Debugf("deleting zone CR %q", zone.Name) objContext := object.NewContext(r.context, r.clusterInfo, zone.Name) From d041be4bcf25d4e67829f9de308e406396cbf8e6 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Fri, 6 Sep 2024 16:07:11 +0200 Subject: [PATCH 04/54] csi: update to new cephcsi release we have 3.12.2 as the new cephcsi release updating the rook to use the same. Signed-off-by: Madhu Rajanna --- Documentation/Helm-Charts/operator-chart.md | 2 +- .../Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md | 6 +++--- .../Storage-Configuration/Ceph-CSI/custom-images.md | 2 +- deploy/charts/rook-ceph/values.yaml | 2 +- deploy/examples/images.txt | 2 +- deploy/examples/operator-openshift.yaml | 2 +- deploy/examples/operator.yaml | 2 +- pkg/operator/ceph/csi/spec.go | 2 +- pkg/operator/ceph/csi/util_test.go | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Documentation/Helm-Charts/operator-chart.md b/Documentation/Helm-Charts/operator-chart.md index f3816c76c320..7ff471e7df16 100644 --- a/Documentation/Helm-Charts/operator-chart.md +++ b/Documentation/Helm-Charts/operator-chart.md @@ -61,7 +61,7 @@ The following table lists the configurable parameters of the rook-operator chart | `csi.cephFSPluginUpdateStrategy` | CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate | `RollingUpdate` | | `csi.cephFSPluginUpdateStrategyMaxUnavailable` | A maxUnavailable parameter of CSI cephFS plugin daemonset update strategy. | `1` | | `csi.cephcsi.repository` | Ceph CSI image repository | `"quay.io/cephcsi/cephcsi"` | -| `csi.cephcsi.tag` | Ceph CSI image tag | `"v3.12.0"` | +| `csi.cephcsi.tag` | Ceph CSI image tag | `"v3.12.2"` | | `csi.cephfsLivenessMetricsPort` | CSI CephFS driver metrics port | `9081` | | `csi.cephfsPodLabels` | Labels to add to the CSI CephFS Deployments and DaemonSets Pods | `nil` | | `csi.clusterName` | Cluster name identifier to set as metadata on the CephFS subvolume and RBD images. This will be useful in cases like for example, when two container orchestrator clusters (Kubernetes/OCP) are using a single ceph cluster | `nil` | diff --git a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md index b904d2da8ab5..d81f55ebf2c2 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md +++ b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md @@ -210,10 +210,10 @@ CSI-Addons supports the following operations: Ceph-CSI supports encrypting PersistentVolumeClaims (PVCs) for both RBD and CephFS. This can be achieved using LUKS for RBD and fscrypt for CephFS. More details on encrypting RBD PVCs can be found -[here](https://github.com/ceph/ceph-csi/blob/v3.12.0/docs/deploy-rbd.md#encryption-for-rbd-volumes), +[here](https://github.com/ceph/ceph-csi/blob/v3.12.2/docs/deploy-rbd.md#encryption-for-rbd-volumes), which includes a full list of supported encryption configurations. -More details on encrypting CephFS PVCs can be found [here](https://github.com/ceph/ceph-csi/blob/v3.12.0/docs/deploy-cephfs.md#cephfs-volume-encryption). -A sample KMS configmap can be found [here](https://github.com/ceph/ceph-csi/blob/v3.12.0/examples/kms/vault/kms-config.yaml). +More details on encrypting CephFS PVCs can be found [here](https://github.com/ceph/ceph-csi/blob/v3.12.2/docs/deploy-cephfs.md#cephfs-volume-encryption). +A sample KMS configmap can be found [here](https://github.com/ceph/ceph-csi/blob/v3.12.2/examples/kms/vault/kms-config.yaml). !!! note Not all KMS are compatible with fscrypt. Generally, KMS that either store secrets to use directly (like Vault) diff --git a/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md b/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md index e3dedf6351c6..8629bbcc1b55 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md +++ b/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md @@ -18,7 +18,7 @@ kubectl -n $ROOK_OPERATOR_NAMESPACE edit configmap rook-ceph-operator-config The default upstream images are included below, which you can change to your desired images. ```yaml -ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.12.0" +ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.12.2" ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1" ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.0.1" ROOK_CSI_ATTACHER_IMAGE: "registry.k8s.io/sig-storage/csi-attacher:v4.6.1" diff --git a/deploy/charts/rook-ceph/values.yaml b/deploy/charts/rook-ceph/values.yaml index 1b931a492693..387712a37e2f 100644 --- a/deploy/charts/rook-ceph/values.yaml +++ b/deploy/charts/rook-ceph/values.yaml @@ -487,7 +487,7 @@ csi: # -- Ceph CSI image repository repository: quay.io/cephcsi/cephcsi # -- Ceph CSI image tag - tag: v3.12.0 + tag: v3.12.2 registrar: # -- Kubernetes CSI registrar image repository diff --git a/deploy/examples/images.txt b/deploy/examples/images.txt index 12ccd7dfd6ee..faab1198c12c 100644 --- a/deploy/examples/images.txt +++ b/deploy/examples/images.txt @@ -2,7 +2,7 @@ gcr.io/k8s-staging-sig-storage/objectstorage-sidecar:v20240513-v0.1.0-35-gefb3255 quay.io/ceph/ceph:v18.2.4 quay.io/ceph/cosi:v0.1.2 - quay.io/cephcsi/cephcsi:v3.12.0 + quay.io/cephcsi/cephcsi:v3.12.2 quay.io/csiaddons/k8s-sidecar:v0.9.1 registry.k8s.io/sig-storage/csi-attacher:v4.6.1 registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1 diff --git a/deploy/examples/operator-openshift.yaml b/deploy/examples/operator-openshift.yaml index 7d0c052d59e2..396f022dd420 100644 --- a/deploy/examples/operator-openshift.yaml +++ b/deploy/examples/operator-openshift.yaml @@ -197,7 +197,7 @@ data: # The default version of CSI supported by Rook will be started. To change the version # of the CSI driver to something other than what is officially supported, change # these images to the desired release of the CSI driver. - # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.12.0" + # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.12.2" # ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1" # ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.11.1" # ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.0.1" diff --git a/deploy/examples/operator.yaml b/deploy/examples/operator.yaml index 7f86068f50d9..1d60f5638559 100644 --- a/deploy/examples/operator.yaml +++ b/deploy/examples/operator.yaml @@ -127,7 +127,7 @@ data: # The default version of CSI supported by Rook will be started. To change the version # of the CSI driver to something other than what is officially supported, change # these images to the desired release of the CSI driver. - # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.12.0" + # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:3.12.2" # ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1" # ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.11.1" # ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.0.1" diff --git a/pkg/operator/ceph/csi/spec.go b/pkg/operator/ceph/csi/spec.go index d63e7bc9da2b..b3033f15cdeb 100644 --- a/pkg/operator/ceph/csi/spec.go +++ b/pkg/operator/ceph/csi/spec.go @@ -151,7 +151,7 @@ var ( // manually challenging. var ( // image names - DefaultCSIPluginImage = "quay.io/cephcsi/cephcsi:v3.12.0" + DefaultCSIPluginImage = "quay.io/cephcsi/cephcsi:v3.12.2" DefaultRegistrarImage = "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1" DefaultProvisionerImage = "registry.k8s.io/sig-storage/csi-provisioner:v5.0.1" DefaultAttacherImage = "registry.k8s.io/sig-storage/csi-attacher:v4.6.1" diff --git a/pkg/operator/ceph/csi/util_test.go b/pkg/operator/ceph/csi/util_test.go index 2308d426e14d..3c8afc0ba40d 100644 --- a/pkg/operator/ceph/csi/util_test.go +++ b/pkg/operator/ceph/csi/util_test.go @@ -284,7 +284,7 @@ func Test_getImage(t *testing.T) { args: args{ data: map[string]string{}, settingName: "ROOK_CSI_CEPH_IMAGE", - defaultImage: "quay.io/cephcsi/cephcsi:v3.12.0", + defaultImage: "quay.io/cephcsi/cephcsi:v3.12.2", }, want: DefaultCSIPluginImage, }, From d9d0d8e1d37cdb339aa8f3998d660d418ab83bcb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 28 Aug 2024 10:00:25 +0200 Subject: [PATCH 05/54] ci: rename 'check-helm-docs' to 'check.helm-docs This makes the naming of ci-related make targets more systematic and consistent. It is based on PR https://github.com/rook/rook/pull/14672 and continues the pattern started in that PR. Signed-off-by: Michael Adam --- .github/workflows/docs-check.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index 1a13e842d604..c110b2b7dc07 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -43,7 +43,7 @@ jobs: !Documentation/Helm-Charts - name: Check helm-docs - run: make check-helm-docs + run: make check.helm-docs - name: Check docs run: make check.docs - name: Install mkdocs and dependencies diff --git a/Makefile b/Makefile index 825664cf7937..6fef6948bb21 100644 --- a/Makefile +++ b/Makefile @@ -201,7 +201,7 @@ helm-docs: $(HELM_DOCS) ## Use helm-docs to generate documentation from helm cha -t ../../../Documentation/Helm-Charts/ceph-cluster-chart.gotmpl.md \ -t ../../../Documentation/Helm-Charts/_templates.gotmpl -check-helm-docs: +check.helm-docs: @$(MAKE) helm-docs @git diff --exit-code || { \ echo "Please run 'make helm-docs' locally, commit the updated docs, and push the change. See https://rook.io/docs/rook/latest/Contributing/documentation/#making-docs" ; \ From a16ad75c929cce19ab29cda2fabea80fd61eb40f Mon Sep 17 00:00:00 2001 From: subhamkrai Date: Fri, 6 Sep 2024 16:59:04 +0530 Subject: [PATCH 06/54] csi: stop deleting csi-operator resources to keep it simple we'll not delete the csi-operator resources we'll only document this for users who want to switch to csi-drivers. Anyways by next release we'll only support csi-operator only. Signed-off-by: subhamkrai --- pkg/operator/ceph/csi/controller.go | 5 --- pkg/operator/ceph/csi/operator_config.go | 17 ---------- pkg/operator/ceph/csi/spec.go | 43 ------------------------ 3 files changed, 65 deletions(-) diff --git a/pkg/operator/ceph/csi/controller.go b/pkg/operator/ceph/csi/controller.go index f5341a48325f..b93fe7a09bb8 100644 --- a/pkg/operator/ceph/csi/controller.go +++ b/pkg/operator/ceph/csi/controller.go @@ -150,7 +150,6 @@ var reconcileSaveCSIDriverOptions = SaveCSIDriverOptions func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, error) { // reconcileResult is used to communicate the result of the reconciliation back to the caller var reconcileResult reconcile.Result - var clusterNamespace string ownerRef, err := k8sutil.GetDeploymentOwnerReference(r.opManagerContext, r.context.Clientset, os.Getenv(k8sutil.PodNameEnvVar), r.opConfig.OperatorNamespace) if err != nil { @@ -295,7 +294,6 @@ func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, e return opcontroller.ImmediateRetryResult, errors.Wrapf(err, "failed to load cluster info for cluster %q", cluster.Name) } clusterInfo.OwnerInfo = k8sutil.NewOwnerInfo(&cephClusters.Items[i], r.scheme) - clusterNamespace = clusterInfo.Namespace // is holder enabled for this cluster? thisHolderEnabled := (!csiHostNetworkEnabled || cluster.Spec.Network.IsMultus()) && !csiDisableHolders @@ -331,13 +329,10 @@ func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, e return opcontroller.ImmediateRetryResult, errors.Wrap(err, "failed to reconcile csi-op config CR") } return reconcileResult, nil - } else { - r.deleteCSIOperatorResources(clusterNamespace, false) } } if !EnableCSIOperator() { - r.deleteCSIOperatorResources(clusterNamespace, true) err = r.validateAndConfigureDrivers(serverVersion, ownerInfo) if err != nil { diff --git a/pkg/operator/ceph/csi/operator_config.go b/pkg/operator/ceph/csi/operator_config.go index 82f27c19a9ba..d1aceecfb698 100644 --- a/pkg/operator/ceph/csi/operator_config.go +++ b/pkg/operator/ceph/csi/operator_config.go @@ -176,20 +176,3 @@ func (r *ReconcileCSI) createImageSetConfigmap() (string, error) { return cm.Name, nil } - -func (r *ReconcileCSI) deleteImageSetConfigMap() error { - cm := &v1.ConfigMap{} - err := r.client.Get(r.opManagerContext, types.NamespacedName{Name: cm.Name, Namespace: r.opConfig.OperatorNamespace}, cm) - if err != nil { - if kerrors.IsNotFound(err) { - return nil - } - } - err = r.client.Delete(r.opManagerContext, cm) - if nil != err { - return errors.Wrapf(err, "failed to delete imageSet configMap %v", cm.Name) - } - logger.Infof("deleted imageSet configMap %q", cm.Name) - - return nil -} diff --git a/pkg/operator/ceph/csi/spec.go b/pkg/operator/ceph/csi/spec.go index 631b0446f01c..6b40437d9059 100644 --- a/pkg/operator/ceph/csi/spec.go +++ b/pkg/operator/ceph/csi/spec.go @@ -42,7 +42,6 @@ import ( "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/kubernetes" - csiopv1a1 "github.com/ceph/ceph-csi-operator/api/v1alpha1" cephcsi "github.com/ceph/ceph-csi/api/deploy/kubernetes" ) @@ -759,48 +758,6 @@ func (r *ReconcileCSI) stopDrivers(ver *version.Info) error { return nil } -func (r *ReconcileCSI) deleteCSIOperatorResources(clusterNamespace string, deleteOp bool) { - csiCephConnection := &csiopv1a1.CephConnection{} - - err := r.client.DeleteAllOf(r.opManagerContext, csiCephConnection, &client.DeleteAllOfOptions{ListOptions: client.ListOptions{Namespace: clusterNamespace}}) - if err != nil && !kerrors.IsNotFound(err) { - logger.Errorf("failed to delete CSI-operator Ceph Connection %q. %v", csiCephConnection.Name, err) - } else { - logger.Infof("deleted CSI-operator Ceph Connection %q", csiCephConnection.Name) - } - - csiOpClientProfile := &csiopv1a1.ClientProfile{} - err = r.client.DeleteAllOf(r.opManagerContext, csiOpClientProfile, &client.DeleteAllOfOptions{ListOptions: client.ListOptions{Namespace: clusterNamespace}}) - if err != nil && !kerrors.IsNotFound(err) { - logger.Errorf("failed to delete CSI-operator client profile %q. %v", csiOpClientProfile.Name, err) - } else { - logger.Infof("deleted CSI-operator client profile %q", csiOpClientProfile.Name) - } - - err = r.deleteImageSetConfigMap() - if err != nil && !kerrors.IsNotFound(err) { - logger.Error("failed to delete imageSetConfigMap", err) - } - - if deleteOp { - csiDriver := &csiopv1a1.Driver{} - err = r.client.DeleteAllOf(r.opManagerContext, csiDriver, &client.DeleteAllOfOptions{ListOptions: client.ListOptions{Namespace: r.opConfig.OperatorNamespace}}) - if err != nil && !kerrors.IsNotFound(err) { - logger.Errorf("failed to delete CSI-operator driver config %q. %v", csiDriver.Name, err) - } else { - logger.Infof("deleted CSI-operator driver config %q", csiDriver.Name) - } - - opConfig := &csiopv1a1.OperatorConfig{} - err = r.client.DeleteAllOf(r.opManagerContext, opConfig, &client.DeleteAllOfOptions{ListOptions: client.ListOptions{Namespace: r.opConfig.OperatorNamespace}}) - if err != nil && !kerrors.IsNotFound(err) { - logger.Errorf("failed to delete CSI-operator operator config %q. %v", opConfig.Name, err) - } else { - logger.Infof("deleted CSI-operator operator config %q", opConfig.Name) - } - } -} - func (r *ReconcileCSI) deleteCSIDriverResources(ver *version.Info, daemonset, deployment, service, driverName string) error { csiDriverobj := v1CsiDriver{} err := k8sutil.DeleteDaemonset(r.opManagerContext, r.context.Clientset, r.opConfig.OperatorNamespace, daemonset) From 454ec1eea491fda6ff3535979e114a4110d86532 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:06:37 +0000 Subject: [PATCH 07/54] build(deps): bump the github-dependencies group with 2 updates Bumps the github-dependencies group with 2 updates: [github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring](https://github.com/prometheus-operator/prometheus-operator) and [github.com/prometheus-operator/prometheus-operator/pkg/client](https://github.com/prometheus-operator/prometheus-operator). Updates `github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring` from 0.76.0 to 0.76.1 - [Release notes](https://github.com/prometheus-operator/prometheus-operator/releases) - [Changelog](https://github.com/prometheus-operator/prometheus-operator/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus-operator/prometheus-operator/compare/v0.76.0...v0.76.1) Updates `github.com/prometheus-operator/prometheus-operator/pkg/client` from 0.76.0 to 0.76.1 - [Release notes](https://github.com/prometheus-operator/prometheus-operator/releases) - [Changelog](https://github.com/prometheus-operator/prometheus-operator/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus-operator/prometheus-operator/compare/v0.76.0...v0.76.1) --- updated-dependencies: - dependency-name: github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-dependencies - dependency-name: github.com/prometheus-operator/prometheus-operator/pkg/client dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-dependencies ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 076aa298e388..789a8464d54b 100644 --- a/go.mod +++ b/go.mod @@ -31,8 +31,8 @@ require ( github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1 github.com/libopenstorage/secrets v0.0.0-20240416031220-a17cf7f72c6c github.com/pkg/errors v0.9.1 - github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.0 - github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.0 + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.1 + github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.1 github.com/rook/rook/pkg/apis v0.0.0-20231204200402-5287527732f7 github.com/sethvargo/go-password v0.3.1 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 1faf19988f81..ccec62e8dcf6 100644 --- a/go.sum +++ b/go.sum @@ -778,11 +778,11 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.44.1/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.46.0/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.0 h1:tRwEFYFg+To2TGnibGl8dHBCh8Z/BVNKnXj2O5Za/2M= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.0/go.mod h1:Rd8YnCqz+2FYsiGmE2DMlaLjQRB4v2jFNnzCt9YY4IM= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.1 h1:QU2cs0xxKYvF1JfibP/8vs+pFy6OvIpqNR2lYC4jYNU= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.1/go.mod h1:Rd8YnCqz+2FYsiGmE2DMlaLjQRB4v2jFNnzCt9YY4IM= github.com/prometheus-operator/prometheus-operator/pkg/client v0.46.0/go.mod h1:k4BrWlVQQsvBiTcDnKEMgyh/euRxyxgrHdur/ZX/sdA= -github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.0 h1:bJhRd6R4kaYBZpH7cBrzbJpEKJjHx8cbVW1n3dxYnag= -github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.0/go.mod h1:Nu6G9XLApnqXqunMwMYulcHlaxRwoveH4p4WnZsBHD8= +github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.1 h1:wMPmeRdflJFu14F0YaIiOIYGkBDDKipkeWW0q53d2+s= +github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.1/go.mod h1:7vND+IkdMpZyfSyRs6P5/uXz6BlFDaOj8olErODi8I0= github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= From 3b59db4b87145261ca94f2c2d0a6053a6798247b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:55:21 +0000 Subject: [PATCH 08/54] build(deps): bump wagoid/commitlint-github-action from 6.1.1 to 6.1.2 Bumps [wagoid/commitlint-github-action](https://github.com/wagoid/commitlint-github-action) from 6.1.1 to 6.1.2. - [Changelog](https://github.com/wagoid/commitlint-github-action/blob/master/CHANGELOG.md) - [Commits](https://github.com/wagoid/commitlint-github-action/compare/a2bc521d745b1ba127ee2f8b02d6afaa4eed035c...3d28780bbf0365e29b144e272b2121204d5be5f3) --- updated-dependencies: - dependency-name: wagoid/commitlint-github-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/commitlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 41f543423309..aa2feb26e75d 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - - uses: wagoid/commitlint-github-action@a2bc521d745b1ba127ee2f8b02d6afaa4eed035c # v6.1.1 + - uses: wagoid/commitlint-github-action@3d28780bbf0365e29b144e272b2121204d5be5f3 # v6.1.2 with: configFile: "./.commitlintrc.json" helpURL: https://rook.io/docs/rook/latest/Contributing/development-flow/#commit-structure From 67c40fe5beaddd1d803d3b47c214a462a9d726f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:55:29 +0000 Subject: [PATCH 09/54] build(deps): bump snyk/actions Bumps [snyk/actions](https://github.com/snyk/actions) from 9213221444c2dc9e8b2502c1e857c26d851e84a7 to cdb760004ba9ea4d525f2e043745dfe85bb9077e. - [Release notes](https://github.com/snyk/actions/releases) - [Commits](https://github.com/snyk/actions/compare/9213221444c2dc9e8b2502c1e857c26d851e84a7...cdb760004ba9ea4d525f2e043745dfe85bb9077e) --- updated-dependencies: - dependency-name: snyk/actions dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/snyk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snyk.yaml b/.github/workflows/snyk.yaml index abb671219163..b8c2459ba132 100644 --- a/.github/workflows/snyk.yaml +++ b/.github/workflows/snyk.yaml @@ -21,7 +21,7 @@ jobs: fetch-depth: 0 - name: run Snyk to check for code vulnerabilities - uses: snyk/actions/golang@9213221444c2dc9e8b2502c1e857c26d851e84a7 # master + uses: snyk/actions/golang@cdb760004ba9ea4d525f2e043745dfe85bb9077e # master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} GOFLAGS: "-buildvcs=false" From b9188c793aceb6df9ada464c970e44ec2ca036b7 Mon Sep 17 00:00:00 2001 From: Travis Nielsen Date: Mon, 9 Sep 2024 13:27:54 -0600 Subject: [PATCH 10/54] pool: allow negative step num in crush rule The crush rules may have a negative step num. Rook had assumed negative values were not possible, but just had not been encountered previously in a custom crush rule. Signed-off-by: Travis Nielsen --- pkg/daemon/ceph/client/crush.go | 2 +- pkg/daemon/ceph/client/crush_rule.go | 2 +- pkg/daemon/ceph/client/crush_rule_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/daemon/ceph/client/crush.go b/pkg/daemon/ceph/client/crush.go index 2f1c4d4631cd..75bb6fc01caf 100644 --- a/pkg/daemon/ceph/client/crush.go +++ b/pkg/daemon/ceph/client/crush.go @@ -75,7 +75,7 @@ type ruleSpec struct { type stepSpec struct { Operation string `json:"op"` - Number uint `json:"num"` + Number int `json:"num"` Item int `json:"item"` ItemName string `json:"item_name"` Type string `json:"type"` diff --git a/pkg/daemon/ceph/client/crush_rule.go b/pkg/daemon/ceph/client/crush_rule.go index b79d5470ac5c..97575b2a8164 100644 --- a/pkg/daemon/ceph/client/crush_rule.go +++ b/pkg/daemon/ceph/client/crush_rule.go @@ -150,7 +150,7 @@ func buildTwoStepCrushSteps(pool cephv1.PoolSpec) []stepSpec { // Step three stepTakeSubFailureDomain := &stepSpec{ Operation: "chooseleaf_firstn", - Number: pool.Replicated.ReplicasPerFailureDomain, + Number: int(pool.Replicated.ReplicasPerFailureDomain), Type: pool.Replicated.SubFailureDomain, } steps = append(steps, *stepTakeSubFailureDomain) diff --git a/pkg/daemon/ceph/client/crush_rule_test.go b/pkg/daemon/ceph/client/crush_rule_test.go index ce799bfdf138..c48e52b7355d 100644 --- a/pkg/daemon/ceph/client/crush_rule_test.go +++ b/pkg/daemon/ceph/client/crush_rule_test.go @@ -56,7 +56,7 @@ func TestBuildCrushSteps(t *testing.T) { assert.Equal(t, 4, len(steps)) assert.Equal(t, cephv1.DefaultCRUSHRoot, steps[0].ItemName) assert.Equal(t, "datacenter", steps[1].Type) - assert.Equal(t, uint(2), steps[2].Number) + assert.Equal(t, 2, steps[2].Number) } func TestCompileCRUSHMap(t *testing.T) { From 4af5b6a33133e81b82e920160f74c7fada339881 Mon Sep 17 00:00:00 2001 From: parth-gr Date: Mon, 9 Sep 2024 16:04:53 +0530 Subject: [PATCH 11/54] doc: add the pv encryption key rotation job Add missing csi addon's feature in the Rook document Signed-off-by: parth-gr --- .../Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md index d81f55ebf2c2..dc5df80b8847 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md +++ b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md @@ -200,11 +200,18 @@ CSI-Addons supports the following operations: * [Creating a ReclaimSpaceCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#reclaimspacecronjob) * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#annotating-perstentvolumeclaims) * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#annotating-namespace) + * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#annotating-storageclass) * Network Fencing * [Creating a NetworkFence](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/networkfence.md) * Volume Replication * [Creating VolumeReplicationClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/volumereplicationclass.md) * [Creating VolumeReplication CR](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/volumereplication.md) +* Key Rotation Job for PV encryption + * [Creating EncryptionKeyRotationJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#encryptionkeyrotationjob) + * [Creating EncryptionKeyRotationCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#encryptionkeyrotationcronjob) + * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#annotating-persistentvolumeclaims) + * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#annotating-namespace) + * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#annotating-storageclass) ## Enable RBD and CephFS Encryption Support From 28994e8ad5c6231deb87a19f6209e695c638ee0b Mon Sep 17 00:00:00 2001 From: Ceph Jenkins Date: Wed, 11 Sep 2024 04:03:09 -0400 Subject: [PATCH 12/54] csv: add additional csv changes that other commits bring add generated csv changes Signed-off-by: Ceph Jenkins --- .../ceph/ceph.rook.io_cephobjectstores.yaml | 39 +++++++++++++++++-- .../ceph/ceph.rook.io_cephobjectzones.yaml | 39 +++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/build/csv/ceph/ceph.rook.io_cephobjectstores.yaml b/build/csv/ceph/ceph.rook.io_cephobjectstores.yaml index cafd46dba004..3f86d6ffce5d 100644 --- a/build/csv/ceph/ceph.rook.io_cephobjectstores.yaml +++ b/build/csv/ceph/ceph.rook.io_cephobjectstores.yaml @@ -1476,11 +1476,44 @@ spec: x-kubernetes-validations: - message: object store shared metadata pool is immutable rule: self == oldSelf + poolPlacements: + items: + properties: + dataNonECPoolName: + type: string + dataPoolName: + minLength: 1 + type: string + metadataPoolName: + minLength: 1 + type: string + name: + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + storageClasses: + items: + properties: + dataPoolName: + minLength: 1 + type: string + name: + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + required: + - dataPoolName + - name + type: object + type: array + required: + - dataPoolName + - metadataPoolName + - name + type: object + type: array preserveRadosNamespaceDataOnDelete: type: boolean - required: - - dataPoolName - - metadataPoolName type: object zone: nullable: true diff --git a/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml b/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml index f5946e3142e8..deb02663feb5 100644 --- a/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml +++ b/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml @@ -314,11 +314,44 @@ spec: x-kubernetes-validations: - message: object store shared metadata pool is immutable rule: self == oldSelf + poolPlacements: + items: + properties: + dataNonECPoolName: + type: string + dataPoolName: + minLength: 1 + type: string + metadataPoolName: + minLength: 1 + type: string + name: + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + storageClasses: + items: + properties: + dataPoolName: + minLength: 1 + type: string + name: + minLength: 1 + pattern: ^[a-zA-Z0-9._/-]+$ + type: string + required: + - dataPoolName + - name + type: object + type: array + required: + - dataPoolName + - metadataPoolName + - name + type: object + type: array preserveRadosNamespaceDataOnDelete: type: boolean - required: - - dataPoolName - - metadataPoolName type: object zoneGroup: type: string From 645ae2b86f8ff9323cfd38f14ae4b254bdc87471 Mon Sep 17 00:00:00 2001 From: Blaine Gardner Date: Wed, 11 Sep 2024 11:05:52 -0600 Subject: [PATCH 13/54] object: add missing codegen from pool placements When pool placements were recently added to the object store CRD, it seems that codegen didn't get run, and Rook's CI didn't accurately catch the codegen issue. This will address adding the missing generated code. Follow-up work will address fixing CI so that it doesn't continue missing when codegen needs to be run. Signed-off-by: Blaine Gardner --- .../ceph.rook.io/v1/zz_generated.deepcopy.go | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go b/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go index bd6bf6821cef..6ac445966598 100644 --- a/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go +++ b/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go @@ -3632,6 +3632,13 @@ func (in *ObjectRealmSpec) DeepCopy() *ObjectRealmSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectSharedPoolsSpec) DeepCopyInto(out *ObjectSharedPoolsSpec) { *out = *in + if in.PoolPlacements != nil { + in, out := &in.PoolPlacements, &out.PoolPlacements + *out = make([]PoolPlacementSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -3694,7 +3701,7 @@ func (in *ObjectStoreSpec) DeepCopyInto(out *ObjectStoreSpec) { *out = *in in.MetadataPool.DeepCopyInto(&out.MetadataPool) in.DataPool.DeepCopyInto(&out.DataPool) - out.SharedPools = in.SharedPools + in.SharedPools.DeepCopyInto(&out.SharedPools) in.Gateway.DeepCopyInto(&out.Gateway) in.Protocols.DeepCopyInto(&out.Protocols) in.Auth.DeepCopyInto(&out.Auth) @@ -3876,7 +3883,7 @@ func (in *ObjectZoneSpec) DeepCopyInto(out *ObjectZoneSpec) { *out = *in in.MetadataPool.DeepCopyInto(&out.MetadataPool) in.DataPool.DeepCopyInto(&out.DataPool) - out.SharedPools = in.SharedPools + in.SharedPools.DeepCopyInto(&out.SharedPools) if in.CustomEndpoints != nil { in, out := &in.CustomEndpoints, &out.CustomEndpoints *out = make([]string, len(*in)) @@ -4010,6 +4017,22 @@ func (in PlacementSpec) DeepCopy() PlacementSpec { return *out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementStorageClassSpec) DeepCopyInto(out *PlacementStorageClassSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementStorageClassSpec. +func (in *PlacementStorageClassSpec) DeepCopy() *PlacementStorageClassSpec { + if in == nil { + return nil + } + out := new(PlacementStorageClassSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PoolMirroringInfo) DeepCopyInto(out *PoolMirroringInfo) { *out = *in @@ -4069,6 +4092,27 @@ func (in *PoolMirroringStatusSummarySpec) DeepCopy() *PoolMirroringStatusSummary return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PoolPlacementSpec) DeepCopyInto(out *PoolPlacementSpec) { + *out = *in + if in.StorageClasses != nil { + in, out := &in.StorageClasses, &out.StorageClasses + *out = make([]PlacementStorageClassSpec, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PoolPlacementSpec. +func (in *PoolPlacementSpec) DeepCopy() *PoolPlacementSpec { + if in == nil { + return nil + } + out := new(PoolPlacementSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PoolSpec) DeepCopyInto(out *PoolSpec) { *out = *in From 36f6807fbeca45e308599ba35e036e422965294c Mon Sep 17 00:00:00 2001 From: Alexander Trost Date: Mon, 2 Sep 2024 17:24:18 +0200 Subject: [PATCH 14/54] docs: add grafana dashboards files to docs Co-authored-by: Travis Nielsen Signed-off-by: Alexander Trost --- .../Monitoring/ceph-monitoring.md | 8 +- .../grafana/Ceph Cluster Dashboard.json | 5679 +++++++++++++++++ .../grafana/Ceph OSD Single Dashboard.json | 1615 +++++ .../grafana/Ceph Pools Dashboard.json | 925 +++ deploy/examples/monitoring/grafana/README.md | 12 + 5 files changed, 8236 insertions(+), 3 deletions(-) create mode 100644 deploy/examples/monitoring/grafana/Ceph Cluster Dashboard.json create mode 100644 deploy/examples/monitoring/grafana/Ceph OSD Single Dashboard.json create mode 100644 deploy/examples/monitoring/grafana/Ceph Pools Dashboard.json create mode 100644 deploy/examples/monitoring/grafana/README.md diff --git a/Documentation/Storage-Configuration/Monitoring/ceph-monitoring.md b/Documentation/Storage-Configuration/Monitoring/ceph-monitoring.md index 8781d91da911..40098c724f5b 100644 --- a/Documentation/Storage-Configuration/Monitoring/ceph-monitoring.md +++ b/Documentation/Storage-Configuration/Monitoring/ceph-monitoring.md @@ -228,9 +228,11 @@ The dashboards have been created by [@galexrt](https://github.com/galexrt). For The following Grafana dashboards are available: -- [Ceph - Cluster](https://grafana.com/grafana/dashboards/2842) -- [Ceph - OSD (Single)](https://grafana.com/grafana/dashboards/5336) -- [Ceph - Pools](https://grafana.com/grafana/dashboards/5342) +- [Ceph - Cluster (ID: 2842)](https://grafana.com/grafana/dashboards/2842) +- [Ceph - OSD (Single) (ID: 5336)](https://grafana.com/grafana/dashboards/5336) +- [Ceph - Pools (ID: 5342)](https://grafana.com/grafana/dashboards/5342) + +The dashboard JSON files are also available on [GitHub here `/deploy/examples/monitoring/grafana/`](https://github.com/rook/rook/tree/master/deploy/examples/monitoring/grafana/). ## Updates and Upgrades diff --git a/deploy/examples/monitoring/grafana/Ceph Cluster Dashboard.json b/deploy/examples/monitoring/grafana/Ceph Cluster Dashboard.json new file mode 100644 index 000000000000..c2d012eab11a --- /dev/null +++ b/deploy/examples/monitoring/grafana/Ceph Cluster Dashboard.json @@ -0,0 +1,5679 @@ +{ + "__inputs": [], + "__requires": [ + { + "id": "grafana", + "name": "Grafana", + "type": "grafana", + "version": "5.3.2" + }, + { + "id": "graph", + "name": "Graph", + "type": "panel", + "version": "5.0.0" + }, + { + "id": "heatmap", + "name": "Heatmap", + "type": "panel", + "version": "5.0.0" + }, + { + "id": "singlestat", + "name": "Singlestat", + "type": "panel", + "version": "5.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "showIn": 0, + "tags": [], + "type": "dashboard" + } + ] + }, + "description": "Overview of your Ceph cluster.", + "editable": false, + "gnetId": 2842, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [], + "panels": [ + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CLUSTER STATE", + "titleSize": "h6", + "type": "row" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "0": { + "text": "HEALTHY" + }, + "1": { + "text": "WARNING" + }, + "2": { + "text": "ERROR" + } + }, + "type": "value" + }, + { + "id": 1, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#9ac48a" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 2 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 3, + "interval": "1m", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_health_status{}", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Ceph health status", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 1, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "Bps" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 4, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_w_in_bytes{}[5m]))", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Write Throughput", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 1, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#9ac48a", + "value": 0 + } + ] + }, + "unit": "Bps" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 5, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_r_out_bytes{}[5m]))", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Read Throughput", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 2, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0.025 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 1 + } + ] + }, + "unit": "decbytes" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 6, + "interval": "1m", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_cluster_total_bytes{}", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Cluster Capacity", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0.1 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 0.3 + } + ] + }, + "unit": "percentunit" + } + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 7, + "interval": "1m", + "links": [], + "maxDataPoints": 100, + "options": { + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_cluster_total_bytes{}-ceph_cluster_total_used_bytes{})/ceph_cluster_total_bytes{}", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Available Capacity", + "transparent": false, + "type": "gauge" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 2, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 8, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pool_objects{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Number of Objects", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 1, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 9, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "delta" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_osd_op_w_in_bytes{})", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Bytes Written", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 1, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "delta" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_osd_op_r_out_bytes{})", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Bytes Read", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#9ac48a" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "#e24d42", + "value": 1 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 0, + "y": 4 + }, + "id": 11, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count(ALERTS{alertstate=\"firing\",alertname=~\"^Ceph.+\"}) OR vector(0)", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Alerts starting with Ceph", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "ops" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 3, + "y": 4 + }, + "id": 12, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_w{}[5m]))", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Write IOPS", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#9ac48a", + "value": 0 + } + ] + }, + "unit": "ops" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 6, + "y": 4 + }, + "id": 13, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_r{}[5m]))", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Read IOPS", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 2, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0.025 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 0.1 + } + ] + }, + "unit": "decbytes" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 9, + "y": 4 + }, + "id": 14, + "interval": "1m", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_cluster_total_used_bytes{}", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Used Capacity", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 2, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#ea6460" + }, + { + "color": "#052b51", + "value": 0 + }, + { + "color": "#508642", + "value": 0 + } + ] + }, + "unit": "short" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 15, + "y": 4 + }, + "id": 15, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "diff" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pool_objects)", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Difference", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 128 + } + ] + }, + "unit": "short" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 18, + "y": 4 + }, + "id": 16, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_mon_num_sessions{})", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Mon Session Num", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 2 + }, + { + "color": "green", + "value": 3 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 4 + }, + "id": 17, + "interval": "1m", + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count(ceph_mon_quorum_status{}) or vector(0)", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Monitors In Quorum", + "transparent": false, + "type": "stat" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 18, + "panels": [], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "OSD STATE", + "titleSize": "h6", + "type": "row" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#9ac48a" + }, + { + "color": "rgba(237, 40, 40, 0.89)", + "value": 1 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 1 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 0, + "y": 8 + }, + "id": 19, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count(ceph_osd_up{}) - count(ceph_osd_in{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "OSDs OUT", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "#eab839", + "value": 1 + }, + { + "color": "#ea6460", + "value": 1 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 2, + "y": 8 + }, + "id": 20, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count(ceph_osd_up{} == 0.0) OR vector(0)", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "OSDs DOWN", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 4, + "y": 8 + }, + "id": 21, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_osd_up{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "OSDs UP", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 0, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 6, + "y": 8 + }, + "id": 22, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_osd_in{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "OSDs IN", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 1, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 250 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 300 + } + ] + }, + "unit": "none" + } + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 8, + "y": 8 + }, + "id": 23, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(ceph_osd_numpg{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Avg PGs", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 2, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 50 + } + ] + }, + "unit": "ms" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 10, + "y": 8 + }, + "id": 24, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(ceph_osd_apply_latency_ms{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Avg Apply Latency", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 2, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 50 + } + ] + }, + "unit": "ms" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 13, + "y": 8 + }, + "id": 25, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(ceph_osd_commit_latency_ms{})", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 300 + } + ], + "title": "Avg Commit Latency", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 4, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "color": "#299c46", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "#d44a3a", + "value": 2 + } + ] + }, + "unit": "ms" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 16, + "y": 8 + }, + "id": 26, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(rate(ceph_osd_op_w_latency_sum{}[5m]) / rate(ceph_osd_op_w_latency_count{}[5m]) >= 0)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Avg Op Write Latency", + "transparent": false, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "decimals": 6, + "links": [], + "mappings": [ + { + "id": 0, + "options": { + "match": null, + "result": { + "color": "#299c46", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "#d44a3a", + "value": 2 + } + ] + }, + "unit": "ms" + } + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 19, + "y": 8 + }, + "id": 27, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(rate(ceph_osd_op_r_latency_sum{}[5m])/rate(ceph_osd_op_r_latency_count{}[5m]) >= 0)", + "format": "time_series", + "instant": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Avg Op Read Latency", + "transparent": false, + "type": "stat" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 28, + "panels": [], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "CLUSTER STATS", + "titleSize": "h6", + "type": "row" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 0, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Available" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Capacity" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#447EBC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_avail" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_space" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Capacity" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.lineWidth", + "value": 3 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 10 + }, + "id": 29, + "interval": "$interval", + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_cluster_total_bytes{}-ceph_cluster_total_used_bytes{}", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Available", + "refId": "A", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_cluster_total_used_bytes{}", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Used", + "refId": "B", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_cluster_total_bytes{}", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Total Capacity", + "refId": "C", + "step": 300 + } + ], + "title": "Capacity", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total Capacity" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_avail" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_space" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 10 + }, + "id": 30, + "interval": "$interval", + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_w{}[5m]))", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Write", + "refId": "A", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_r{}[5m]))", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Read", + "refId": "B", + "step": 300 + } + ], + "title": "IOPS", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 10 + }, + "id": 31, + "interval": "$interval", + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_w_in_bytes{}[5m]))", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Write", + "refId": "A", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_op_r_out_bytes{}[5m]))", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Read", + "refId": "B", + "step": 300 + } + ], + "title": "Cluster Throughput", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 18 + }, + "id": 32, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_pool_bytes_used{}) *on (pool_id) group_left(name)(ceph_pool_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "refId": "A", + "step": 300 + } + ], + "title": "Pool Used Bytes", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 18 + }, + "id": 33, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_pool_avail_raw{}) *on (pool_id) group_left(name)(ceph_pool_metadata{})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{name}} Avail", + "range": true, + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_pool_stored_raw{}) *on (pool_id) group_left(name)(ceph_pool_metadata{})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{name}} Stored", + "range": true, + "refId": "B" + } + ], + "title": "Pool RAW Bytes", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 18 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_pool_objects{}) *on (pool_id) group_left(name)(ceph_pool_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "title": "Objects Per Pool", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 26 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_pool_quota_bytes{}) *on (pool_id) group_left(name)(ceph_pool_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "title": "Pool Quota Bytes", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 26 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(ceph_pool_quota_objects{}) *on (pool_id) group_left(name)(ceph_pool_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "title": "Pool Objects Quota", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 26 + }, + "id": 37, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count(ceph_bluestore_kv_commit_lat_count{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "BlueStore", + "range": true, + "refId": "A" + } + ], + "title": "OSD Type Count", + "type": "timeseries" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 38, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "decimals": 2, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss" + }, + { + "id": "custom.align" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 28 + }, + "id": 39, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.1.3", + "styles": "", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ALERTS{alertstate=\"firing\",alertname=~\"^Ceph.+\"}", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Alerts starting with Ceph", + "transformations": [ + { + "id": "merge", + "options": { + "reducer": [] + } + } + ], + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": false, + "inspect": false + }, + "decimals": 2, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss" + }, + { + "id": "custom.align" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 28 + }, + "id": 40, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.1.3", + "styles": "", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "topk(5,sort_desc(ceph_osd_apply_latency_ms{} + ceph_osd_commit_latency_ms{}))", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "_auto", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top Sluggish OSDs", + "transformations": [ + { + "id": "merge", + "options": { + "reducer": [] + } + } + ], + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "decimals": 2, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss" + }, + { + "id": "custom.align" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 28 + }, + "id": 41, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.1.3", + "styles": "", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_osd_up{} == 0", + "format": "table", + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Down OSDs", + "transformations": [ + { + "id": "merge", + "options": { + "reducer": [] + } + } + ], + "type": "table" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Alerts", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 42, + "panels": [ + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "scaleDistributionLog": 2, + "type": "log" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 43, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "node_memory_Active_anon_bytes{}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(node_memory_Active_anon_bytes{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Cluster Memory Usage", + "refId": "B" + } + ], + "title": "Node Memory Usage", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "scaleDistributionLog": 2, + "type": "log" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 44, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg by(instance)(irate(node_cpu_seconds_total{job='node',mode!=\"idle\"}[$interval])) * 100", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "title": "Node CPU Usage", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 45, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum by (instance)(irate(node_disk_read_bytes_total{}[$interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "title": "Node Out", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 46, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum by (instance)(irate(node_disk_written_bytes_total{}[$interval]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "title": "Node In", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 44 + }, + "id": 47, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "(node_filesystem_free_bytes{ mountpoint=\"/\", device != \"rootfs\"})*100 / (node_filesystem_size_bytes{ mountpoint=\"/\", device != \"rootfs\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Free Space in root filesystem", + "type": "timeseries" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Node Statistics (NodeExporter)", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 48, + "panels": [], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "OBJECTS", + "titleSize": "h6", + "type": "row" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^Total.*$/" + }, + "properties": [ + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 6, + "x": 0, + "y": 46 + }, + "id": 49, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "asc" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pool_objects)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Total", + "range": true, + "refId": "A", + "step": 300 + } + ], + "title": "OSD Type Count", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^Total.*$/" + }, + "properties": [ + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 8, + "x": 6, + "y": 46 + }, + "id": 50, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "asc" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_active{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Active", + "range": true, + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_clean{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Clean", + "range": true, + "refId": "B" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_peering{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Peering", + "range": true, + "refId": "C" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_degraded{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Degraded", + "range": true, + "refId": "D", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_stale{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Stale", + "range": true, + "refId": "E", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_unclean_pgs{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Unclean", + "range": true, + "refId": "F", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_undersized{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Undersized", + "range": true, + "refId": "G", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_incomplete{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Incomplete", + "range": true, + "refId": "H" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_forced_backfill{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Forced Backfill", + "range": true, + "refId": "I" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_forced_recovery{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Forced Recovery", + "range": true, + "refId": "J" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_creating{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Creating", + "range": true, + "refId": "K" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_wait_backfill{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Wait Backfill", + "range": true, + "refId": "L" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_deep{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Deep", + "range": true, + "refId": "M" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_scrubbing{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Scrubbing", + "range": true, + "refId": "N" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_recovering{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Recovering", + "range": true, + "refId": "O" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_repair{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Repair", + "range": true, + "refId": "P" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_down{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Down", + "range": true, + "refId": "Q" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_peered{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Peered", + "range": true, + "refId": "R" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_backfill{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Backfill", + "range": true, + "refId": "S" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_remapped{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Remapped", + "range": true, + "refId": "T" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_backfill_toofull{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Backfill Toofull", + "range": true, + "refId": "U" + } + ], + "title": "PGs State", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^Total.*$/" + }, + "properties": [ + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 14, + "y": 46 + }, + "id": 51, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "asc" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_degraded{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Degraded", + "range": true, + "refId": "A", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_stale{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Stale", + "range": true, + "refId": "B", + "step": 300 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(ceph_pg_undersized{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Undersized", + "range": true, + "refId": "C", + "step": 300 + } + ], + "title": "Stuck PGs", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 14, + "y": 52 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(ceph_osd_recovery_ops{}[$interval]))", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "OPS", + "refId": "A", + "step": 300 + } + ], + "title": "Recovery Operations", + "type": "timeseries" + }, + { + "collapse": false, + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 53, + "panels": [], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "LATENCY", + "titleSize": "h6", + "type": "row" + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 54 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 54, + "legend": { + "show": true + }, + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + }, + "value": "1" + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#b4ff00", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_osd_apply_latency_ms{}", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Apply Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "", + "yAxis": { + "decimals": null, + "format": "ms", + "logBase": 2, + "max": null, + "min": "0", + "show": true, + "splitFactor": 1 + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": 10 + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#65c5db", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 54 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 55, + "legend": { + "show": true + }, + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + } + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#65c5db", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "ceph_osd_commit_latency_ms{}", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Commit Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "", + "yAxis": { + "decimals": null, + "format": "ms", + "logBase": 2, + "max": null, + "min": "0", + "show": true, + "splitFactor": 1 + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#806eb7", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 62 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 56, + "legend": { + "show": true + }, + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + } + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#806eb7", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "decimals": 2, + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "rate(ceph_osd_op_r_latency_sum{}[5m]) / rate(ceph_osd_op_r_latency_count{}[5m]) >= 0", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Read Op Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "", + "yAxis": { + "decimals": null, + "format": "ms", + "logBase": 2, + "max": null, + "min": "0", + "show": true, + "splitFactor": 1 + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#f9934e", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + } + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 62 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 57, + "legend": { + "show": true + }, + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + } + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#f9934e", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "decimals": 2, + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "rate(ceph_osd_op_w_latency_sum{}[5m]) / rate(ceph_osd_op_w_latency_count{}[5m]) >= 0", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Write Op Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "", + "yAxis": { + "decimals": 2, + "format": "ms", + "logBase": 2, + "max": null, + "min": "0", + "show": true, + "splitFactor": 1 + }, + "yBucketBound": "auto", + "yBucketNumber": null, + "yBucketSize": null + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 70 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(rate(ceph_osd_op_r_latency_sum{}[5m]) / rate(ceph_osd_op_r_latency_count{}[5m]) >= 0)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Read", + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(rate(ceph_osd_op_w_latency_sum{}[5m]) / rate(ceph_osd_op_w_latency_count{}[5m]) >= 0)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Write", + "refId": "B" + } + ], + "title": "Recovery Operations", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 70 + }, + "id": 59, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(ceph_osd_apply_latency_ms{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "apply", + "metric": "ceph_osd_perf_apply_latency_seconds", + "refId": "A", + "step": 4 + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(ceph_osd_commit_latency_ms{})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "commit", + "metric": "ceph_osd_perf_commit_latency_seconds", + "refId": "B", + "step": 4 + } + ], + "title": "AVG OSD Apply + Commit Latency", + "type": "timeseries" + }, + { + "collapse": true, + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 71 + }, + "id": 60, + "panels": [ + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 72 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count by (ceph_version)(ceph_osd_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Ceph OSD Versions", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 72 + }, + "id": 62, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count by (ceph_version)(ceph_mon_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Ceph Mon Versions", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 12, + "y": 72 + }, + "id": 63, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count by (ceph_version)(ceph_mds_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Ceph MDS Versions", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 72 + }, + "id": 64, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count by (ceph_version)(ceph_rgw_metadata{})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Ceph RGW Versions", + "type": "timeseries" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": true, + "title": "Ceph Versions", + "titleSize": "h6", + "type": "row" + } + ], + "refresh": "1m", + "rows": [], + "schemaVersion": 37, + "style": "dark", + "tags": [ + "ceph-mixin" + ], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": "Data Source", + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "auto": true, + "auto_count": 10, + "auto_min": "1m", + "current": { + "text": "$__auto_interval_interval", + "value": "$__auto_interval_interval" + }, + "hide": 0, + "label": "Interval", + "name": "interval", + "options": [ + { + "selected": true, + "text": "auto", + "value": "$__auto_interval_interval" + }, + { + "selected": false, + "text": "5s", + "value": "5s" + }, + { + "selected": false, + "text": "10s", + "value": "10s" + }, + { + "selected": false, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": false, + "text": "30m", + "value": "30m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + } + ], + "query": "5s,10s,30s,1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", + "refresh": 2, + "type": "interval", + "valuelabels": {} + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Ceph Cluster", + "uid": "tbO9LAiZK", + "version": 0 +} diff --git a/deploy/examples/monitoring/grafana/Ceph OSD Single Dashboard.json b/deploy/examples/monitoring/grafana/Ceph OSD Single Dashboard.json new file mode 100644 index 000000000000..1c5f9e51c495 --- /dev/null +++ b/deploy/examples/monitoring/grafana/Ceph OSD Single Dashboard.json @@ -0,0 +1,1615 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.0.5" + }, + { + "type": "panel", + "id": "heatmap", + "name": "Heatmap", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "CEPH OSD Status.", + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": 5336, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 11, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "refId": "A" + } + ], + "title": "OSD Status / Total OSDs", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "from": 0, + "result": { + "index": 0, + "text": "N/A" + }, + "to": 0 + }, + "type": "range" + }, + { + "options": { + "from": 0, + "result": { + "index": 1, + "text": "DOWN" + }, + "to": 0.99 + }, + "type": "range" + }, + { + "options": { + "from": 0.99, + "result": { + "index": 2, + "text": "UP" + }, + "to": 1 + }, + "type": "range" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 40, 40, 0.89)", + "value": 0 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 0, + "y": 1 + }, + "id": 6, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum without (instance) (ceph_osd_up{ceph_daemon=\"$osd\"})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "range": true, + "refId": "A", + "step": 60 + } + ], + "title": "Status", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "from": 0, + "result": { + "index": 0, + "text": "N/A" + }, + "to": 0 + }, + "type": "range" + }, + { + "options": { + "from": 0, + "result": { + "index": 1, + "text": "OUT" + }, + "to": 0.99 + }, + "type": "range" + }, + { + "options": { + "from": 0.99, + "result": { + "index": 2, + "text": "IN" + }, + "to": 1 + }, + "type": "range" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 40, 40, 0.89)", + "value": 0 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 2, + "y": 1 + }, + "id": 8, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance) (ceph_osd_in{ceph_daemon=\"$osd\"})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 60 + } + ], + "title": "Available", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "from": 0, + "result": { + "index": 0, + "text": "N/A" + }, + "to": 0 + }, + "type": "range" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(255, 255, 255, 0.9)", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 2, + "x": 4, + "y": 1 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "count without (instance, ceph_daemon) (ceph_osd_up)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 60 + } + ], + "title": "Total OSDs", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 12, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "refId": "A" + } + ], + "title": "OSD: $osd", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "rgba(216, 200, 27, 0.27)", + "value": 250 + }, + { + "color": "rgba(234, 112, 112, 0.22)", + "value": 300 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^Average.*/" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 5 + }, + "id": 5, + "interval": "$interval", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance, ceph_daemon) (ceph_osd_numpg{ceph_daemon=~\"$osd\"})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Number of PGs", + "refId": "A", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "avg without (instance, ceph_daemon) (ceph_osd_numpg)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Average Number of PGs in the Cluster", + "refId": "B", + "step": 60 + } + ], + "title": "PGs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 9, + "x": 11, + "y": 5 + }, + "id": 2, + "interval": "$interval", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance, ceph_daemon) (ceph_osd_stat_bytes{ceph_daemon=\"osd.0\"}-ceph_osd_stat_bytes_used{ceph_daemon=\"osd.0\"})", + "format": "time_series", + "hide": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Available", + "metric": "ceph_osd_avail_bytes", + "refId": "A", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance, ceph_daemon) (ceph_osd_stat_bytes_used{ceph_daemon=~\"$osd\"})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Used", + "metric": "ceph_osd_avail_bytes", + "refId": "B", + "step": 60 + } + ], + "title": "OSD Storage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 60 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 20, + "y": 5 + }, + "id": 7, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance, ceph_daemon) (ceph_osd_stat_bytes_used{ceph_daemon=\"osd.0\"}/ceph_osd_stat_bytes{ceph_daemon=\"osd.0\"})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 60 + } + ], + "title": "Utilization", + "type": "gauge" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 13, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "refId": "A" + } + ], + "title": "Latency, Storage, Utilization Varience", + "type": "row" + }, + { + "cards": {}, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 13 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 83, + "legend": { + "show": true + }, + "links": [], + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + }, + "value": "1" + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#b4ff00", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance) (ceph_osd_apply_latency_ms{ceph_daemon='$osd'})", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Apply Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketSize": "", + "yAxis": { + "format": "ms", + "logBase": 2, + "min": "0", + "show": true, + "splitFactor": 1 + }, + "yBucketBound": "auto", + "yBucketSize": 10 + }, + { + "cards": {}, + "color": { + "cardColor": "#65c5db", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 13 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 84, + "legend": { + "show": true + }, + "links": [], + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + } + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#65c5db", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance) (ceph_osd_commit_latency_ms{ceph_daemon='$osd'})", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Commit Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketSize": "", + "yAxis": { + "format": "ms", + "logBase": 2, + "min": "0", + "show": true + }, + "yBucketBound": "auto" + }, + { + "cards": {}, + "color": { + "cardColor": "#806eb7", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 85, + "legend": { + "show": true + }, + "links": [], + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + } + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#806eb7", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "decimals": 2, + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance) (rate(ceph_osd_op_r_latency_sum{ceph_daemon='$osd'}[5m]) / rate(ceph_osd_op_r_latency_count{ceph_daemon='$osd'}[5m]) >= 0)", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Read Op Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketSize": "", + "yAxis": { + "decimals": 2, + "format": "ms", + "logBase": 2, + "min": "0", + "show": true + }, + "yBucketBound": "auto" + }, + { + "cards": {}, + "color": { + "cardColor": "#f9934e", + "colorScale": "sqrt", + "colorScheme": "interpolateOranges", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "timeseries", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 86, + "legend": { + "show": true + }, + "links": [], + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "mode": "count", + "scale": { + "log": 2, + "type": "log" + } + } + }, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#f9934e", + "mode": "opacity", + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "decimals": 2, + "min": "0", + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "9.1.3", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance) (rate(ceph_osd_op_w_latency_sum{ceph_daemon='$osd'}[5m]) / rate(ceph_osd_op_w_latency_count{ceph_daemon='$osd'}[5m]) >= 0)", + "format": "time_series", + "instant": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "OSD Write Op Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketSize": "", + "yAxis": { + "decimals": 2, + "format": "ms", + "logBase": 2, + "min": "0", + "show": true + }, + "yBucketBound": "auto" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 44, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "avg without (instance, ceph_daemon) (rate(ceph_osd_op_r_latency_sum{ceph_daemon='$osd'}[5m]) / rate(ceph_osd_op_r_latency_count{ceph_daemon='$osd'}[5m]) >= 0)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "read", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "avg without (instance, ceph_daemon) (rate(ceph_osd_op_w_latency_sum{ceph_daemon='$osd'}[5m]) / rate(ceph_osd_op_w_latency_count{ceph_daemon='$osd'}[5m]) >= 0)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "write", + "refId": "B" + } + ], + "title": "Avg OSD Op Latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 35, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "avg without (instance, ceph_daemon) (ceph_osd_apply_latency_ms{ceph_daemon='$osd'})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "apply", + "metric": "ceph_osd_perf_apply_latency_seconds", + "refId": "A", + "step": 4 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "avg without (instance, ceph_daemon)(ceph_osd_commit_latency_ms{ceph_daemon='$osd'})", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "commit", + "metric": "ceph_osd_perf_commit_latency_seconds", + "refId": "B", + "step": 4 + } + ], + "title": "AVG OSD Apply + Commit Latency", + "type": "timeseries" + } + ], + "refresh": "5m", + "schemaVersion": 36, + "style": "dark", + "tags": [ + "ceph", + "osd" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "label": "Data source", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": true, + "auto_count": 10, + "auto_min": "1m", + "current": { + "selected": false, + "text": "30s", + "value": "30s" + }, + "datasource": "Prometheus", + "hide": 0, + "includeAll": false, + "label": "Interval", + "multi": false, + "name": "interval", + "options": [ + { + "selected": false, + "text": "auto", + "value": "$__auto_interval_interval" + }, + { + "selected": false, + "text": "10s", + "value": "10s" + }, + { + "selected": true, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": false, + "text": "30m", + "value": "30m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + } + ], + "query": "10s,30s,1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", + "queryValue": "", + "refresh": 2, + "skipUrlSync": false, + "type": "interval" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(ceph_osd_up, ceph_daemon)", + "hide": 0, + "includeAll": false, + "label": "OSD", + "multi": false, + "name": "osd", + "options": [], + "query": { + "query": "label_values(ceph_osd_up, ceph_daemon)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Ceph - OSD (Single)", + "uid": "Fj5fAfzik", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/deploy/examples/monitoring/grafana/Ceph Pools Dashboard.json b/deploy/examples/monitoring/grafana/Ceph Pools Dashboard.json new file mode 100644 index 000000000000..3ea91bb90167 --- /dev/null +++ b/deploy/examples/monitoring/grafana/Ceph Pools Dashboard.json @@ -0,0 +1,925 @@ +{ + "__inputs": [], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.0.5" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Ceph Pools dashboard.", + "editable": false, + "fiscalYearStartMonth": 0, + "gnetId": 5342, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 11, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "refId": "A" + } + ], + "title": "Pool: $pool", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 30, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^Total.*$/" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.lineWidth", + "value": 4 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^Raw.*$/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.lineWidth", + "value": 4 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 20, + "x": 0, + "y": 1 + }, + "id": 2, + "interval": "$interval", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_max_avail) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "hide": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Available - {{ name }}", + "metric": "ceph_pool_available_bytes", + "refId": "A", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_stored) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "hide": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Stored - {{ name }}", + "metric": "ceph_pool", + "refId": "B", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_stored + ceph_pool_max_avail) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "hide": true, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Total - {{ name }}", + "metric": "ceph_pool", + "refId": "C", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_stored_raw) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "hide": false, + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Raw - {{ name }}", + "metric": "ceph_pool", + "refId": "D", + "step": 60 + } + ], + "title": "Pool Storage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 1, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 75 + }, + { + "color": "red", + "value": 90 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 20, + "y": 1 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum without (instance, pool_id, name) ((ceph_pool_stored / (ceph_pool_stored + ceph_pool_max_avail)) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"}))", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 60 + } + ], + "title": "Usage", + "type": "gauge" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 12, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "refId": "A" + } + ], + "title": "Pool Info", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 7, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_objects) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Objects - {{ name }}", + "refId": "A", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_dirty) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Dirty Objects - {{ name }}", + "refId": "B", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((ceph_pool_quota_objects) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Quota Objects - {{ name }}", + "refId": "C" + } + ], + "title": "Objects in Pool", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "IOPS", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 4, + "interval": "$interval", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((irate(ceph_pool_rd[3m])) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Read - {{ name }}", + "refId": "B", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((irate(ceph_pool_wr[3m])) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Write - {{ name }}", + "refId": "A", + "step": 60 + } + ], + "title": "IOPS", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 5, + "interval": "$interval", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.1.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((irate(ceph_pool_rd_bytes[5m])) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Read Bytes - {{ name }}", + "refId": "A", + "step": 60 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "sum((irate(ceph_pool_wr_bytes[5m])) *on (pool_id) group_left(name)(ceph_pool_metadata{name=~\"^$pool$\"})) by (name)", + "format": "time_series", + "interval": "$interval", + "intervalFactor": 1, + "legendFormat": "Written Bytes - {{ name }}", + "refId": "B", + "step": 60 + } + ], + "title": "Throughput", + "type": "timeseries" + } + ], + "refresh": "1m", + "schemaVersion": 36, + "style": "dark", + "tags": [ + "ceph", + "pools" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "label": "Data source", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": true, + "auto_count": 10, + "auto_min": "1m", + "current": { + "selected": false, + "text": "30s", + "value": "30s" + }, + "datasource": "Prometheus", + "hide": 0, + "includeAll": false, + "label": "Interval", + "multi": false, + "name": "interval", + "options": [ + { + "selected": false, + "text": "auto", + "value": "$__auto_interval_interval" + }, + { + "selected": false, + "text": "10s", + "value": "10s" + }, + { + "selected": true, + "text": "30s", + "value": "30s" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": false, + "text": "30m", + "value": "30m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + } + ], + "query": "10s,30s,1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", + "queryValue": "", + "refresh": 2, + "skipUrlSync": false, + "type": "interval" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(ceph_pool_metadata, name)", + "hide": 0, + "includeAll": true, + "label": "Pool", + "multi": true, + "name": "pool", + "options": [], + "query": { + "query": "label_values(ceph_pool_metadata, name)", + "refId": "Prometheus-pool-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 3, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Ceph - Pools", + "uid": "-gtf0Bzik", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/deploy/examples/monitoring/grafana/README.md b/deploy/examples/monitoring/grafana/README.md new file mode 100644 index 000000000000..225dd3566728 --- /dev/null +++ b/deploy/examples/monitoring/grafana/README.md @@ -0,0 +1,12 @@ +# Grafana Dashboards + +This folder contains the JSON files for the Grafana dashboards. +The dashboards are based upon [the official Ceph Grafana dashboards](https://github.com/ceph/ceph/tree/main/monitoring/ceph-mixin) but with some slight tweaks. + +## Updating the Dashboards + +To update the dashboards, please export them via Grafana's built-in export function. + +Please note that exporting a dashboard from Grafana, that version of Grafana will be the minimum required version for all users. For example, exporting from Grafana 9.1.0 would require all users to also have at least Grafana version 9.1.0 running. + +So it might be a good idea to take that into account when updating the dashboards. From 325950239b347ff8a2fee46613e04ad653a99c2b Mon Sep 17 00:00:00 2001 From: Alexander Trost Date: Wed, 4 Sep 2024 15:31:36 +0200 Subject: [PATCH 15/54] ci: code spell ignore grafana dashboard json files Signed-off-by: Alexander Trost --- .github/workflows/codespell.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codespell.yaml b/.github/workflows/codespell.yaml index 961dcd7d23c7..78f387374c30 100644 --- a/.github/workflows/codespell.yaml +++ b/.github/workflows/codespell.yaml @@ -34,7 +34,8 @@ jobs: # in other places, so ignore the file itself assuming it is correct # crds.yaml, resources.yaml: CRD files are fully generated from content we control (should # be flagged elsewhere) and content we don't control (can't fix easily), so ignore - skip: .git,*.png,*.jpg,*.svg,*.sum,./LICENSE,./deploy/examples/crds.yaml,./deploy/charts/rook-ceph/templates/resources.yaml,./deploy/examples/csi-operator.yaml + # *Dashboard.jjson: Grafana dashboards that are generated via exporting them from Grafana. + skip: .git,*.png,*.jpg,*.svg,*.sum,./LICENSE,./deploy/examples/crds.yaml,./deploy/charts/rook-ceph/templates/resources.yaml,./deploy/examples/csi-operator.yaml,*Dashboard.json # aks: Amazon Kubernetes Service # keyserver: flag to apt-key # atleast: codespell wants to flag any 'AtLeast' method From 3d06aee626c949d8d7b761d16bc3d0d0e034459c Mon Sep 17 00:00:00 2001 From: Nikhil-Ladha Date: Fri, 13 Sep 2024 17:55:36 +0530 Subject: [PATCH 16/54] external: add a new configmap to store external cluster script add a new static configmap to store the external cluster script and ship it as part of the rook bundle Signed-off-by: Nikhil-Ladha --- build/csv/csv-gen.sh | 4 ++++ deploy/examples/external-cluster-script-configmap.yaml | 9 +++++++++ deploy/examples/kustomization.yaml | 1 + 3 files changed, 14 insertions(+) create mode 100644 deploy/examples/external-cluster-script-configmap.yaml diff --git a/build/csv/csv-gen.sh b/build/csv/csv-gen.sh index 0c4ae2a2e571..97e163fec3ec 100755 --- a/build/csv/csv-gen.sh +++ b/build/csv/csv-gen.sh @@ -16,6 +16,7 @@ YQ_CMD_MERGE_OVERWRITE=("$yq" merge --inplace --overwrite --prettyPrint) YQ_CMD_MERGE=("$yq" merge --arrays=append --inplace) YQ_CMD_WRITE=("$yq" write --inplace -P) CSV_FILE_NAME="../../build/csv/ceph/$PLATFORM/manifests/rook-ceph-operator.clusterserviceversion.yaml" +EXTERNAL_CLUSTER_SCRIPT_CONFIGMAP="../../build/csv/ceph/$PLATFORM/manifests/rook-ceph-external-cluster-script-config_v1_configmap.yaml" CEPH_EXTERNAL_SCRIPT_FILE="../../deploy/examples/create-external-cluster-resources.py" ASSEMBLE_FILE_COMMON="../../deploy/olm/assemble/metadata-common.yaml" ASSEMBLE_FILE_OCP="../../deploy/olm/assemble/metadata-ocp.yaml" @@ -66,6 +67,9 @@ function generate_csv() { # We don't need to include these files in csv as ocs-operator creates its own. rm -rf "../../build/csv/ceph/$PLATFORM/manifests/rook-ceph-operator-config_v1_configmap.yaml" + # Update the "create-external-resources.py" script value in external-cluster-script-configmap + "${YQ_CMD_WRITE[@]}" "$EXTERNAL_CLUSTER_SCRIPT_CONFIGMAP" data.script "$(base64 <$CEPH_EXTERNAL_SCRIPT_FILE)" + # This change are just to make the CSV file as it was earlier and as ocs-operator reads. # Skipping this change for darwin since `sed -i` doesn't work with darwin properly. # and the csv is not ever needed in the mac builds. diff --git a/deploy/examples/external-cluster-script-configmap.yaml b/deploy/examples/external-cluster-script-configmap.yaml new file mode 100644 index 000000000000..4edbbdd65bc6 --- /dev/null +++ b/deploy/examples/external-cluster-script-configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +data: + # The below field will contain the "create-external-cluster-resources.py" script. + # Use the updated configmap with the base64 encoded script value stored under + # build/csv/ceph directory. + script: "" +kind: ConfigMap +metadata: + name: rook-ceph-external-cluster-script-config diff --git a/deploy/examples/kustomization.yaml b/deploy/examples/kustomization.yaml index 5bed5c3e8e11..7d2bc4d6432a 100644 --- a/deploy/examples/kustomization.yaml +++ b/deploy/examples/kustomization.yaml @@ -6,3 +6,4 @@ resources: - common.yaml - operator-openshift.yaml - csi/nfs/rbac.yaml + - external-cluster-script-configmap.yaml From 0f87de9f39feebc0b8cc61bb831c614d149e661b Mon Sep 17 00:00:00 2001 From: Nikhil-Ladha Date: Fri, 13 Sep 2024 17:59:32 +0530 Subject: [PATCH 17/54] csv: add generated changes add generated configmap changes Signed-off-by: Nikhil-Ladha --- ...al-cluster-script-config_v1_configmap.yaml | 1695 +++++++++++++++++ 1 file changed, 1695 insertions(+) create mode 100644 build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml diff --git a/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml b/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml new file mode 100644 index 000000000000..f1e95f9061d1 --- /dev/null +++ b/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml @@ -0,0 +1,1695 @@ +apiVersion: v1 +data: + script: |- + IiIiCkNvcHlyaWdodCAyMDIwIFRoZSBSb29rIEF1dGhvcnMuIEFsbCByaWdodHMgcmVzZXJ2ZWQu + CgpMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxp + Y2Vuc2UiKTsKeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3 + aXRoIHRoZSBMaWNlbnNlLgpZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQK + CglodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKClVubGVzcyByZXF1 + aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUK + ZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElT + IiBCQVNJUywKV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVp + dGhlciBleHByZXNzIG9yIGltcGxpZWQuClNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmlj + IGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKbGltaXRhdGlvbnMgdW5kZXIgdGhl + IExpY2Vuc2UuCiIiIgoKaW1wb3J0IGVycm5vCmltcG9ydCBzeXMKaW1wb3J0IGpzb24KaW1wb3J0 + IGFyZ3BhcnNlCmltcG9ydCByZQppbXBvcnQgc3VicHJvY2VzcwppbXBvcnQgaG1hYwppbXBvcnQg + Y29uZmlncGFyc2VyCmZyb20gaGFzaGxpYiBpbXBvcnQgc2hhMSBhcyBzaGEKZnJvbSBvcyBpbXBv + cnQgbGluZXNlcCBhcyBMSU5FU0VQCmZyb20gb3MgaW1wb3J0IHBhdGgKZnJvbSBlbWFpbC51dGls + cyBpbXBvcnQgZm9ybWF0ZGF0ZQppbXBvcnQgcmVxdWVzdHMKZnJvbSByZXF1ZXN0cy5hdXRoIGlt + cG9ydCBBdXRoQmFzZQpmcm9tIGlvIGltcG9ydCBTdHJpbmdJTwpmcm9tIHVybGxpYi5wYXJzZSBp + bXBvcnQgdXJscGFyc2UKZnJvbSB1cmxsaWIucGFyc2UgaW1wb3J0IHVybGVuY29kZSBhcyB1cmxl + bmNvZGUKZnJvbSBpcGFkZHJlc3MgaW1wb3J0IGlwX2FkZHJlc3MKZnJvbSBpcGFkZHJlc3MgaW1w + b3J0IElQdjRBZGRyZXNzCmZyb20gYmFzZTY0IGltcG9ydCBlbmNvZGVieXRlcyBhcyBlbmNvZGVz + dHJpbmcKCk1vZHVsZU5vdEZvdW5kRXJyb3IgPSBJbXBvcnRFcnJvcgoKdHJ5OgogICAgaW1wb3J0 + IHJhZG9zCmV4Y2VwdCBNb2R1bGVOb3RGb3VuZEVycm9yIGFzIG5vTW9kRXJyOgogICAgcHJpbnQo + ZiJFcnJvcjoge25vTW9kRXJyfVxuRXhpdGluZyB0aGUgc2NyaXB0Li4uIikKICAgIHN5cy5leGl0 + KDEpCgp0cnk6CiAgICBpbXBvcnQgcmJkCmV4Y2VwdCBNb2R1bGVOb3RGb3VuZEVycm9yIGFzIG5v + TW9kRXJyOgogICAgcHJpbnQoZiJFcnJvcjoge25vTW9kRXJyfVxuRXhpdGluZyB0aGUgc2NyaXB0 + Li4uIikKICAgIHN5cy5leGl0KDEpCgoKY2xhc3MgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbihF + eGNlcHRpb24pOgogICAgcGFzcwoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj + IyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMgRHVtbXlSYWRvcyAjIyMjIyMjIyMjIyMj + IyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMg + dGhpcyBpcyBtYWlubHkgZm9yIHRlc3RpbmcgYW5kIGNvdWxkIGJlIHVzZWQgd2hlcmUgJ3JhZG9z + JyBpcyBub3QgYXZhaWxhYmxlCgoKY2xhc3MgRHVtbXlSYWRvcyhvYmplY3QpOgogICAgZGVmIF9f + aW5pdF9fKHNlbGYpOgogICAgICAgIHNlbGYucmV0dXJuX3ZhbCA9IDAKICAgICAgICBzZWxmLmVy + cl9tZXNzYWdlID0gIiIKICAgICAgICBzZWxmLnN0YXRlID0gImNvbm5lY3RlZCIKICAgICAgICBz + ZWxmLmNtZF9vdXRwdXRfbWFwID0ge30KICAgICAgICBzZWxmLmNtZF9uYW1lcyA9IHt9CiAgICAg + ICAgc2VsZi5faW5pdF9jbWRfb3V0cHV0X21hcCgpCiAgICAgICAgc2VsZi5kdW1teV9ob3N0X2lw + X21hcCA9IHt9CgogICAgZGVmIF9pbml0X2NtZF9vdXRwdXRfbWFwKHNlbGYpOgogICAgICAgIGpz + b25fZmlsZV9uYW1lID0gInRlc3QtZGF0YS9jZXBoLXN0YXR1cy1vdXQiCiAgICAgICAgc2NyaXB0 + X2RpciA9IHBhdGguYWJzcGF0aChwYXRoLmRpcm5hbWUoX19maWxlX18pKQogICAgICAgIGNlcGhf + c3RhdHVzX3N0ciA9ICIiCiAgICAgICAgd2l0aCBvcGVuKAogICAgICAgICAgICBwYXRoLmpvaW4o + c2NyaXB0X2RpciwganNvbl9maWxlX25hbWUpLCBtb2RlPSJyIiwgZW5jb2Rpbmc9IlVURi04Igog + ICAgICAgICkgYXMganNvbl9maWxlOgogICAgICAgICAgICBjZXBoX3N0YXR1c19zdHIgPSBqc29u + X2ZpbGUucmVhZCgpCiAgICAgICAgc2VsZi5jbWRfbmFtZXNbImZzIGxzIl0gPSAiIiJ7ImZvcm1h + dCI6ICJqc29uIiwgInByZWZpeCI6ICJmcyBscyJ9IiIiCiAgICAgICAgc2VsZi5jbWRfbmFtZXNb + InF1b3J1bV9zdGF0dXMiXSA9ICgKICAgICAgICAgICAgIiIieyJmb3JtYXQiOiAianNvbiIsICJw + cmVmaXgiOiAicXVvcnVtX3N0YXR1cyJ9IiIiCiAgICAgICAgKQogICAgICAgIHNlbGYuY21kX25h + bWVzWyJtZ3Igc2VydmljZXMiXSA9ICgKICAgICAgICAgICAgIiIieyJmb3JtYXQiOiAianNvbiIs + ICJwcmVmaXgiOiAibWdyIHNlcnZpY2VzIn0iIiIKICAgICAgICApCiAgICAgICAgIyBhbGwgdGhl + IGNvbW1hbmRzIGFuZCB0aGVpciBvdXRwdXQKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwW3Nl + bGYuY21kX25hbWVzWyJmcyBscyJdXSA9ICgKICAgICAgICAgICAgIiIiW3sibmFtZSI6Im15ZnMi + LCJtZXRhZGF0YV9wb29sIjoibXlmcy1tZXRhZGF0YSIsIm1ldGFkYXRhX3Bvb2xfaWQiOjIsImRh + dGFfcG9vbF9pZHMiOlszXSwiZGF0YV9wb29scyI6WyJteWZzLXJlcGxpY2F0ZWQiXX1dIiIiCiAg + ICAgICAgKQogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbc2VsZi5jbWRfbmFtZXNbInF1b3J1 + bV9zdGF0dXMiXV0gPSAoCiAgICAgICAgICAgICIiInsiZWxlY3Rpb25fZXBvY2giOjMsInF1b3J1 + bSI6WzBdLCJxdW9ydW1fbmFtZXMiOlsiYSJdLCJxdW9ydW1fbGVhZGVyX25hbWUiOiJhIiwicXVv + cnVtX2FnZSI6MTQzODUsImZlYXR1cmVzIjp7InF1b3J1bV9jb24iOiI0NTQwMTM4MjkyODM2Njk2 + MDYzIiwicXVvcnVtX21vbiI6WyJrcmFrZW4iLCJsdW1pbm91cyIsIm1pbWljIiwib3NkbWFwLXBy + dW5lIiwibmF1dGlsdXMiLCJvY3RvcHVzIl19LCJtb25tYXAiOnsiZXBvY2giOjEsImZzaWQiOiJh + ZjRlMTY3My0wYjcyLTQwMmQtOTkwYS0yMmQyOTE5ZDBmMWMiLCJtb2RpZmllZCI6IjIwMjAtMDUt + MDdUMDM6MzY6MzkuOTE4MDM1WiIsImNyZWF0ZWQiOiIyMDIwLTA1LTA3VDAzOjM2OjM5LjkxODAz + NVoiLCJtaW5fbW9uX3JlbGVhc2UiOjE1LCJtaW5fbW9uX3JlbGVhc2VfbmFtZSI6Im9jdG9wdXMi + LCJmZWF0dXJlcyI6eyJwZXJzaXN0ZW50IjpbImtyYWtlbiIsImx1bWlub3VzIiwibWltaWMiLCJv + c2RtYXAtcHJ1bmUiLCJuYXV0aWx1cyIsIm9jdG9wdXMiXSwib3B0aW9uYWwiOltdfSwibW9ucyI6 + W3sicmFuayI6MCwibmFtZSI6ImEiLCJwdWJsaWNfYWRkcnMiOnsiYWRkcnZlYyI6W3sidHlwZSI6 + InYyIiwiYWRkciI6IjEwLjExMC4yMDUuMTc0OjMzMDAiLCJub25jZSI6MH0seyJ0eXBlIjoidjEi + LCJhZGRyIjoiMTAuMTEwLjIwNS4xNzQ6Njc4OSIsIm5vbmNlIjowfV19LCJhZGRyIjoiMTAuMTEw + LjIwNS4xNzQ6Njc4OS8wIiwicHVibGljX2FkZHIiOiIxMC4xMTAuMjA1LjE3NDo2Nzg5LzAiLCJw + cmlvcml0eSI6MCwid2VpZ2h0IjowfV19fSIiIgogICAgICAgICkKICAgICAgICBzZWxmLmNtZF9v + dXRwdXRfbWFwW3NlbGYuY21kX25hbWVzWyJtZ3Igc2VydmljZXMiXV0gPSAoCiAgICAgICAgICAg + ICIiInsiZGFzaGJvYXJkIjoiaHR0cHM6Ly9jZXBoLWRhc2hib2FyZDo4NDQzLyIsInByb21ldGhl + dXMiOiJodHRwOi8vY2VwaC1kYXNoYm9hcmQtZGI6OTI4My8ifSIiIgogICAgICAgICkKICAgICAg + ICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJh + bGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMiLCAib3NkIiwgInByb2ZpbGUgcmJk + LXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBwb29s + PS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyB4IHBv + b2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJdLCAiZW50aXR5IjogImNsaWVudC5oZWFsdGhj + aGVja2VyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUi + fSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuaGVhbHRoY2hlY2tlciIsImtl + eSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNscmRBPT0iLCJjYXBzIjp7Im1v + biI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1cyIsIm9zZCI6InByb2ZpbGUg + cmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBw + b29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyB4 + IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9v + dXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJwcm9maWxlIHJiZCwg + YWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAib3NkIiwgInByb2ZpbGUgcmJkIl0sICJl + bnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtbm9kZSIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgi + OiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5IjoiY2xp + ZW50LmNzaS1yYmQtbm9kZSIsImtleSI6IkFRQk9nck5lSGJLMUF4QUF1YllCZVY4UzFVL0dQenE1 + U1ZlcTZnPT0iLCJjYXBzIjp7Im1vbiI6InByb2ZpbGUgcmJkLCBhbGxvdyBjb21tYW5kICdvc2Qg + YmxvY2tsaXN0JyIsIm9zZCI6InByb2ZpbGUgcmJkIn19XSIiIgogICAgICAgIHNlbGYuY21kX291 + dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgInByb2ZpbGUgcmJkLCBh + bGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwg + InByb2ZpbGUgcmJkIl0sICJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiLCAi + Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9IiIiCiAgICAg + ICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiwia2V5Ijoi + QVFCTmdyTmUxZ2V5S3hBQThla1ZpUmRFK2hzczVPd2VZQmt3Tmc9PSIsImNhcHMiOnsibWdyIjoi + YWxsb3cgcnciLCJtb24iOiJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlz + dCciLCJvc2QiOiJwcm9maWxlIHJiZCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFw + WwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5k + ICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3IHRh + ZyBjZXBoZnMgKj0qIiwgIm1kcyIsICJhbGxvdyBydyJdLCAiZW50aXR5IjogImNsaWVudC5jc2kt + Y2VwaGZzLW5vZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNy + ZWF0ZSJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLW5v + ZGUiLCJrZXkiOiJBUUJPZ3JOZUVOdW5LeEFBUENtZ0U3UjZHOERjWG5hSjFGMzJxZz09IiwiY2Fw + cyI6eyJtZHMiOiJhbGxvdyBydyIsIm1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxs + b3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzICo9 + KiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNh + cHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJt + Z3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiJd + LCAiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJq + c29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJb + eyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsImtleSI6IkFRQk9nck5l + QUZnY0dCQUF2R3FLT0FEMEQzeHhtVlkwUjkxMmRnPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3 + IiwibW9uIjoiYWxsb3cgciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJh + bGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0 + cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBzIjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cg + Y29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIsICJhbGxv + dyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiXSwgImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhm + cy1wcm92aXNpb25lci1vcGVuc2hpZnQtc3RvcmFnZSIsICJmb3JtYXQiOiAianNvbiIsICJwcmVm + aXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5Ijoi + Y2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UiLCJrZXkiOiJC + UUJPZ3JOZUFGZ2NHQkFBdkdxS09BRDBEM3h4bVZZMFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJh + bGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwi + b3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIn19XSIiIgogICAgICAgIHNlbGYu + Y21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgImFsbG93IHIs + IGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJhbGxvdyBydyIsICJvc2Qi + LCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT1teWZzIl0sICJlbnRpdHkiOiAiY2xpZW50 + LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UtbXlmcyIsICJmb3JtYXQi + OiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0g + IiIiW3siZW50aXR5IjoiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0 + b3JhZ2UtbXlmcyIsImtleSI6IkNRQk9nck5lQUZnY0dCQUF2R3FLT0FEMEQzeHhtVlkwUjkxMmRn + PT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxsb3cgY29tbWFu + ZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPW15 + ZnMifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJj + YXBzIjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxv + dyBjb21tYW5kIHZlcnNpb24iLCAibWdyIiwgImFsbG93IGNvbW1hbmQgY29uZmlnIiwgIm9zZCIs + ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3Lm1ldGEs + IGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9ZGVmYXVsdC5yZ3cuY29udHJv + bCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93IHggcG9vbD1kZWZhdWx0LnJn + dy5idWNrZXRzLmluZGV4Il0sICJlbnRpdHkiOiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCAiZm9y + bWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9IiIiCiAgICAgICAg + XSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5oZWFsdGhjaGVja2VyIiwia2V5IjoiQVFERmtiTmVm + dDViRlJBQVRuZExOVVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjogImFsbG93IHIs + IGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1cywgYWxsb3cgY29tbWFuZCB2ZXJzaW9uIiwgIm1n + ciI6ICJhbGxvdyBjb21tYW5kIGNvbmZpZyIsICJvc2QiOiAicHJvZmlsZSByYmQtcmVhZC1vbmx5 + LCBhbGxvdyByd3ggcG9vbD1kZWZhdWx0LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290 + LCBhbGxvdyBydyBwb29sPWRlZmF1bHQucmd3LmNvbnRyb2wsIGFsbG93IHJ4IHBvb2w9ZGVmYXVs + dC5yZ3cubG9nLCBhbGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIK + ICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1v + biIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQg + dmVyc2lvbiIsICJtZ3IiLCAiYWxsb3cgY29tbWFuZCBjb25maWciLCAib3NkIiwgInByb2ZpbGUg + cmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBw + b29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyBy + eCBwb29sPWRlZmF1bHQucmd3LmxvZywgYWxsb3cgeCBwb29sPWRlZmF1bHQucmd3LmJ1Y2tldHMu + aW5kZXgiXSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNv + biIsICJwcmVmaXgiOiAiYXV0aCBjYXBzIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5Ijoi + Y2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0NWJGUkFBVG5kTE5VU1JLcnVv + enhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBxdW9y + dW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdyIjogImFsbG93IGNvbW1hbmQg + Y29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPWRl + ZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9ZGVm + YXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93IHgg + cG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4In19XSIiIgogICAgICAgIHNlbGYuY21kX291 + dHB1dF9tYXBbIiIieyJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAibWdyIHNlcnZpY2VzIn0i + IiJdID0gKAogICAgICAgICAgICAiIiJ7ImRhc2hib2FyZCI6ICJodHRwOi8vcm9vay1jZXBoLW1n + ci1hLTU3Y2Y5Zjg0YmMtZjRqbmw6NzAwMC8iLCAicHJvbWV0aGV1cyI6ICJodHRwOi8vcm9vay1j + ZXBoLW1nci1hLTU3Y2Y5Zjg0YmMtZjRqbmw6OTI4My8ifSIiIgogICAgICAgICkKICAgICAgICBz + ZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuaGVh + bHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgog + ICAgICAgIF0gPSAiIiJ7ImRhc2hib2FyZCI6ICJodHRwOi8vcm9vay1jZXBoLW1nci1hLTU3Y2Y5 + Zjg0YmMtZjRqbmw6NzAwMC8iLCAicHJvbWV0aGV1cyI6ICJodHRwOi8vcm9vay1jZXBoLW1nci1h + LTU3Y2Y5Zjg0YmMtZjRqbmw6OTI4My8ifSIiIgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBb + CiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5oZWFsdGhjaGVja2VyIiwgImZvcm1h + dCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVu + dGl0eSI6ImNsaWVudC5oZWFsdGhjaGVja2VyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExO + VVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjogImFsbG93IHIsIGFsbG93IGNvbW1h + bmQgcXVvcnVtX3N0YXR1cywgYWxsb3cgY29tbWFuZCB2ZXJzaW9uIiwgIm1nciI6ICJhbGxvdyBj + b21tYW5kIGNvbmZpZyIsICJvc2QiOiAicHJvZmlsZSByYmQtcmVhZC1vbmx5LCBhbGxvdyByd3gg + cG9vbD1kZWZhdWx0LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290LCBhbGxvdyBydyBw + b29sPWRlZmF1bHQucmd3LmNvbnRyb2wsIGFsbG93IHJ4IHBvb2w9ZGVmYXVsdC5yZ3cubG9nLCBh + bGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIKICAgICAgICBzZWxm + LmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuY3NpLWNl + cGhmcy1ub2RlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAg + ICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAg + ICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtbm9kZSIsICJmb3JtYXQiOiAianNvbiIs + ICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIiIgogICAgICAgIHNl + bGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5jc2kt + cmJkLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9 + IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAg + ICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAi + Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0gIiIi + W10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0 + eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lci1vcGVuc2hpZnQtc3RvcmFnZSIsICJm + b3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJb + XSIiIgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5 + IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMi + LCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0g + IiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVu + dGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQiOiAianNvbiIs + ICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGll + bnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVT + RUtydW96eGlaaTNscmRBPT0iLCJjYXBzIjp7Im1vbiI6ImFsbG93IHIiLCAibWdyIjoiYWxsb3cg + cnciLCAib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIn19XSIiIgogICAgICAg + IHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgImFs + bG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJhbGxvdyBydyIs + ICJvc2QiLCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIl0sICJlbnRpdHkiOiAiY2xp + ZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4Ijog + ImF1dGggY2FwcyJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2Vw + aGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExOVVNFS3J1b3p4aVpp + M2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cgciwgIGFsbG93IGNvbW1hbmQgJ29zZCBibG9j + a2xpc3QnIiwgIm1nciI6ImFsbG93IHJ3IiwgIm9zZCI6ImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0 + YWRhdGE9KiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWyd7ImZvcm1hdCI6ICJq + c29uIiwgInByZWZpeCI6ICJzdGF0dXMifSddID0gY2VwaF9zdGF0dXNfc3RyCgogICAgZGVmIHNo + dXRkb3duKHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgZ2V0X2ZzaWQoc2VsZik6CiAgICAg + ICAgcmV0dXJuICJhZjRlMTY3My0wYjcyLTQwMmQtOTkwYS0yMmQyOTE5ZDBmMWMiCgogICAgZGVm + IGNvbmZfcmVhZF9maWxlKHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgY29ubmVjdChzZWxm + KToKICAgICAgICBwYXNzCgogICAgZGVmIHBvb2xfZXhpc3RzKHNlbGYsIHBvb2xfbmFtZSk6CiAg + ICAgICAgcmV0dXJuIFRydWUKCiAgICBkZWYgbW9uX2NvbW1hbmQoc2VsZiwgY21kLCBvdXQpOgog + ICAgICAgIGpzb25fY21kID0ganNvbi5sb2FkcyhjbWQpCiAgICAgICAganNvbl9jbWRfc3RyID0g + anNvbi5kdW1wcyhqc29uX2NtZCwgc29ydF9rZXlzPVRydWUpCiAgICAgICAgY21kX291dHB1dCA9 + IHNlbGYuY21kX291dHB1dF9tYXBbanNvbl9jbWRfc3RyXQogICAgICAgIHJldHVybiBzZWxmLnJl + dHVybl92YWwsIGNtZF9vdXRwdXQsIHN0cihzZWxmLmVycl9tZXNzYWdlLmVuY29kZSgidXRmLTgi + KSkKCiAgICBkZWYgX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoc2VsZiwgaG9zdF9uYW1lKToKICAg + ICAgICBpcF9yZWdfeCA9IHJlLmNvbXBpbGUociJcZHsxLDN9LlxkezEsM30uXGR7MSwzfS5cZHsx + LDN9IikKICAgICAgICAjIGlmIHByb3ZpZGVkIGhvc3QgaXMgZGlyZWN0bHkgYW4gSVAgYWRkcmVz + cywgcmV0dXJuIHRoZSBzYW1lCiAgICAgICAgaWYgaXBfcmVnX3gubWF0Y2goaG9zdF9uYW1lKToK + ICAgICAgICAgICAgcmV0dXJuIGhvc3RfbmFtZQogICAgICAgIGltcG9ydCByYW5kb20KCiAgICAg + ICAgaG9zdF9pcCA9IHNlbGYuZHVtbXlfaG9zdF9pcF9tYXAuZ2V0KGhvc3RfbmFtZSwgIiIpCiAg + ICAgICAgaWYgbm90IGhvc3RfaXA6CiAgICAgICAgICAgIGhvc3RfaXAgPSBmIjE3Mi45LntyYW5k + b20ucmFuZGludCgwLCAyNTQpfS57cmFuZG9tLnJhbmRpbnQoMCwgMjU0KX0iCiAgICAgICAgICAg + IHNlbGYuZHVtbXlfaG9zdF9pcF9tYXBbaG9zdF9uYW1lXSA9IGhvc3RfaXAKICAgICAgICBkZWwg + cmFuZG9tCiAgICAgICAgcmV0dXJuIGhvc3RfaXAKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBS + YWRvcyhjb25mZmlsZT1Ob25lKToKICAgICAgICByZXR1cm4gRHVtbXlSYWRvcygpCgoKY2xhc3Mg + UzNBdXRoKEF1dGhCYXNlKToKICAgICIiIkF0dGFjaGVzIEFXUyBBdXRoZW50aWNhdGlvbiB0byB0 + aGUgZ2l2ZW4gUmVxdWVzdCBvYmplY3QuIiIiCgogICAgc2VydmljZV9iYXNlX3VybCA9ICJzMy5h + bWF6b25hd3MuY29tIgoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhY2Nlc3Nfa2V5LCBzZWNyZXRf + a2V5LCBzZXJ2aWNlX3VybD1Ob25lKToKICAgICAgICBpZiBzZXJ2aWNlX3VybDoKICAgICAgICAg + ICAgc2VsZi5zZXJ2aWNlX2Jhc2VfdXJsID0gc2VydmljZV91cmwKICAgICAgICBzZWxmLmFjY2Vz + c19rZXkgPSBzdHIoYWNjZXNzX2tleSkKICAgICAgICBzZWxmLnNlY3JldF9rZXkgPSBzdHIoc2Vj + cmV0X2tleSkKCiAgICBkZWYgX19jYWxsX18oc2VsZiwgcik6CiAgICAgICAgIyBDcmVhdGUgZGF0 + ZSBoZWFkZXIgaWYgaXQgaXMgbm90IGNyZWF0ZWQgeWV0LgogICAgICAgIGlmICJkYXRlIiBub3Qg + aW4gci5oZWFkZXJzIGFuZCAieC1hbXotZGF0ZSIgbm90IGluIHIuaGVhZGVyczoKICAgICAgICAg + ICAgci5oZWFkZXJzWyJkYXRlIl0gPSBmb3JtYXRkYXRlKHRpbWV2YWw9Tm9uZSwgbG9jYWx0aW1l + PUZhbHNlLCB1c2VnbXQ9VHJ1ZSkKICAgICAgICBzaWduYXR1cmUgPSBzZWxmLmdldF9zaWduYXR1 + cmUocikKICAgICAgICBzaWduYXR1cmUgPSBzaWduYXR1cmUuZGVjb2RlKCJ1dGYtOCIpCiAgICAg + ICAgci5oZWFkZXJzWyJBdXRob3JpemF0aW9uIl0gPSBmIkFXUyB7c2VsZi5hY2Nlc3Nfa2V5fTp7 + c2lnbmF0dXJlfSIKICAgICAgICByZXR1cm4gcgoKICAgIGRlZiBnZXRfc2lnbmF0dXJlKHNlbGYs + IHIpOgogICAgICAgIGNhbm9uaWNhbF9zdHJpbmcgPSBzZWxmLmdldF9jYW5vbmljYWxfc3RyaW5n + KHIudXJsLCByLmhlYWRlcnMsIHIubWV0aG9kKQogICAgICAgIGtleSA9IHNlbGYuc2VjcmV0X2tl + eS5lbmNvZGUoInV0Zi04IikKICAgICAgICBtc2cgPSBjYW5vbmljYWxfc3RyaW5nLmVuY29kZSgi + dXRmLTgiKQogICAgICAgIGggPSBobWFjLm5ldyhrZXksIG1zZywgZGlnZXN0bW9kPXNoYSkKICAg + ICAgICByZXR1cm4gZW5jb2Rlc3RyaW5nKGguZGlnZXN0KCkpLnN0cmlwKCkKCiAgICBkZWYgZ2V0 + X2Nhbm9uaWNhbF9zdHJpbmcoc2VsZiwgdXJsLCBoZWFkZXJzLCBtZXRob2QpOgogICAgICAgIHBh + cnNlZHVybCA9IHVybHBhcnNlKHVybCkKICAgICAgICBvYmplY3RrZXkgPSBwYXJzZWR1cmwucGF0 + aFsxOl0KCiAgICAgICAgYnVja2V0ID0gcGFyc2VkdXJsLm5ldGxvY1s6IC1sZW4oc2VsZi5zZXJ2 + aWNlX2Jhc2VfdXJsKV0KICAgICAgICBpZiBsZW4oYnVja2V0KSA+IDE6CiAgICAgICAgICAgICMg + cmVtb3ZlIGxhc3QgZG90CiAgICAgICAgICAgIGJ1Y2tldCA9IGJ1Y2tldFs6LTFdCgogICAgICAg + IGludGVyZXN0aW5nX2hlYWRlcnMgPSB7ImNvbnRlbnQtbWQ1IjogIiIsICJjb250ZW50LXR5cGUi + OiAiIiwgImRhdGUiOiAiIn0KICAgICAgICBmb3Iga2V5IGluIGhlYWRlcnM6CiAgICAgICAgICAg + IGxrID0ga2V5Lmxvd2VyKCkKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgbGsgPSBs + ay5kZWNvZGUoInV0Zi04IikKICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgcGFz + cwogICAgICAgICAgICBpZiBoZWFkZXJzW2tleV0gYW5kICgKICAgICAgICAgICAgICAgIGxrIGlu + IGludGVyZXN0aW5nX2hlYWRlcnMua2V5cygpIG9yIGxrLnN0YXJ0c3dpdGgoIngtYW16LSIpCiAg + ICAgICAgICAgICk6CiAgICAgICAgICAgICAgICBpbnRlcmVzdGluZ19oZWFkZXJzW2xrXSA9IGhl + YWRlcnNba2V5XS5zdHJpcCgpCgogICAgICAgICMgSWYgeC1hbXotZGF0ZSBpcyB1c2VkIGl0IHN1 + cGVyc2VkZXMgdGhlIGRhdGUgaGVhZGVyLgogICAgICAgIGlmICJ4LWFtei1kYXRlIiBpbiBpbnRl + cmVzdGluZ19oZWFkZXJzOgogICAgICAgICAgICBpbnRlcmVzdGluZ19oZWFkZXJzWyJkYXRlIl0g + PSAiIgoKICAgICAgICBidWYgPSBmInttZXRob2R9XG4iCiAgICAgICAgZm9yIGtleSBpbiBzb3J0 + ZWQoaW50ZXJlc3RpbmdfaGVhZGVycy5rZXlzKCkpOgogICAgICAgICAgICB2YWwgPSBpbnRlcmVz + dGluZ19oZWFkZXJzW2tleV0KICAgICAgICAgICAgaWYga2V5LnN0YXJ0c3dpdGgoIngtYW16LSIp + OgogICAgICAgICAgICAgICAgYnVmICs9IGYie2tleX06e3ZhbH1cbiIKICAgICAgICAgICAgZWxz + ZToKICAgICAgICAgICAgICAgIGJ1ZiArPSBmInt2YWx9XG4iCgogICAgICAgICMgYXBwZW5kIHRo + ZSBidWNrZXQgaWYgaXQgZXhpc3RzCiAgICAgICAgaWYgYnVja2V0ICE9ICIiOgogICAgICAgICAg + ICBidWYgKz0gZiIve2J1Y2tldH0iCgogICAgICAgICMgYWRkIHRoZSBvYmplY3RrZXkuIGV2ZW4g + aWYgaXQgZG9lc24ndCBleGlzdCwgYWRkIHRoZSBzbGFzaAogICAgICAgIGJ1ZiArPSBmIi97b2Jq + ZWN0a2V5fSIKCiAgICAgICAgcmV0dXJuIGJ1ZgoKCmNsYXNzIFJhZG9zSlNPTjoKICAgIEVYVEVS + TkFMX1VTRVJfTkFNRSA9ICJjbGllbnQuaGVhbHRoY2hlY2tlciIKICAgIEVYVEVSTkFMX1JHV19B + RE1JTl9PUFNfVVNFUl9OQU1FID0gInJndy1hZG1pbi1vcHMtdXNlciIKICAgIEVNUFRZX09VVFBV + VF9MSVNUID0gIkVtcHR5IG91dHB1dCBsaXN0IgogICAgREVGQVVMVF9SR1dfUE9PTF9QUkVGSVgg + PSAiZGVmYXVsdCIKICAgIERFRkFVTFRfTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUID0gIjkyODMi + CgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgZ2VuX2FyZ19wYXJzZXIoY2xzLCBhcmdzX3RvX3Bh + cnNlPU5vbmUpOgogICAgICAgIGFyZ1AgPSBhcmdwYXJzZS5Bcmd1bWVudFBhcnNlcigpCgogICAg + ICAgIGNvbW1vbl9ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJjb21tb24iKQogICAg + ICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoIi0tdmVyYm9zZSIsICItdiIsIGFjdGlvbj0i + c3RvcmVfdHJ1ZSIsIGRlZmF1bHQ9RmFsc2UpCiAgICAgICAgY29tbW9uX2dyb3VwLmFkZF9hcmd1 + bWVudCgKICAgICAgICAgICAgIi0tY2VwaC1jb25mIiwgIi1jIiwgaGVscD0iUHJvdmlkZSBhIGNl + cGggY29uZiBmaWxlLiIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiCiAgICAgICAgKQogICAgICAgIGNv + bW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWtleXJpbmciLCAiLWsiLCBo + ZWxwPSJQYXRoIHRvIGNlcGgga2V5cmluZyBmaWxlLiIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiCiAg + ICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICIt + LXJ1bi1hcy11c2VyIiwKICAgICAgICAgICAgIi11IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwK + ICAgICAgICAgICAgdHlwZT1zdHIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIGEgdXNlciBu + YW1lIHRvIGNoZWNrIHRoZSBjbHVzdGVyJ3MgaGVhbHRoIHN0YXR1cywgbXVzdCBiZSBwcmVmaXhl + ZCBieSAnY2xpZW50LiciLAogICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3Vt + ZW50KAogICAgICAgICAgICAiLS1jbHVzdGVyLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIi + LAogICAgICAgICAgICBoZWxwPSJLdWJlcm5ldGVzIGNsdXN0ZXIgbmFtZShsZWdhY3kgZmxhZyks + IE5vdGU6IEVpdGhlciB1c2UgdGhpcyBvciAtLWs4cy1jbHVzdGVyLW5hbWUiLAogICAgICAgICkK + ICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1rOHMtY2x1 + c3Rlci1uYW1lIiwgZGVmYXVsdD0iIiwgaGVscD0iS3ViZXJuZXRlcyBjbHVzdGVyIG5hbWUiCiAg + ICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICIt + LW5hbWVzcGFjZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9Ik5h + bWVzcGFjZSB3aGVyZSBDZXBoQ2x1c3RlciBpcyBydW5uaW5nIiwKICAgICAgICApCiAgICAgICAg + Y29tbW9uX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXBvb2wtcHJlZml4 + IiwgZGVmYXVsdD0iIiwgaGVscD0iUkdXIFBvb2wgcHJlZml4IgogICAgICAgICkKICAgICAgICBj + b21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yZXN0cmljdGVkLWF1dGgt + cGVybWlzc2lvbiIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9 + IlJlc3RyaWN0IGNlcGhDU0lLZXlyaW5ncyBhdXRoIHBlcm1pc3Npb25zIHRvIHNwZWNpZmljIHBv + b2xzLCBjbHVzdGVyLiIKICAgICAgICAgICAgKyAiTWFuZGF0b3J5IGZsYWdzIHRoYXQgbmVlZCB0 + byBiZSBzZXQgYXJlIC0tcmJkLWRhdGEtcG9vbC1uYW1lLCBhbmQgLS1rOHMtY2x1c3Rlci1uYW1l + LiIKICAgICAgICAgICAgKyAiLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIGZsYWcgY2FuIGFsc28g + YmUgcGFzc2VkIGluIGNhc2Ugb2YgY2VwaGZzIHVzZXIgcmVzdHJpY3Rpb24sIHNvIGl0IGNhbiBy + ZXN0cmljdCB1c2VyIHRvIHBhcnRpY3VsYXIgY2VwaGZzIGZpbGVzeXN0ZW0iCiAgICAgICAgICAg + ICsgInNhbXBsZSBydW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rl + ci1yZXNvdXJjZXMucHkgLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIG15ZnMgLS1yYmQtZGF0YS1w + b29sLW5hbWUgcmVwbGljYXBvb2wgLS1rOHMtY2x1c3Rlci1uYW1lIHJvb2tzdG9yYWdlIC0tcmVz + dHJpY3RlZC1hdXRoLXBlcm1pc3Npb24gdHJ1ZWAiCiAgICAgICAgICAgICsgIk5vdGU6IFJlc3Ry + aWN0aW5nIHRoZSBjc2ktdXNlcnMgcGVyIHBvb2wsIGFuZCBwZXIgY2x1c3RlciB3aWxsIHJlcXVp + cmUgY3JlYXRpbmcgbmV3IGNzaS11c2VycyBhbmQgbmV3IHNlY3JldHMgZm9yIHRoYXQgY3NpLXVz + ZXJzLiIKICAgICAgICAgICAgKyAiU28gYXBwbHkgdGhlc2Ugc2VjcmV0cyBvbmx5IHRvIG5ldyBg + Q29uc3VtZXIgY2x1c3RlcmAgZGVwbG95bWVudCB3aGlsZSB1c2luZyB0aGUgc2FtZSBgU291cmNl + IGNsdXN0ZXJgLiIsCiAgICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQo + CiAgICAgICAgICAgICItLXYyLXBvcnQtZW5hYmxlIiwKICAgICAgICAgICAgYWN0aW9uPSJzdG9y + ZV90cnVlIiwKICAgICAgICAgICAgZGVmYXVsdD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iRW5h + YmxlIHYyIG1vbiBwb3J0KDMzMDApIGZvciBtb25zIiwKICAgICAgICApCgogICAgICAgIG91dHB1 + dF9ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJvdXRwdXQiKQogICAgICAgIG91dHB1 + dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWZvcm1hdCIsCiAgICAgICAgICAg + ICItdCIsCiAgICAgICAgICAgIGNob2ljZXM9WyJqc29uIiwgImJhc2giXSwKICAgICAgICAgICAg + ZGVmYXVsdD0ianNvbiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBvdXRwdXQgZm9y + bWF0IChqc29uIHwgYmFzaCkiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy + Z3VtZW50KAogICAgICAgICAgICAiLS1vdXRwdXQiLAogICAgICAgICAgICAiLW8iLAogICAgICAg + ICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJPdXRwdXQgd2lsbCBiZSBzdG9yZWQg + aW50byB0aGUgcHJvdmlkZWQgZmlsZSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5h + ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNlcGhmcy1maWxlc3lzdGVtLW5hbWUiLAogICAg + ICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBv + ZiB0aGUgQ2VwaCBmaWxlc3lzdGVtIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFk + ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tY2VwaGZzLW1ldGFkYXRhLXBvb2wtbmFtZSIsCiAg + ICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBuYW1l + IG9mIHRoZSBjZXBoZnMgbWV0YWRhdGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9n + cm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNlcGhmcy1kYXRhLXBvb2wtbmFtZSIs + CiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBu + YW1lIG9mIHRoZSBjZXBoZnMgZGF0YSBwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dy + b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmJkLWRhdGEtcG9vbC1uYW1lIiwKICAg + ICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAg + ICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBuYW1lIG9mIHRoZSBSQkQgZGF0YXBvb2wiLAogICAgICAg + ICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1hbGlh + cy1yYmQtZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAg + ICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iUHJvdmlkZXMgYW4gYWxpYXMgZm9y + IHRoZSAgUkJEIGRhdGEgcG9vbCBuYW1lLCBuZWNlc3NhcnkgaWYgYSBzcGVjaWFsIGNoYXJhY3Rl + ciBpcyBwcmVzZW50IGluIHRoZSBwb29sIG5hbWUgc3VjaCBhcyBhIHBlcmlvZCBvciB1bmRlcnNj + b3JlIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg + ICAgICAgIi0tcmd3LWVuZHBvaW50IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAg + ICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IlJBRE9TIEdhdGV3YXkgZW5kcG9p + bnQgKGluIGA8SVB2ND46PFBPUlQ+YCBvciBgPFtJUHY2XT46PFBPUlQ+YCBvciBgPEZRRE4+OjxQ + T1JUPmAgZm9ybWF0KSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1l + bnQoCiAgICAgICAgICAgICItLXJndy10bHMtY2VydC1wYXRoIiwKICAgICAgICAgICAgZGVmYXVs + dD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IlJBRE9T + IEdhdGV3YXkgZW5kcG9pbnQgVExTIGNlcnRpZmljYXRlIiwKICAgICAgICApCiAgICAgICAgb3V0 + cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXNraXAtdGxzIiwKICAg + ICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAg + ICAgICAgIGhlbHA9Iklnbm9yZSBUTFMgY2VydGlmaWNhdGlvbiB2YWxpZGF0aW9uIHdoZW4gYSBz + ZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZSBpcyBwcm92aWRlZCAoTk9UIFJFQ09NTUVOREVEIiwKICAg + ICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0t + bW9uaXRvcmluZy1lbmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAg + IHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJDZXBoIE1hbmFnZXIgcHJvbWV0aGV1 + cyBleHBvcnRlciBlbmRwb2ludHMgKGNvbW1hIHNlcGFyYXRlZCBsaXN0IG9mIChmb3JtYXQgYDxJ + UHY0PmAgb3IgYDxbSVB2Nl0+YCBvciBgPEZRRE4+YCkgZW50cmllcyBvZiBhY3RpdmUgYW5kIHN0 + YW5kYnkgbWdycykiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50 + KAogICAgICAgICAgICAiLS1tb25pdG9yaW5nLWVuZHBvaW50LXBvcnQiLAogICAgICAgICAgICBk + ZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0i + Q2VwaCBNYW5hZ2VyIHByb21ldGhldXMgZXhwb3J0ZXIgcG9ydCIsCiAgICAgICAgKQogICAgICAg + IG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXNraXAtbW9uaXRvcmlu + Zy1lbmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGFjdGlv + bj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGhlbHA9IkRvIG5vdCBjaGVjayBmb3IgYSBtb25p + dG9yaW5nIGVuZHBvaW50IGZvciB0aGUgQ2VwaCBjbHVzdGVyIiwKICAgICAgICApCiAgICAgICAg + b3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmJkLW1ldGFkYXRhLWVj + LXBvb2wtbmFtZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVk + PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiBlcmFzdXJlIGNv + ZGVkIFJCRCBtZXRhZGF0YSBwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFk + ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tZHJ5LXJ1biIsCiAgICAgICAgICAgIGRlZmF1bHQ9 + RmFsc2UsCiAgICAgICAgICAgIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGhlbHA9 + IkRyeSBydW4gcHJpbnRzIHRoZSBleGVjdXRlZCBjb21tYW5kcyB3aXRob3V0IHJ1bm5pbmcgdGhl + bSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAg + ICAgICItLXJhZG9zLW5hbWVzcGFjZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAg + ICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJEaXZpZGVzIGEgcG9vbCBpbnRv + IHNlcGFyYXRlIGxvZ2ljYWwgbmFtZXNwYWNlcywgdXNlZCBmb3IgY3JlYXRpbmcgUkJEIFBWQyBp + biBhIENlcGhCbG9ja1Bvb2xSYWRvc05hbWVzcGFjZSAoc2hvdWxkIGJlIGxvd2VyIGNhc2UpIiwK + ICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAg + Ii0tc3Vidm9sdW1lLWdyb3VwIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAg + cmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9InByb3ZpZGVzIHRoZSBuYW1lIG9mIHRo + ZSBzdWJ2b2x1bWUgZ3JvdXAiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy + Z3VtZW50KAogICAgICAgICAgICAiLS1yZ3ctcmVhbG0tbmFtZSIsCiAgICAgICAgICAgIGRlZmF1 + bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJwcm92 + aWRlcyB0aGUgbmFtZSBvZiB0aGUgcmd3LXJlYWxtIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0 + X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXpvbmUtbmFtZSIsCiAgICAg + ICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAg + ICBoZWxwPSJwcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgcmd3LXpvbmUiLAogICAgICAgICkKICAg + ICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yZ3ctem9uZWdy + b3VwLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1G + YWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlkZXMgdGhlIG5hbWUgb2YgdGhlIHJndy16b25l + Z3JvdXAiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAg + ICAgICAgICAiLS10b3BvbG9neS1wb29scyIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAg + ICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJjb21tYS1zZXBhcmF0ZWQg + bGlzdCBvZiB0b3BvbG9neS1jb25zdHJhaW5lZCByYmQgcG9vbHMiLAogICAgICAgICkKICAgICAg + ICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS10b3BvbG9neS1mYWls + dXJlLWRvbWFpbi1sYWJlbCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJl + cXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJrOHMgY2x1c3RlciBmYWlsdXJlIGRvbWFp + biBsYWJlbCAoZXhhbXBsZTogem9uZSwgcmFjaywgb3IgaG9zdCkgZm9yIHRoZSB0b3BvbG9neS1w + b29scyB0aGF0IG1hdGNoIHRoZSBjZXBoIGRvbWFpbiIsCiAgICAgICAgKQogICAgICAgIG91dHB1 + dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXRvcG9sb2d5LWZhaWx1cmUtZG9t + YWluLXZhbHVlcyIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVk + PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiB0aGUgazhz + IGNsdXN0ZXIgZmFpbHVyZSBkb21haW4gdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gZWFjaCBvZiB0 + aGUgcG9vbHMgaW4gdGhlIGB0b3BvbG9neS1wb29sc2AgbGlzdCIsCiAgICAgICAgKQoKICAgICAg + ICB1cGdyYWRlX2dyb3VwID0gYXJnUC5hZGRfYXJndW1lbnRfZ3JvdXAoInVwZ3JhZGUiKQogICAg + ICAgIHVwZ3JhZGVfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS11cGdyYWRlIiwK + ICAgICAgICAgICAgYWN0aW9uPSJzdG9yZV90cnVlIiwKICAgICAgICAgICAgZGVmYXVsdD1GYWxz + ZSwKICAgICAgICAgICAgaGVscD0iVXBncmFkZXMgdGhlIGNlcGhDU0lLZXlyaW5ncyhGb3IgZXhh + bXBsZTogY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIpIGFuZCBjbGllbnQuaGVhbHRoY2hl + Y2tlciBjZXBoIHVzZXJzIHdpdGggbmV3IHBlcm1pc3Npb25zIG5lZWRlZCBmb3IgdGhlIG5ldyBj + bHVzdGVyIHZlcnNpb24gYW5kIG9sZGVyIHBlcm1pc3Npb24gd2lsbCBzdGlsbCBiZSBhcHBsaWVk + LiIKICAgICAgICAgICAgKyAiU2FtcGxlIHJ1bjogYHB5dGhvbjMgL2V0Yy9jZXBoL2NyZWF0ZS1l + eHRlcm5hbC1jbHVzdGVyLXJlc291cmNlcy5weSAtLXVwZ3JhZGVgLCB0aGlzIHdpbGwgdXBncmFk + ZSBhbGwgdGhlIGRlZmF1bHQgY3NpIHVzZXJzKG5vbi1yZXN0cmljdGVkKSIKICAgICAgICAgICAg + KyAiRm9yIHJlc3RyaWN0ZWQgdXNlcnMoRm9yIGV4YW1wbGU6IGNsaWVudC5jc2ktY2VwaGZzLXBy + b3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMpLCB1c2VycyBjcmVhdGVkIHVzaW5nIC0t + cmVzdHJpY3RlZC1hdXRoLXBlcm1pc3Npb24gZmxhZyBuZWVkIHRvIHBhc3MgbWFuZGF0b3J5IGZs + YWdzIgogICAgICAgICAgICArICJtYW5kYXRvcnkgZmxhZ3M6ICctLXJiZC1kYXRhLXBvb2wtbmFt + ZSwgLS1rOHMtY2x1c3Rlci1uYW1lIGFuZCAtLXJ1bi1hcy11c2VyJyBmbGFncyB3aGlsZSB1cGdy + YWRpbmciCiAgICAgICAgICAgICsgImluIGNhc2Ugb2YgY2VwaGZzIHVzZXJzIGlmIHlvdSBoYXZl + IHBhc3NlZCAtLWNlcGhmcy1maWxlc3lzdGVtLW5hbWUgZmxhZyB3aGlsZSBjcmVhdGluZyB1c2Vy + IHRoZW4gd2hpbGUgdXBncmFkaW5nIGl0IHdpbGwgYmUgbWFuZGF0b3J5IHRvbyIKICAgICAgICAg + ICAgKyAiU2FtcGxlIHJ1bjogYHB5dGhvbjMgL2V0Yy9jZXBoL2NyZWF0ZS1leHRlcm5hbC1jbHVz + dGVyLXJlc291cmNlcy5weSAtLXVwZ3JhZGUgLS1yYmQtZGF0YS1wb29sLW5hbWUgcmVwbGljYXBv + b2wgLS1rOHMtY2x1c3Rlci1uYW1lIHJvb2tzdG9yYWdlICAtLXJ1bi1hcy11c2VyIGNsaWVudC5j + c2ktcmJkLW5vZGUtcm9va3N0b3JhZ2UtcmVwbGljYXBvb2xgIgogICAgICAgICAgICArICJQUzog + QW4gZXhpc3Rpbmcgbm9uLXJlc3RyaWN0ZWQgdXNlciBjYW5ub3QgYmUgY29udmVydGVkIHRvIGEg + cmVzdHJpY3RlZCB1c2VyIGJ5IHVwZ3JhZGluZy4iCiAgICAgICAgICAgICsgIlVwZ3JhZGUgZmxh + ZyBzaG91bGQgb25seSBiZSB1c2VkIHRvIGFwcGVuZCBuZXcgcGVybWlzc2lvbnMgdG8gdXNlcnMs + IGl0IHNob3VsZG4ndCBiZSB1c2VkIGZvciBjaGFuZ2luZyB1c2VyIGFscmVhZHkgYXBwbGllZCBw + ZXJtaXNzaW9uLCBmb3IgZXhhbXBsZSB5b3Ugc2hvdWxkbid0IGNoYW5nZSBpbiB3aGljaCBwb29s + IHVzZXIgaGFzIGFjY2VzcyIsCiAgICAgICAgKQoKICAgICAgICAjIEFkZCBjb21tYW5kLWxpbmUg + YXJndW1lbnRzCiAgICAgICAgY29uZmlnX2dyb3VwID0gYXJnUC5hZGRfYXJndW1lbnRfZ3JvdXAo + ImNvbmZpZyIpCiAgICAgICAgY29uZmlnX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAg + Ii0tY29uZmlnLWZpbGUiLAogICAgICAgICAgICB0eXBlPXN0ciwKICAgICAgICAgICAgaGVscD0i + UGF0aCB0byB0aGUgY29uZmlndXJhdGlvbiBmaWxlLCBQcmlvcml0eTogY29tbWFuZC1saW5lLWFy + Z3MgPiBjb25maWcuaW5pIGZpbGUgdmFsdWVzID4gZGVmYXVsdCB2YWx1ZXMiLAogICAgICAgICAg + ICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICApCgogICAg + ICAgIGlmIGFyZ3NfdG9fcGFyc2U6CiAgICAgICAgICAgIGFzc2VydCAoCiAgICAgICAgICAgICAg + ICB0eXBlKGFyZ3NfdG9fcGFyc2UpID09IGxpc3QKICAgICAgICAgICAgKSwgIkFyZ3VtZW50IHRv + ICdnZW5fYXJnX3BhcnNlcicgc2hvdWxkIGJlIGEgbGlzdCIKICAgICAgICBlbHNlOgogICAgICAg + ICAgICBhcmdzX3RvX3BhcnNlID0gc3lzLmFyZ3ZbMTpdCiAgICAgICAgcmV0dXJuIGFyZ1AucGFy + c2VfYXJncyhhcmdzX3RvX3BhcnNlKQoKICAgIGRlZiB2YWxpZGF0ZV9yYmRfbWV0YWRhdGFfZWNf + cG9vbF9uYW1lKHNlbGYpOgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmJkX21ldGFkYXRh + X2VjX3Bvb2xfbmFtZToKICAgICAgICAgICAgcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZSA9IHNl + bGYuX2FyZ19wYXJzZXIucmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQogICAgICAgICAgICByYmRf + cG9vbF9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5yYmRfZGF0YV9wb29sX25hbWUKCiAgICAgICAg + ICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRp + b25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJGbGFnICctLXJiZC1kYXRh + LXBvb2wtbmFtZScgc2hvdWxkIG5vdCBiZSBlbXB0eSIKICAgICAgICAgICAgICAgICkKCiAgICAg + ICAgICAgIGlmIHJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAg + ICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJG + bGFnICctLXJiZC1tZXRhZGF0YS1lYy1wb29sLW5hbWUnIHNob3VsZCBub3QgYmUgZW1wdHkiCiAg + ICAgICAgICAgICAgICApCgogICAgICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogIm9zZCBk + dW1wIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVy + cl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICBp + ZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFp + c2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBmIntjbWRf + anNvblsncHJlZml4J119IGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAgICAgICAgIGYi + RXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJ + U1R9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBtZXRhZGF0YV9wb29sX2V4aXN0LCBw + b29sX2V4aXN0ID0gRmFsc2UsIEZhbHNlCgogICAgICAgICAgICBmb3Iga2V5IGluIGpzb25fb3V0 + WyJwb29scyJdOgogICAgICAgICAgICAgICAgIyBpZiBlcmFzdXJlX2NvZGVfcHJvZmlsZSBpcyBl + bXB0eSBhbmQgcG9vbCBuYW1lIGV4aXN0cyB0aGVuIGl0IHJlcGxpY2EgcG9vbAogICAgICAgICAg + ICAgICAgaWYgKAogICAgICAgICAgICAgICAgICAgIGtleVsiZXJhc3VyZV9jb2RlX3Byb2ZpbGUi + XSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBrZXlbInBvb2xfbmFtZSJdID09IHJiZF9t + ZXRhZGF0YV9lY19wb29sX25hbWUKICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICAg + ICAgbWV0YWRhdGFfcG9vbF9leGlzdCA9IFRydWUKICAgICAgICAgICAgICAgICMgaWYgZXJhc3Vy + ZV9jb2RlX3Byb2ZpbGUgaXMgbm90IGVtcHR5IGFuZCBwb29sIG5hbWUgZXhpc3RzIHRoZW4gaXQg + aXMgZWMgcG9vbAogICAgICAgICAgICAgICAgaWYga2V5WyJlcmFzdXJlX2NvZGVfcHJvZmlsZSJd + IGFuZCBrZXlbInBvb2xfbmFtZSJdID09IHJiZF9wb29sX25hbWU6CiAgICAgICAgICAgICAgICAg + ICAgcG9vbF9leGlzdCA9IFRydWUKCiAgICAgICAgICAgIGlmIG5vdCBtZXRhZGF0YV9wb29sX2V4 + aXN0OgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAg + ICAgICAgICAgICAgICAgICAiUHJvdmlkZWQgcmJkX2VjX21ldGFkYXRhX3Bvb2wgbmFtZSwiCiAg + ICAgICAgICAgICAgICAgICAgZiIge3JiZF9tZXRhZGF0YV9lY19wb29sX25hbWV9LCBkb2VzIG5v + dCBleGlzdCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgbm90IHBvb2xfZXhpc3Q6 + CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg + ICAgICAgICAgICAgIGYiUHJvdmlkZWQgcmJkX2RhdGFfcG9vbCBuYW1lLCB7cmJkX3Bvb2xfbmFt + ZX0sIGRvZXMgbm90IGV4aXN0IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICByZXR1cm4g + cmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQoKICAgIGRlZiBkcnlfcnVuKHNlbGYsIG1zZyk6CiAg + ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICBwcmludCgiRXhl + Y3V0ZTogIiArICInIiArIG1zZyArICInIikKCiAgICBkZWYgdmFsaWRhdGVfcmd3X2VuZHBvaW50 + X3Rsc19jZXJ0KHNlbGYpOgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Rsc19jZXJ0 + X3BhdGg6CiAgICAgICAgICAgIHdpdGggb3BlbihzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2Vy + dF9wYXRoLCBlbmNvZGluZz0idXRmOCIpIGFzIGY6CiAgICAgICAgICAgICAgICBjb250ZW50cyA9 + IGYucmVhZCgpCiAgICAgICAgICAgICAgICByZXR1cm4gY29udGVudHMucnN0cmlwKCkKCiAgICBk + ZWYgX2NoZWNrX2NvbmZsaWN0aW5nX29wdGlvbnMoc2VsZik6CiAgICAgICAgaWYgbm90IHNlbGYu + X2FyZ19wYXJzZXIudXBncmFkZSBhbmQgbm90IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9v + bF9uYW1lOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAg + ICAgICAgICAgICAgIkVpdGhlciAnLS11cGdyYWRlJyBvciAnLS1yYmQtZGF0YS1wb29sLW5hbWUg + PHBvb2xfbmFtZT4nIHNob3VsZCBiZSBzcGVjaWZpZWQiCiAgICAgICAgICAgICkKCiAgICBkZWYg + X2ludmFsaWRfZW5kcG9pbnQoc2VsZiwgZW5kcG9pbnRfc3RyKToKICAgICAgICAjIGV4dHJhY3Qg + dGhlIHBvcnQgYnkgZ2V0dGluZyB0aGUgbGFzdCBzcGxpdCBvbiBgOmAgZGVsaW1pdGVyCiAgICAg + ICAgdHJ5OgogICAgICAgICAgICBlbmRwb2ludF9zdHJfaXAsIHBvcnQgPSBlbmRwb2ludF9zdHIu + cnNwbGl0KCI6IiwgMSkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgcmFp + c2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbihmIk5vdCBhIHByb3BlciBlbmRwb2ludDoge2Vu + ZHBvaW50X3N0cn0iKQoKICAgICAgICB0cnk6CiAgICAgICAgICAgIGlmIGVuZHBvaW50X3N0cl9p + cFswXSA9PSAiWyI6CiAgICAgICAgICAgICAgICBlbmRwb2ludF9zdHJfaXAgPSBlbmRwb2ludF9z + dHJfaXBbMSA6IGxlbihlbmRwb2ludF9zdHJfaXApIC0gMV0KICAgICAgICAgICAgaXBfdHlwZSA9 + ICgKICAgICAgICAgICAgICAgICJJUHY0IiBpZiB0eXBlKGlwX2FkZHJlc3MoZW5kcG9pbnRfc3Ry + X2lwKSkgaXMgSVB2NEFkZHJlc3MgZWxzZSAiSVB2NiIKICAgICAgICAgICAgKQogICAgICAgIGV4 + Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICBpcF90eXBlID0gIkZRRE4iCiAgICAgICAgaWYg + bm90IHBvcnQuaXNkaWdpdCgpOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj + ZXB0aW9uKGYiUG9ydCBub3QgdmFsaWQ6IHtwb3J0fSIpCiAgICAgICAgaW50UG9ydCA9IGludChw + b3J0KQogICAgICAgIGlmIGludFBvcnQgPCAxIG9yIGludFBvcnQgPiAyKioxNiAtIDE6CiAgICAg + ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oZiJPdXQgb2YgcmFuZ2UgcG9y + dCBudW1iZXI6IHtwb3J0fSIpCgogICAgICAgIHJldHVybiBpcF90eXBlCgogICAgZGVmIGVuZHBv + aW50X2RpYWwoc2VsZiwgZW5kcG9pbnRfc3RyLCBpcF90eXBlLCB0aW1lb3V0PTMsIGNlcnQ9Tm9u + ZSk6CiAgICAgICAgIyBpZiB0aGUgJ2NsdXN0ZXInIGluc3RhbmNlIGlzIGEgZHVtbXkgb25lLAog + ICAgICAgICMgZG9uJ3QgdHJ5IHRvIHJlYWNoIG91dCB0byB0aGUgZW5kcG9pbnQKICAgICAgICBp + ZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlSYWRvcyk6CiAgICAgICAgICAgIHJldHVy + biAiIiwgIiIsICIiCiAgICAgICAgaWYgaXBfdHlwZSA9PSAiSVB2NiI6CiAgICAgICAgICAgIHRy + eToKICAgICAgICAgICAgICAgIGVuZHBvaW50X3N0cl9pcCwgZW5kcG9pbnRfc3RyX3BvcnQgPSBl + bmRwb2ludF9zdHIucnNwbGl0KCI6IiwgMSkKICAgICAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6 + CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg + ICAgICAgICAgICAgIGYiTm90IGEgcHJvcGVyIGVuZHBvaW50OiB7ZW5kcG9pbnRfc3RyfSIKICAg + ICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgZW5kcG9pbnRfc3RyX2lwWzBdICE9ICJbIjoK + ICAgICAgICAgICAgICAgIGVuZHBvaW50X3N0cl9pcCA9ICJbIiArIGVuZHBvaW50X3N0cl9pcCAr + ICJdIgogICAgICAgICAgICBlbmRwb2ludF9zdHIgPSAiOiIuam9pbihbZW5kcG9pbnRfc3RyX2lw + LCBlbmRwb2ludF9zdHJfcG9ydF0pCgogICAgICAgIHByb3RvY29scyA9IFsiaHR0cCIsICJodHRw + cyJdCiAgICAgICAgcmVzcG9uc2VfZXJyb3IgPSBOb25lCiAgICAgICAgZm9yIHByZWZpeCBpbiBw + cm90b2NvbHM6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGVwID0gZiJ7cHJlZml4 + fTovL3tlbmRwb2ludF9zdHJ9IgogICAgICAgICAgICAgICAgdmVyaWZ5ID0gTm9uZQogICAgICAg + ICAgICAgICAgIyBJZiB2ZXJpZnkgaXMgc2V0IHRvIGEgcGF0aCB0byBhIGRpcmVjdG9yeSwKICAg + ICAgICAgICAgICAgICMgdGhlIGRpcmVjdG9yeSBtdXN0IGhhdmUgYmVlbiBwcm9jZXNzZWQgdXNp + bmcgdGhlIGNfcmVoYXNoIHV0aWxpdHkgc3VwcGxpZWQgd2l0aCBPcGVuU1NMLgogICAgICAgICAg + ICAgICAgaWYgcHJlZml4ID09ICJodHRwcyIgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3NraXBf + dGxzOgogICAgICAgICAgICAgICAgICAgIHZlcmlmeSA9IEZhbHNlCiAgICAgICAgICAgICAgICAg + ICAgciA9IHJlcXVlc3RzLmhlYWQoZXAsIHRpbWVvdXQ9dGltZW91dCwgdmVyaWZ5PUZhbHNlKQog + ICAgICAgICAgICAgICAgZWxpZiBwcmVmaXggPT0gImh0dHBzIiBhbmQgY2VydDoKICAgICAgICAg + ICAgICAgICAgICB2ZXJpZnkgPSBjZXJ0CiAgICAgICAgICAgICAgICAgICAgciA9IHJlcXVlc3Rz + LmhlYWQoZXAsIHRpbWVvdXQ9dGltZW91dCwgdmVyaWZ5PWNlcnQpCiAgICAgICAgICAgICAgICBl + bHNlOgogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0cy5oZWFkKGVwLCB0aW1lb3V0PXRp + bWVvdXQpCiAgICAgICAgICAgICAgICBpZiByLnN0YXR1c19jb2RlID09IDIwMDoKICAgICAgICAg + ICAgICAgICAgICByZXR1cm4gcHJlZml4LCB2ZXJpZnksICIiCiAgICAgICAgICAgIGV4Y2VwdCBF + eGNlcHRpb24gYXMgZXJyOgogICAgICAgICAgICAgICAgcmVzcG9uc2VfZXJyb3IgPSBlcnIKICAg + ICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgc3lzLnN0ZGVyci53cml0ZSgKICAgICAgICAg + ICAgZiJ1bmFibGUgdG8gY29ubmVjdCB0byBlbmRwb2ludDoge2VuZHBvaW50X3N0cn0sIGZhaWxl + ZCBlcnJvcjoge3Jlc3BvbnNlX2Vycm9yfSIKICAgICAgICApCiAgICAgICAgcmV0dXJuICgKICAg + ICAgICAgICAgIiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAoIi0xIiksCiAgICAgICAg + KQoKICAgIGRlZiBwYXJzZV9jb25maWdfZmlsZShzZWxmLCBjb25maWdfZmlsZSk6CiAgICAgICAg + Y29uZmlnID0gY29uZmlncGFyc2VyLkNvbmZpZ1BhcnNlcigpCiAgICAgICAgY29uZmlnLnJlYWQo + Y29uZmlnX2ZpbGUpCiAgICAgICAgZm9yIGFyZyBpbiBsaXN0KHZhcnMoc2VsZi5fYXJnX3BhcnNl + cikpOgogICAgICAgICAgICAjIHB5dGhvbiB0cmVhdHMgZmxhZy1uYW1lIGFzIGZsYWdfbmFtZSBp + bnRlcm5hbGx5LCBzbyBjb252ZXJ0aW5nIGJhY2sgdG8gZmxhZy1uYW1lLAogICAgICAgICAgICAj + IHNvIHdlIGNhbiBnZXQgdGhvc2UgdmFsdWVzIGZyb20gY29uZmlnIGZpbGUKICAgICAgICAgICAg + YXJndW1lbnQgPSBhcmcucmVwbGFjZSgiXyIsICItIikKICAgICAgICAgICAgYXJndW1lbnRWYWx1 + ZSA9IHN0cihnZXRhdHRyKHNlbGYuX2FyZ19wYXJzZXIsIGFyZykpCiAgICAgICAgICAgIGNvbmZp + Z192YWx1ZSA9IGNvbmZpZy5nZXQoIkNvbmZpZ3VyYXRpb25zIiwgYXJndW1lbnQsIGZhbGxiYWNr + PU5vbmUpCiAgICAgICAgICAgICMgZ2l2ZSBwcmlvcml0eSB0byBjb21tYW5kIGxpbmUgYXJndW1l + bnQsIGlmIGNvbW1hbmQgbGluZSBhcmd1bWVudCBpcyBub3QgcHJlc2VudCB1c2UgY29uZmlnLmlu + aSB2YWx1ZSwKICAgICAgICAgICAgaWYgKHN0cihzeXMuYXJndikuZmluZChhcmd1bWVudCkgPT0g + LTEpIGFuZCAoCiAgICAgICAgICAgICAgICAoY29uZmlnX3ZhbHVlICE9IE5vbmUpIGFuZCAoY29u + ZmlnX3ZhbHVlICE9ICIiKQogICAgICAgICAgICApOgogICAgICAgICAgICAgICAgc2VsZi5fYXJn + X3BhcnNlci5fX3NldGF0dHJfXyhhcmcsIGNvbmZpZ192YWx1ZSkKCiAgICAgICAgcmV0dXJuIGNv + bmZpZwoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhcmdfbGlzdD1Ob25lKToKICAgICAgICBzZWxm + Lm91dF9tYXAgPSB7fQogICAgICAgIHNlbGYuX2V4Y2x1ZGVkX2tleXMgPSBzZXQoKQogICAgICAg + IHNlbGYuX2FyZ19wYXJzZXIgPSBzZWxmLmdlbl9hcmdfcGFyc2VyKGFyZ3NfdG9fcGFyc2U9YXJn + X2xpc3QpCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jb25maWdfZmlsZToKICAgICAgICAg + ICAgc2VsZi5jb25maWcgPSBzZWxmLnBhcnNlX2NvbmZpZ19maWxlKHNlbGYuX2FyZ19wYXJzZXIu + Y29uZmlnX2ZpbGUpCiAgICAgICAgc2VsZi5fY2hlY2tfY29uZmxpY3Rpbmdfb3B0aW9ucygpCiAg + ICAgICAgc2VsZi5ydW5fYXNfdXNlciA9IHNlbGYuX2FyZ19wYXJzZXIucnVuX2FzX3VzZXIKICAg + ICAgICBzZWxmLm91dHB1dF9maWxlID0gc2VsZi5fYXJnX3BhcnNlci5vdXRwdXQKICAgICAgICBz + ZWxmLmNlcGhfY29uZiA9IHNlbGYuX2FyZ19wYXJzZXIuY2VwaF9jb25mCiAgICAgICAgc2VsZi5j + ZXBoX2tleXJpbmcgPSBzZWxmLl9hcmdfcGFyc2VyLmtleXJpbmcKICAgICAgICAjIGlmIHVzZXIg + bm90IHByb3ZpZGVkLCBnaXZlIGEgZGVmYXVsdCB1c2VyCiAgICAgICAgaWYgbm90IHNlbGYucnVu + X2FzX3VzZXIgYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVwZ3JhZGU6CiAgICAgICAgICAgIHNl + bGYucnVuX2FzX3VzZXIgPSBzZWxmLkVYVEVSTkFMX1VTRVJfTkFNRQogICAgICAgIGlmIG5vdCBz + ZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeCBhbmQgbm90IHNlbGYuX2FyZ19wYXJzZXIu + dXBncmFkZToKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXggPSBz + ZWxmLkRFRkFVTFRfUkdXX1BPT0xfUFJFRklYCiAgICAgICAgaWYgc2VsZi5jZXBoX2NvbmY6CiAg + ICAgICAgICAgIGt3YXJncyA9IHt9CiAgICAgICAgICAgIGlmIHNlbGYuY2VwaF9rZXlyaW5nOgog + ICAgICAgICAgICAgICAga3dhcmdzWyJjb25mIl0gPSB7ImtleXJpbmciOiBzZWxmLmNlcGhfa2V5 + cmluZ30KICAgICAgICAgICAgc2VsZi5jbHVzdGVyID0gcmFkb3MuUmFkb3MoY29uZmZpbGU9c2Vs + Zi5jZXBoX2NvbmYsICoqa3dhcmdzKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYuY2x1 + c3RlciA9IHJhZG9zLlJhZG9zKCkKICAgICAgICAgICAgc2VsZi5jbHVzdGVyLmNvbmZfcmVhZF9m + aWxlKCkKICAgICAgICBzZWxmLmNsdXN0ZXIuY29ubmVjdCgpCgogICAgZGVmIHNodXRkb3duKHNl + bGYpOgogICAgICAgIGlmIHNlbGYuY2x1c3Rlci5zdGF0ZSA9PSAiY29ubmVjdGVkIjoKICAgICAg + ICAgICAgc2VsZi5jbHVzdGVyLnNodXRkb3duKCkKCiAgICBkZWYgZ2V0X2ZzaWQoc2VsZik6CiAg + ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2Vs + Zi5kcnlfcnVuKCJjZXBoIGZzaWQiKQogICAgICAgIHJldHVybiBzdHIoc2VsZi5jbHVzdGVyLmdl + dF9mc2lkKCkpCgogICAgZGVmIF9jb21tb25fY21kX2pzb25fZ2VuKHNlbGYsIGNtZF9qc29uKToK + ICAgICAgICBjbWQgPSBqc29uLmR1bXBzKGNtZF9qc29uLCBzb3J0X2tleXM9VHJ1ZSkKICAgICAg + ICByZXRfdmFsLCBjbWRfb3V0LCBlcnJfbXNnID0gc2VsZi5jbHVzdGVyLm1vbl9jb21tYW5kKGNt + ZCwgYiIiKQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudmVyYm9zZToKICAgICAgICAgICAg + cHJpbnQoZiJDb21tYW5kIElucHV0OiB7Y21kfSIpCiAgICAgICAgICAgIHByaW50KAogICAgICAg + ICAgICAgICAgZiJSZXR1cm4gVmFsOiB7cmV0X3ZhbH1cbkNvbW1hbmQgT3V0cHV0OiB7Y21kX291 + dH1cbiIKICAgICAgICAgICAgICAgIGYiRXJyb3IgTWVzc2FnZToge2Vycl9tc2d9XG4tLS0tLS0t + LS0tXG4iCiAgICAgICAgICAgICkKICAgICAgICBqc29uX291dCA9IHt9CiAgICAgICAgIyBpZiB0 + aGVyZSBpcyBubyBlcnJvciAoaS5lOyByZXRfdmFsIGlzIFpFUk8pIGFuZCAnY21kX291dCcgaXMg + bm90IGVtcHR5CiAgICAgICAgIyB0aGVuIGNvbnZlcnQgJ2NtZF9vdXQnIHRvIGEganNvbiBvdXRw + dXQKICAgICAgICBpZiByZXRfdmFsID09IDAgYW5kIGNtZF9vdXQ6CiAgICAgICAgICAgIGpzb25f + b3V0ID0ganNvbi5sb2FkcyhjbWRfb3V0KQogICAgICAgIHJldHVybiByZXRfdmFsLCBqc29uX291 + dCwgZXJyX21zZwoKICAgIGRlZiBnZXRfY2VwaF9leHRlcm5hbF9tb25fZGF0YShzZWxmKToKICAg + ICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogInF1b3J1bV9zdGF0dXMiLCAiZm9ybWF0IjogImpz + b24ifQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0 + dXJuIHNlbGYuZHJ5X3J1bigiY2VwaCAiICsgY21kX2pzb25bInByZWZpeCJdKQogICAgICAgIHJl + dF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRf + anNvbikKICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAg + ICAgIGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJh + aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiJ3F1b3J1bV9z + dGF0dXMnIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9t + c2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAg + ICAgICkKICAgICAgICBxX2xlYWRlcl9uYW1lID0ganNvbl9vdXRbInF1b3J1bV9sZWFkZXJfbmFt + ZSJdCiAgICAgICAgcV9sZWFkZXJfZGV0YWlscyA9IHt9CiAgICAgICAgcV9sZWFkZXJfbWF0Y2hp + bmdfbGlzdCA9IFsKICAgICAgICAgICAgbCBmb3IgbCBpbiBqc29uX291dFsibW9ubWFwIl1bIm1v + bnMiXSBpZiBsWyJuYW1lIl0gPT0gcV9sZWFkZXJfbmFtZQogICAgICAgIF0KICAgICAgICBpZiBs + ZW4ocV9sZWFkZXJfbWF0Y2hpbmdfbGlzdCkgPT0gMDoKICAgICAgICAgICAgcmFpc2UgRXhlY3V0 + aW9uRmFpbHVyZUV4Y2VwdGlvbigiTm8gbWF0Y2hpbmcgJ21vbicgZGV0YWlscyBmb3VuZCIpCiAg + ICAgICAgcV9sZWFkZXJfZGV0YWlscyA9IHFfbGVhZGVyX21hdGNoaW5nX2xpc3RbMF0KICAgICAg + ICAjIGdldCB0aGUgYWRkcmVzcyB2ZWN0b3Igb2YgdGhlIHF1b3J1bS1sZWFkZXIKICAgICAgICBx + X2xlYWRlcl9hZGRydmVjID0gcV9sZWFkZXJfZGV0YWlscy5nZXQoInB1YmxpY19hZGRycyIsIHt9 + KS5nZXQoImFkZHJ2ZWMiLCBbXSkKICAgICAgICBpcF9hZGRyID0gc3RyKHFfbGVhZGVyX2RldGFp + bHNbInB1YmxpY19hZGRyIl0uc3BsaXQoIi8iKVswXSkKCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh + cnNlci52Ml9wb3J0X2VuYWJsZToKICAgICAgICAgICAgaWYgcV9sZWFkZXJfYWRkcnZlY1swXVsi + dHlwZSJdID09ICJ2MiI6CiAgICAgICAgICAgICAgICBpcF9hZGRyID0gcV9sZWFkZXJfYWRkcnZl + Y1swXVsiYWRkciJdCiAgICAgICAgICAgIGVsaWYgbGVuKHFfbGVhZGVyX2FkZHJ2ZWMpID4gMSBh + bmQgcV9sZWFkZXJfYWRkcnZlY1sxXVsidHlwZSJdID09ICJ2MiI6CiAgICAgICAgICAgICAgICBp + cF9hZGRyID0gcV9sZWFkZXJfYWRkcnZlY1sxXVsiYWRkciJdCiAgICAgICAgICAgIGVsc2U6CiAg + ICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKAogICAgICAgICAgICAgICAgICAgICIndjIn + IGFkZHJlc3MgdHlwZSBub3QgcHJlc2VudCwgYW5kICd2Mi1wb3J0LWVuYWJsZScgZmxhZyBpcyBw + cm92aWRlZCIKICAgICAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIGYie3N0cihxX2xlYWRl + cl9uYW1lKX09e2lwX2FkZHJ9IgoKICAgIGRlZiBfY29udmVydF9ob3N0bmFtZV90b19pcChzZWxm + LCBob3N0X25hbWUsIHBvcnQsIGlwX3R5cGUpOgogICAgICAgICMgaWYgJ2NsdXN0ZXInIGluc3Rh + bmNlIGlzIGEgZHVtbXkgdHlwZSwKICAgICAgICAjIGNhbGwgdGhlIGR1bW15IGluc3RhbmNlJ3Mg + ImNvbnZlcnQiIG1ldGhvZAogICAgICAgIGlmIG5vdCBob3N0X25hbWU6CiAgICAgICAgICAgIHJh + aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oIkVtcHR5IGhvc3RuYW1lIHByb3ZpZGVkIikK + ICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlSYWRvcyk6CiAgICAgICAg + ICAgIHJldHVybiBzZWxmLmNsdXN0ZXIuX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoaG9zdF9uYW1l + KQoKICAgICAgICBpZiBpcF90eXBlID09ICJGUUROIjoKICAgICAgICAgICAgIyBjaGVjayB3aGlj + aCBpcCBGUUROIHNob3VsZCBiZSBjb252ZXJ0ZWQgdG8sIElQdjQgb3IgSVB2NgogICAgICAgICAg + ICAjIGNoZWNrIHRoZSBob3N0IGlwLCB0aGUgZW5kcG9pbnQgaXAgdHlwZSB3b3VsZCBiZSBzaW1p + bGFyIHRvIGhvc3QgaXAKICAgICAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJvcmNoIGhv + c3QgbHMiLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgICAgICByZXRfdmFsLCBqc29uX291dCwg + ZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgICAg + ICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0dGVtcHQsCiAgICAgICAgICAgIGlmIHJl + dF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgICAgICByYWlzZSBF + eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICInb3JjaCBob3N0 + IGxzJyBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgICAgICBmIkVycm9yOiB7ZXJy + X21zZyBpZiByZXRfdmFsICE9IDAgZWxzZSBzZWxmLkVNUFRZX09VVFBVVF9MSVNUfSIKICAgICAg + ICAgICAgICAgICkKICAgICAgICAgICAgaG9zdF9hZGRyID0ganNvbl9vdXRbMF1bImFkZHIiXQog + ICAgICAgICAgICAjIGFkZCA6ODAgc2FtcGxlIHBvcnQgaW4gaXBfdHlwZSwgYXMgX2ludmFsaWRf + ZW5kcG9pbnQgYWxzbyB2ZXJpZnkgcG9ydAogICAgICAgICAgICBob3N0X2lwX3R5cGUgPSBzZWxm + Ll9pbnZhbGlkX2VuZHBvaW50KGhvc3RfYWRkciArICI6ODAiKQogICAgICAgICAgICBpbXBvcnQg + c29ja2V0CgogICAgICAgICAgICBpcCA9IFtdCiAgICAgICAgICAgICMgZXhhbXBsZSBvdXRwdXQg + Wyg8QWRkcmVzc0ZhbWlseS5BRl9JTkVUOiAyPiwgPFNvY2tldEtpbmQuU09DS19TVFJFQU06IDE+ + LCA2LCAnJywgKCc5My4xODQuMjE2LjM0JywgODApKSwgLi4uXQogICAgICAgICAgICAjIHdlIG5l + ZWQgdG8gZ2V0IDkzLjE4NC4yMTYuMzQgc28gaXQgd291bGQgYmUgaXBbMF1bNF1bMF0KICAgICAg + ICAgICAgaWYgaG9zdF9pcF90eXBlID09ICJJUHY2IjoKICAgICAgICAgICAgICAgIGlwID0gc29j + a2V0LmdldGFkZHJpbmZvKAogICAgICAgICAgICAgICAgICAgIGhvc3RfbmFtZSwgcG9ydCwgZmFt + aWx5PXNvY2tldC5BRl9JTkVUNiwgcHJvdG89c29ja2V0LklQUFJPVE9fVENQCiAgICAgICAgICAg + ICAgICApCiAgICAgICAgICAgIGVsaWYgaG9zdF9pcF90eXBlID09ICJJUHY0IjoKICAgICAgICAg + ICAgICAgIGlwID0gc29ja2V0LmdldGFkZHJpbmZvKAogICAgICAgICAgICAgICAgICAgIGhvc3Rf + bmFtZSwgcG9ydCwgZmFtaWx5PXNvY2tldC5BRl9JTkVULCBwcm90bz1zb2NrZXQuSVBQUk9UT19U + Q1AKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgZGVsIHNvY2tldAogICAgICAgICAgICBy + ZXR1cm4gaXBbMF1bNF1bMF0KICAgICAgICByZXR1cm4gaG9zdF9uYW1lCgogICAgZGVmIGdldF9h + Y3RpdmVfYW5kX3N0YW5kYnlfbWdycyhzZWxmKToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2Vy + LmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiAiIiwgc2VsZi5kcnlfcnVuKCJjZXBoIHN0YXR1 + cyIpCiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0ID0gc2VsZi5fYXJnX3BhcnNlci5t + b25pdG9yaW5nX2VuZHBvaW50X3BvcnQKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xp + c3QgPSBzZWxmLl9hcmdfcGFyc2VyLm1vbml0b3JpbmdfZW5kcG9pbnQKICAgICAgICBzdGFuZGJ5 + X21ncnMgPSBbXQogICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3Q6CiAg + ICAgICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAic3RhdHVzIiwgImZvcm1hdCI6ICJqc29u + In0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25f + Y21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3Vj + Y2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgICAgICBpZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25f + b3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv + bigKICAgICAgICAgICAgICAgICAgICAiJ21nciBzZXJ2aWNlcycgY29tbWFuZCBmYWlsZWQuXG4i + CiAgICAgICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVs + c2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAg + IG1vbml0b3JpbmdfZW5kcG9pbnQgPSAoCiAgICAgICAgICAgICAgICBqc29uX291dC5nZXQoIm1n + cm1hcCIsIHt9KS5nZXQoInNlcnZpY2VzIiwge30pLmdldCgicHJvbWV0aGV1cyIsICIiKQogICAg + ICAgICAgICApCiAgICAgICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2VuZHBvaW50OgogICAgICAg + ICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAg + ICAgICAiY2FuJ3QgZmluZCBtb25pdG9yaW5nX2VuZHBvaW50LCBwcm9tZXRoZXVzIG1vZHVsZSBt + aWdodCBub3QgYmUgZW5hYmxlZCwgIgogICAgICAgICAgICAgICAgICAgICJlbmFibGUgdGhlIG1v + ZHVsZSBieSBydW5uaW5nICdjZXBoIG1nciBtb2R1bGUgZW5hYmxlIHByb21ldGhldXMnIgogICAg + ICAgICAgICAgICAgKQogICAgICAgICAgICAjIG5vdyBjaGVjayB0aGUgc3RhbmQtYnkgbWdyLXMK + ICAgICAgICAgICAgc3RhbmRieV9hcnIgPSBqc29uX291dC5nZXQoIm1ncm1hcCIsIHt9KS5nZXQo + InN0YW5kYnlzIiwgW10pCiAgICAgICAgICAgIGZvciBlYWNoX3N0YW5kYnkgaW4gc3RhbmRieV9h + cnI6CiAgICAgICAgICAgICAgICBpZiAibmFtZSIgaW4gZWFjaF9zdGFuZGJ5LmtleXMoKToKICAg + ICAgICAgICAgICAgICAgICBzdGFuZGJ5X21ncnMuYXBwZW5kKGVhY2hfc3RhbmRieVsibmFtZSJd + KQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBwYXJzZWRfZW5kcG9pbnQgPSB1cmxw + YXJzZShtb25pdG9yaW5nX2VuZHBvaW50KQogICAgICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoK + ICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAg + ICAgICAgICAgICAgZiJpbnZhbGlkIGVuZHBvaW50OiB7bW9uaXRvcmluZ19lbmRwb2ludH0iCiAg + ICAgICAgICAgICAgICApCiAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdCA9 + IHBhcnNlZF9lbmRwb2ludC5ob3N0bmFtZQogICAgICAgICAgICBpZiBub3QgbW9uaXRvcmluZ19l + bmRwb2ludF9wb3J0OgogICAgICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0ID0g + c3RyKHBhcnNlZF9lbmRwb2ludC5wb3J0KQoKICAgICAgICAjIGlmIG1vbml0b3JpbmcgZW5kcG9p + bnQgcG9ydCBpcyBub3Qgc2V0LCBwdXQgYSBkZWZhdWx0IG1vbiBwb3J0CiAgICAgICAgaWYgbm90 + IG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydDoKICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2lu + dF9wb3J0ID0gc2VsZi5ERUZBVUxUX01PTklUT1JJTkdfRU5EUE9JTlRfUE9SVAoKICAgICAgICAj + IHVzZXIgY291bGQgZ2l2ZSBjb21tYSBhbmQgc3BhY2Ugc2VwYXJhdGVkIGlucHV0cyAobGlrZSAt + LW1vbml0b3JpbmctZW5kcG9pbnQ9IjxpcDE+LCA8aXAyPiIpCiAgICAgICAgbW9uaXRvcmluZ19l + bmRwb2ludF9pcF9saXN0ID0gbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0LnJlcGxhY2UoIiwi + LCAiICIpCiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0X3NwbGl0ID0gbW9uaXRv + cmluZ19lbmRwb2ludF9pcF9saXN0LnNwbGl0KCkKICAgICAgICAjIGlmIG1vbml0b3JpbmctZW5k + cG9pbnQgY291bGQgbm90IGJlIGZvdW5kLCByYWlzZSBhbiBlcnJvcgogICAgICAgIGlmIGxlbiht + b25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3Rfc3BsaXQpID09IDA6CiAgICAgICAgICAgIHJhaXNl + IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oIk5vICdtb25pdG9yaW5nLWVuZHBvaW50JyBmb3Vu + ZCIpCiAgICAgICAgIyBmaXJzdCBpcCBpcyB0cmVhdGVkIGFzIHRoZSBtYWluIG1vbml0b3Jpbmct + ZW5kcG9pbnQKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwID0gbW9uaXRvcmluZ19lbmRw + b2ludF9pcF9saXN0X3NwbGl0WzBdCiAgICAgICAgIyByZXN0IG9mIHRoZSBpcC1zIGFyZSBhZGRl + ZCB0byB0aGUgJ3N0YW5kYnlfbWdycycgbGlzdAogICAgICAgIHN0YW5kYnlfbWdycy5leHRlbmQo + bW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0X3NwbGl0WzE6XSkKICAgICAgICBmYWlsZWRfaXAg + PSBtb25pdG9yaW5nX2VuZHBvaW50X2lwCgogICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnQgPSAi + OiIuam9pbigKICAgICAgICAgICAgW21vbml0b3JpbmdfZW5kcG9pbnRfaXAsIG1vbml0b3Jpbmdf + ZW5kcG9pbnRfcG9ydF0KICAgICAgICApCiAgICAgICAgaXBfdHlwZSA9IHNlbGYuX2ludmFsaWRf + ZW5kcG9pbnQobW9uaXRvcmluZ19lbmRwb2ludCkKICAgICAgICB0cnk6CiAgICAgICAgICAgIG1v + bml0b3JpbmdfZW5kcG9pbnRfaXAgPSBzZWxmLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKAogICAg + ICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcCwgbW9uaXRvcmluZ19lbmRwb2ludF9w + b3J0LCBpcF90eXBlCiAgICAgICAgICAgICkKICAgICAgICAgICAgIyBjb2xsZWN0IGFsbCB0aGUg + J3N0YW5kLWJ5JyBtZ3IgaXBzCiAgICAgICAgICAgIG1ncl9pcHMgPSBbXQogICAgICAgICAgICBm + b3IgZWFjaF9zdGFuZGJ5X21nciBpbiBzdGFuZGJ5X21ncnM6CiAgICAgICAgICAgICAgICBmYWls + ZWRfaXAgPSBlYWNoX3N0YW5kYnlfbWdyCiAgICAgICAgICAgICAgICBtZ3JfaXBzLmFwcGVuZCgK + ICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKAogICAgICAg + ICAgICAgICAgICAgICAgICBlYWNoX3N0YW5kYnlfbWdyLCBtb25pdG9yaW5nX2VuZHBvaW50X3Bv + cnQsIGlwX3R5cGUKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApCiAgICAg + ICAgZXhjZXB0OgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAog + ICAgICAgICAgICAgICAgZiJDb252ZXJzaW9uIG9mIGhvc3Q6IHtmYWlsZWRfaXB9IHRvIElQIGZh + aWxlZC4gIgogICAgICAgICAgICAgICAgIlBsZWFzZSBlbnRlciB0aGUgSVAgYWRkcmVzc2VzIG9m + IGFsbCB0aGUgY2VwaC1tZ3JzIHdpdGggdGhlICctLW1vbml0b3JpbmctZW5kcG9pbnQnIGZsYWci + CiAgICAgICAgICAgICkKCiAgICAgICAgXywgXywgZXJyID0gc2VsZi5lbmRwb2ludF9kaWFsKG1v + bml0b3JpbmdfZW5kcG9pbnQsIGlwX3R5cGUpCiAgICAgICAgaWYgZXJyID09ICItMSI6CiAgICAg + ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oZXJyKQogICAgICAgICMgYWRk + IHRoZSB2YWxpZGF0ZWQgYWN0aXZlIG1nciBJUCBpbnRvIHRoZSBmaXJzdCBpbmRleAogICAgICAg + IG1ncl9pcHMuaW5zZXJ0KDAsIG1vbml0b3JpbmdfZW5kcG9pbnRfaXApCiAgICAgICAgYWxsX21n + cl9pcHNfc3RyID0gIiwiLmpvaW4obWdyX2lwcykKICAgICAgICByZXR1cm4gYWxsX21ncl9pcHNf + c3RyLCBtb25pdG9yaW5nX2VuZHBvaW50X3BvcnQKCiAgICBkZWYgY2hlY2tfdXNlcl9leGlzdChz + ZWxmLCB1c2VyKToKICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogImF1dGggZ2V0IiwgImVu + dGl0eSI6IGYie3VzZXJ9IiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICByZXRfdmFsLCBqc29u + X291dCwgXyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgaWYg + cmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAgICAgICAgICAgcmV0dXJuICIi + CiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0pCgogICAgZGVmIGdldF9jZXBo + ZnNfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KHNlbGYpOgogICAgICAgIGVudGl0eSA9ICJj + bGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIKICAgICAgICBjYXBzID0gewogICAgICAgICAg + ICAibW9uIjogImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwKICAgICAg + ICAgICAgIm1nciI6ICJhbGxvdyBydyIsCiAgICAgICAgICAgICJvc2QiOiAiYWxsb3cgcncgdGFn + IGNlcGhmcyBtZXRhZGF0YT0qIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl + ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgazhzX2NsdXN0ZXJfbmFt + ZSA9IHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZQogICAgICAgICAgICBpZiBrOHNf + Y2x1c3Rlcl9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVy + ZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiazhzX2NsdXN0ZXJfbmFtZSBub3QgZm91 + bmQsIHBsZWFzZSBzZXQgdGhlICctLWs4cy1jbHVzdGVyLW5hbWUnIGZsYWciCiAgICAgICAgICAg + ICAgICApCiAgICAgICAgICAgIGNlcGhmc19maWxlc3lzdGVtID0gc2VsZi5fYXJnX3BhcnNlci5j + ZXBoZnNfZmlsZXN5c3RlbV9uYW1lCiAgICAgICAgICAgIGlmIGNlcGhmc19maWxlc3lzdGVtID09 + ICIiOgogICAgICAgICAgICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFt + ZX0iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9 + LXtrOHNfY2x1c3Rlcl9uYW1lfS17Y2VwaGZzX2ZpbGVzeXN0ZW19IgogICAgICAgICAgICAgICAg + Y2Fwc1sib3NkIl0gPSBmImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9e2NlcGhmc19maWxl + c3lzdGVtfSIKCiAgICAgICAgcmV0dXJuIGNhcHMsIGVudGl0eQoKICAgIGRlZiBnZXRfY2VwaGZz + X25vZGVfY2Fwc19hbmRfZW50aXR5KHNlbGYpOgogICAgICAgIGVudGl0eSA9ICJjbGllbnQuY3Np + LWNlcGhmcy1ub2RlIgogICAgICAgIGNhcHMgPSB7CiAgICAgICAgICAgICJtb24iOiAiYWxsb3cg + ciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLAogICAgICAgICAgICAibWdyIjogImFs + bG93IHJ3IiwKICAgICAgICAgICAgIm9zZCI6ICJhbGxvdyBydyB0YWcgY2VwaGZzICo9KiIsCiAg + ICAgICAgICAgICJtZHMiOiAiYWxsb3cgcnciLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9h + cmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uOgogICAgICAgICAgICBrOHNfY2x1 + c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lCiAgICAgICAgICAg + IGlmIGs4c19jbHVzdGVyX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRp + b25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJrOHNfY2x1c3Rlcl9uYW1l + IG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAg + ICAgICAgICAgICAgICkKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW0gPSBzZWxmLl9hcmdf + cGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICAgICAgaWYgY2VwaGZzX2ZpbGVz + eXN0ZW0gPT0gIiI6CiAgICAgICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1 + c3Rlcl9uYW1lfSIKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGVudGl0eSA9IGYi + e2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXtjZXBoZnNfZmlsZXN5c3RlbX0iCiAgICAgICAg + ICAgICAgICBjYXBzWyJvc2QiXSA9IGYiYWxsb3cgcncgdGFnIGNlcGhmcyAqPXtjZXBoZnNfZmls + ZXN5c3RlbX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2VudGl0 + eSgKICAgICAgICBzZWxmLAogICAgICAgIGVudGl0eSwKICAgICAgICByYmRfcG9vbF9uYW1lLAog + ICAgICAgIGFsaWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgazhzX2NsdXN0ZXJfbmFtZSwKICAg + ICAgICByYWRvc19uYW1lc3BhY2UsCiAgICApOgogICAgICAgIGlmICgKICAgICAgICAgICAgcmJk + X3Bvb2xfbmFtZS5jb3VudCgiLiIpICE9IDAKICAgICAgICAgICAgb3IgcmJkX3Bvb2xfbmFtZS5j + b3VudCgiXyIpICE9IDAKICAgICAgICAgICAgb3IgYWxpYXNfcmJkX3Bvb2xfbmFtZSAhPSAiIgog + ICAgICAgICAgICAjIGNoZWNraW5nIGFsaWFzX3JiZF9wb29sX25hbWUgaXMgbm90IGVtcHR5IGFz + IHRoZXJlIG1heWJlIGEgc3BlY2lhbCBjaGFyYWN0ZXIgdXNlZCBvdGhlciB0aGFuIC4gb3IgXwog + ICAgICAgICk6CiAgICAgICAgICAgIGlmIGFsaWFzX3JiZF9wb29sX25hbWUgPT0gIiI6CiAgICAg + ICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAg + ICAgICAgICJwbGVhc2Ugc2V0IHRoZSAnLS1hbGlhcy1yYmQtZGF0YS1wb29sLW5hbWUnIGZsYWcg + YXMgdGhlIHJiZCBkYXRhIHBvb2wgbmFtZSBjb250YWlucyAnLicgb3IgJ18nIgogICAgICAgICAg + ICAgICAgKQogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICBhbGlhc19yYmRfcG9vbF9u + YW1lLmNvdW50KCIuIikgIT0gMAogICAgICAgICAgICAgICAgb3IgYWxpYXNfcmJkX3Bvb2xfbmFt + ZS5jb3VudCgiXyIpICE9IDAKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHJhaXNlIEV4 + ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIictLWFsaWFzLXJi + ZC1kYXRhLXBvb2wtbmFtZScgZmxhZyB2YWx1ZSBzaG91bGQgbm90IGNvbnRhaW4gJy4nIG9yICdf + JyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17azhz + X2NsdXN0ZXJfbmFtZX0te2FsaWFzX3JiZF9wb29sX25hbWV9IgogICAgICAgIGVsc2U6CiAgICAg + ICAgICAgIGVudGl0eSA9IGYie2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXtyYmRfcG9vbF9u + YW1lfSIKCiAgICAgICAgaWYgcmFkb3NfbmFtZXNwYWNlOgogICAgICAgICAgICBlbnRpdHkgPSBm + IntlbnRpdHl9LXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgIHJldHVybiBlbnRpdHkKCiAgICBk + ZWYgZ2V0X3JiZF9wcm92aXNpb25lcl9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50 + aXR5ID0gImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIgogICAgICAgIGNhcHMgPSB7CiAgICAg + ICAgICAgICJtb24iOiAicHJvZmlsZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3Qn + IiwKICAgICAgICAgICAgIm1nciI6ICJhbGxvdyBydyIsCiAgICAgICAgICAgICJvc2QiOiAicHJv + ZmlsZSByYmQiLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0 + ZWRfYXV0aF9wZXJtaXNzaW9uOgogICAgICAgICAgICByYmRfcG9vbF9uYW1lID0gc2VsZi5fYXJn + X3BhcnNlci5yYmRfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFt + ZSA9IHNlbGYuX2FyZ19wYXJzZXIuYWxpYXNfcmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAg + IGs4c19jbHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAg + ICAgICAgICAgcmFkb3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3Bh + Y2UKICAgICAgICAgICAgaWYgcmJkX3Bvb2xfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJh + aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRh + dG9yeSBmbGFnIG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tcmJkLWRhdGEtcG9vbC1uYW1l + JyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1l + ID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigK + ICAgICAgICAgICAgICAgICAgICAibWFuZGF0b3J5IGZsYWcgbm90IGZvdW5kLCBwbGVhc2Ugc2V0 + IHRoZSAnLS1rOHMtY2x1c3Rlci1uYW1lJyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAg + ICAgICBlbnRpdHkgPSBzZWxmLmdldF9lbnRpdHkoCiAgICAgICAgICAgICAgICBlbnRpdHksCiAg + ICAgICAgICAgICAgICByYmRfcG9vbF9uYW1lLAogICAgICAgICAgICAgICAgYWxpYXNfcmJkX3Bv + b2xfbmFtZSwKICAgICAgICAgICAgICAgIGs4c19jbHVzdGVyX25hbWUsCiAgICAgICAgICAgICAg + ICByYWRvc19uYW1lc3BhY2UsCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgcmFkb3NfbmFt + ZXNwYWNlICE9ICIiOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSAoCiAgICAgICAgICAg + ICAgICAgICAgZiJwcm9maWxlIHJiZCBwb29sPXtyYmRfcG9vbF9uYW1lfSBuYW1lc3BhY2U9e3Jh + ZG9zX25hbWVzcGFjZX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAg + ICAgICAgICAgICBjYXBzWyJvc2QiXSA9IGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFt + ZX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X3JiZF9ub2RlX2Nh + cHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSAiY2xpZW50LmNzaS1yYmQtbm9k + ZSIKICAgICAgICBjYXBzID0gewogICAgICAgICAgICAibW9uIjogInByb2ZpbGUgcmJkLCBhbGxv + dyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJvc2QiOiAicHJvZmlsZSBy + YmQiLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0 + aF9wZXJtaXNzaW9uOgogICAgICAgICAgICByYmRfcG9vbF9uYW1lID0gc2VsZi5fYXJnX3BhcnNl + ci5yYmRfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFtZSA9IHNl + bGYuX2FyZ19wYXJzZXIuYWxpYXNfcmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGs4c19j + bHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAgICAgICAg + ICAgcmFkb3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UKICAg + ICAgICAgICAgaWYgcmJkX3Bvb2xfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4 + ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBm + bGFnIG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tcmJkLWRhdGEtcG9vbC1uYW1lJyBmbGFn + IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1lID09ICIi + OgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAg + ICAgICAgICAgICAgICAibWFuZGF0b3J5IGZsYWcgbm90IGZvdW5kLCBwbGVhc2Ugc2V0IHRoZSAn + LS1rOHMtY2x1c3Rlci1uYW1lJyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBl + bnRpdHkgPSBzZWxmLmdldF9lbnRpdHkoCiAgICAgICAgICAgICAgICBlbnRpdHksCiAgICAgICAg + ICAgICAgICByYmRfcG9vbF9uYW1lLAogICAgICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFt + ZSwKICAgICAgICAgICAgICAgIGs4c19jbHVzdGVyX25hbWUsCiAgICAgICAgICAgICAgICByYWRv + c19uYW1lc3BhY2UsCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgcmFkb3NfbmFtZXNwYWNl + ICE9ICIiOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSAoCiAgICAgICAgICAgICAgICAg + ICAgZiJwcm9maWxlIHJiZCBwb29sPXtyYmRfcG9vbF9uYW1lfSBuYW1lc3BhY2U9e3JhZG9zX25h + bWVzcGFjZX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg + ICAgICBjYXBzWyJvc2QiXSA9IGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFtZX0iCgog + ICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2RlZmF1bHRVc2VyX2NhcHNf + YW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSBzZWxmLnJ1bl9hc191c2VyCiAgICAg + ICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1 + b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQgdmVyc2lvbiIsCiAgICAgICAgICAgICJtZ3IiOiAi + YWxsb3cgY29tbWFuZCBjb25maWciLAogICAgICAgICAgICAib3NkIjogZiJwcm9maWxlIHJiZC1y + ZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPXtzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZp + eH0ucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9e3NlbGYu + X2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD17 + c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5sb2csIGFsbG93IHggcG9vbD17 + c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5idWNrZXRzLmluZGV4IiwKICAg + ICAgICB9CgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2NhcHNfYW5k + X2VudGl0eShzZWxmLCB1c2VyX25hbWUpOgogICAgICAgIGlmICJjbGllbnQuY3NpLWNlcGhmcy1w + cm92aXNpb25lciIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAiY2xpZW50LmNzaS1jZXBo + ZnMtcHJvdmlzaW9uZXIiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19w + YXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAgIHJldHVy + biBzZWxmLmdldF9jZXBoZnNfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KCkKICAgICAgICBp + ZiAiY2xpZW50LmNzaS1jZXBoZnMtbm9kZSIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAi + Y2xpZW50LmNzaS1jZXBoZnMtbm9kZSIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2Vs + Zi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAg + ICAgcmV0dXJuIHNlbGYuZ2V0X2NlcGhmc19ub2RlX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAg + aWYgImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiBpbiB1c2VyX25hbWU6CiAgICAgICAgICAg + IGlmICJjbGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIgIT0gdXNlcl9uYW1lOgogICAgICAgICAg + ICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUK + ICAgICAgICAgICAgcmV0dXJuIHNlbGYuZ2V0X3JiZF9wcm92aXNpb25lcl9jYXBzX2FuZF9lbnRp + dHkoKQogICAgICAgIGlmICJjbGllbnQuY3NpLXJiZC1ub2RlIiBpbiB1c2VyX25hbWU6CiAgICAg + ICAgICAgIGlmICJjbGllbnQuY3NpLXJiZC1ub2RlIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAg + ICAgICBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQog + ICAgICAgICAgICByZXR1cm4gc2VsZi5nZXRfcmJkX25vZGVfY2Fwc19hbmRfZW50aXR5KCkKICAg + ICAgICBpZiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiIGluIHVzZXJfbmFtZToKICAgICAgICAgICAg + aWYgImNsaWVudC5oZWFsdGhjaGVja2VyIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAgICAgICBz + ZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQogICAgICAg + ICAgICByZXR1cm4gc2VsZi5nZXRfZGVmYXVsdFVzZXJfY2Fwc19hbmRfZW50aXR5KCkKCiAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgZiJubyB1c2Vy + IGZvdW5kIHdpdGggdXNlcl9uYW1lOiB7dXNlcl9uYW1lfSwgIgogICAgICAgICAgICAiZ2V0X2Nh + cHNfYW5kX2VudGl0eSBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICApCgogICAgZGVmIGNyZWF0 + ZV9jZXBoQ1NJS2V5cmluZ191c2VyKHNlbGYsIHVzZXIpOgogICAgICAgICIiIgogICAgICAgIGNv + bW1hbmQ6IGNlcGggYXV0aCBnZXQtb3ItY3JlYXRlIGNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv + bmVyIG1vbiAnYWxsb3cgcicgbWdyICdhbGxvdyBydycgb3NkICdhbGxvdyBydyB0YWcgY2VwaGZz + IG1ldGFkYXRhPSonCiAgICAgICAgIiIiCiAgICAgICAgY2FwcywgZW50aXR5ID0gc2VsZi5nZXRf + Y2Fwc19hbmRfZW50aXR5KHVzZXIpCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJw + cmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIiwKICAgICAgICAgICAgImVudGl0eSI6IGVudGl0 + eSwKICAgICAgICAgICAgImNhcHMiOiBbY2FwIGZvciBjYXBfbGlzdCBpbiBsaXN0KGNhcHMuaXRl + bXMoKSkgZm9yIGNhcCBpbiBjYXBfbGlzdF0sCiAgICAgICAgICAgICJmb3JtYXQiOiAianNvbiIs + CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAg + ICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICBzZWxmLmRyeV9ydW4oCiAgICAgICAgICAgICAg + ICAgICAgImNlcGggIgogICAgICAgICAgICAgICAgICAgICsgY21kX2pzb25bInByZWZpeCJdCiAg + ICAgICAgICAgICAgICAgICAgKyAiICIKICAgICAgICAgICAgICAgICAgICArIGNtZF9qc29uWyJl + bnRpdHkiXQogICAgICAgICAgICAgICAgICAgICsgIiAiCiAgICAgICAgICAgICAgICAgICAgKyAi + ICIuam9pbihjbWRfanNvblsiY2FwcyJdKQogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAg + ICAgICIiLAogICAgICAgICAgICApCiAgICAgICAgIyBjaGVjayBpZiB1c2VyIGFscmVhZHkgZXhp + c3QKICAgICAgICB1c2VyX2tleSA9IHNlbGYuY2hlY2tfdXNlcl9leGlzdChlbnRpdHkpCiAgICAg + ICAgaWYgdXNlcl9rZXkgIT0gIiI6CiAgICAgICAgICAgIHJldHVybiB1c2VyX2tleSwgZiJ7ZW50 + aXR5LnNwbGl0KCcuJywgMSlbMV19IgogICAgICAgICAgICAjIGVudGl0eS5zcGxpdCgnLicsMSlb + MV0gdG8gcmVuYW1lIGVudGl0eShjbGllbnQuY3NpLXJiZC1ub2RlKSBhcyBjc2ktcmJkLW5vZGUK + CiAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pz + b25fZ2VuKGNtZF9qc29uKQogICAgICAgICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0 + dGVtcHQsCiAgICAgICAgaWYgcmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAg + ICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAg + IGYiJ2F1dGggZ2V0LW9yLWNyZWF0ZSB7dXNlcn0nIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAg + ICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBU + WV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICkKICAgICAgICByZXR1cm4gc3RyKGpzb25fb3V0 + WzBdWyJrZXkiXSksIGYie2VudGl0eS5zcGxpdCgnLicsIDEpWzFdfSIKICAgICAgICAjIGVudGl0 + eS5zcGxpdCgnLicsMSlbMV0gdG8gcmVuYW1lIGVudGl0eShjbGllbnQuY3NpLXJiZC1ub2RlKSBh + cyBjc2ktcmJkLW5vZGUKCiAgICBkZWYgZ2V0X2NlcGhmc19kYXRhX3Bvb2xfZGV0YWlscyhzZWxm + KToKICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogImZzIGxzIiwgImZvcm1hdCI6ICJqc29u + In0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVy + biBzZWxmLmRyeV9ydW4oImNlcGggIiArIGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRf + dmFsLCBqc29uX291dCwgZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pz + b24pCiAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwgcmVwb3J0 + IGFuIGVycm9yCiAgICAgICAgaWYgcmV0X3ZhbCAhPSAwOgogICAgICAgICAgICAjIGlmIGZzIGFu + ZCBkYXRhX3Bvb2wgYXJndW1lbnRzIGFyZSBub3Qgc2V0LCBzaWxlbnRseSByZXR1cm4KICAgICAg + ICAgICAgaWYgKAogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmlsZXN5 + c3RlbV9uYW1lID09ICIiCiAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5jZXBo + ZnNfZGF0YV9wb29sX25hbWUgPT0gIiIKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHJl + dHVybgogICAgICAgICAgICAjIGlmIHVzZXIgaGFzIHByb3ZpZGVkIGFueSBvZiB0aGUKICAgICAg + ICAgICAgIyAnLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lJyBvciAnLS1jZXBoZnMtZGF0YS1wb29s + LW5hbWUnIGFyZ3VtZW50cywKICAgICAgICAgICAgIyByYWlzZSBhbiBleGNlcHRpb24gYXMgd2Ug + YXJlIHVuYWJsZSB0byB2ZXJpZnkgdGhlIGFyZ3MKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9u + RmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiJ2ZzIGxzJyBjZXBoIGNhbGwgZmFp + bGVkIHdpdGggZXJyb3I6IHtlcnJfbXNnfSIKICAgICAgICAgICAgKQoKICAgICAgICBtYXRjaGlu + Z19qc29uX291dCA9IHt9CiAgICAgICAgIyBpZiAnLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lJyBh + cmd1bWVudCBpcyBwcm92aWRlZCwKICAgICAgICAjIGNoZWNrIHdoZXRoZXIgdGhlIHByb3ZpZGVk + IGZpbGVzeXN0ZW0tbmFtZSBleGlzdHMgb3Igbm90CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl + ci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lOgogICAgICAgICAgICAjIGdldCB0aGUgbWF0Y2hpbmcg + bGlzdAogICAgICAgICAgICBtYXRjaGluZ19qc29uX291dF9saXN0ID0gWwogICAgICAgICAgICAg + ICAgbWF0Y2hlZAogICAgICAgICAgICAgICAgZm9yIG1hdGNoZWQgaW4ganNvbl9vdXQKICAgICAg + ICAgICAgICAgIGlmIHN0cihtYXRjaGVkWyJuYW1lIl0pID09IHNlbGYuX2FyZ19wYXJzZXIuY2Vw + aGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgICAgICBdCiAgICAgICAgICAgICMgdW5hYmxlIHRv + IGZpbmQgYSBtYXRjaGluZyBmcy1uYW1lLCByYWlzZSBhbiBlcnJvcgogICAgICAgICAgICBpZiBs + ZW4obWF0Y2hpbmdfanNvbl9vdXRfbGlzdCkgPT0gMDoKICAgICAgICAgICAgICAgIHJhaXNlIEV4 + ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgZiJGaWxlc3lzdGVt + IHByb3ZpZGVkLCAne3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZX0nLCAi + CiAgICAgICAgICAgICAgICAgICAgZiJpcyBub3QgZm91bmQgaW4gdGhlIGZzLWxpc3Q6IHtbc3Ry + KHhbJ25hbWUnXSkgZm9yIHggaW4ganNvbl9vdXRdfSIKICAgICAgICAgICAgICAgICkKICAgICAg + ICAgICAgbWF0Y2hpbmdfanNvbl9vdXQgPSBtYXRjaGluZ19qc29uX291dF9saXN0WzBdCiAgICAg + ICAgIyBpZiBjZXBoZnMgZmlsZXN5c3RlbSBuYW1lIGlzIG5vdCBwcm92aWRlZCwKICAgICAgICAj + IHRyeSB0byBnZXQgYSBkZWZhdWx0IGZzIG5hbWUgYnkgZG9pbmcgdGhlIGZvbGxvd2luZwogICAg + ICAgIGVsc2U6CiAgICAgICAgICAgICMgYS4gY2hlY2sgaWYgdGhlcmUgaXMgb25seSBvbmUgZmls + ZXN5c3RlbSBpcyBwcmVzZW50CiAgICAgICAgICAgIGlmIGxlbihqc29uX291dCkgPT0gMToKICAg + ICAgICAgICAgICAgIG1hdGNoaW5nX2pzb25fb3V0ID0ganNvbl9vdXRbMF0KICAgICAgICAgICAg + IyBiLiBvciBlbHNlLCBjaGVjayBpZiBkYXRhX3Bvb2wgbmFtZSBpcyBwcm92aWRlZAogICAgICAg + ICAgICBlbGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lOgogICAgICAg + ICAgICAgICAgIyBhbmQgaWYgcHJlc2VudCwgY2hlY2sgd2hldGhlciB0aGVyZSBleGlzdHMgYSBm + cyB3aGljaCBoYXMgdGhlIGRhdGFfcG9vbAogICAgICAgICAgICAgICAgZm9yIGVhY2hKIGluIGpz + b25fb3V0OgogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2Rh + dGFfcG9vbF9uYW1lIGluIGVhY2hKWyJkYXRhX3Bvb2xzIl06CiAgICAgICAgICAgICAgICAgICAg + ICAgIG1hdGNoaW5nX2pzb25fb3V0ID0gZWFjaEoKICAgICAgICAgICAgICAgICAgICAgICAgYnJl + YWsKICAgICAgICAgICAgICAgICMgaWYgdGhlcmUgaXMgbm8gbWF0Y2hpbmcgZnMgZXhpc3RzLCB0 + aGF0IG1lYW5zIHByb3ZpZGVkIGRhdGFfcG9vbCBuYW1lIGlzIGludmFsaWQKICAgICAgICAgICAg + ICAgIGlmIG5vdCBtYXRjaGluZ19qc29uX291dDoKICAgICAgICAgICAgICAgICAgICByYWlzZSBF + eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICAgICBmIlByb3Zp + ZGVkIGRhdGFfcG9vbCBuYW1lLCB7c2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25h + bWV9LCIKICAgICAgICAgICAgICAgICAgICAgICAgIiBkb2VzIG5vdCBleGlzdHMiCiAgICAgICAg + ICAgICAgICAgICAgKQogICAgICAgICAgICAjIGMuIGlmIG5vdGhpbmcgaXMgc2V0IGFuZCBjb3Vs + ZG4ndCBmaW5kIGEgZGVmYXVsdCwKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICMg + anVzdCByZXR1cm4gc2lsZW50bHkKICAgICAgICAgICAgICAgIHJldHVybgoKICAgICAgICBpZiBt + YXRjaGluZ19qc29uX291dDoKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls + ZXN5c3RlbV9uYW1lID0gc3RyKG1hdGNoaW5nX2pzb25fb3V0WyJuYW1lIl0pCiAgICAgICAgICAg + IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX21ldGFkYXRhX3Bvb2xfbmFtZSA9IHN0cigKICAgICAg + ICAgICAgICAgIG1hdGNoaW5nX2pzb25fb3V0WyJtZXRhZGF0YV9wb29sIl0KICAgICAgICAgICAg + KQoKICAgICAgICBpZiBpc2luc3RhbmNlKG1hdGNoaW5nX2pzb25fb3V0WyJkYXRhX3Bvb2xzIl0s + IGxpc3QpOgogICAgICAgICAgICAjIGlmIHRoZSB1c2VyIGhhcyBhbHJlYWR5IHByb3ZpZGVkIGRh + dGEtcG9vbC1uYW1lLAogICAgICAgICAgICAjIHRocm91Z2ggLS1jZXBoZnMtZGF0YS1wb29sLW5h + bWUKICAgICAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWU6 + CiAgICAgICAgICAgICAgICAjIGlmIHRoZSBwcm92aWRlZCBuYW1lIGlzIG5vdCBtYXRjaGluZyB3 + aXRoIHRoZSBvbmUgaW4gdGhlIGxpc3QKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAg + ICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFtZQogICAgICAgICAg + ICAgICAgICAgIG5vdCBpbiBtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdCiAgICAgICAg + ICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl + cHRpb24oCiAgICAgICAgICAgICAgICAgICAgICAgIGYiUHJvdmlkZWQgZGF0YS1wb29sLW5hbWU6 + ICd7c2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWV9JywgIgogICAgICAgICAg + ICAgICAgICAgICAgICAiZG9lc24ndCBtYXRjaCBmcm9tIHRoZSBkYXRhLXBvb2xzIGxpc3Q6ICIK + ICAgICAgICAgICAgICAgICAgICAgICAgZiJ7W3N0cih4KSBmb3IgeCBpbiBtYXRjaGluZ19qc29u + X291dFsnZGF0YV9wb29scyddXX0iCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAj + IGlmIGRhdGFfcG9vbCBuYW1lIGlzIG5vdCBwcm92aWRlZCwKICAgICAgICAgICAgIyB0aGVuIHRy + eSB0byBmaW5kIGEgZGVmYXVsdCBkYXRhIHBvb2wgbmFtZQogICAgICAgICAgICBlbHNlOgogICAg + ICAgICAgICAgICAgIyBpZiBubyBkYXRhX3Bvb2xzIGV4aXN0LCBzaWxlbnRseSByZXR1cm4KICAg + ICAgICAgICAgICAgIGlmIGxlbihtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdKSA9PSAw + OgogICAgICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3Bh + cnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWUgPSBzdHIoCiAgICAgICAgICAgICAgICAgICAgbWF0 + Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXVswXQogICAgICAgICAgICAgICAgKQogICAgICAg + ICAgICAjIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lICdkYXRhX3Bvb2xzJyBleGlzdCwKICAg + ICAgICAgICAgIyB0aGVuIHdhcm4gdGhlIHVzZXIgdGhhdCB3ZSBhcmUgdXNpbmcgdGhlIHNlbGVj + dGVkIG5hbWUKICAgICAgICAgICAgaWYgbGVuKG1hdGNoaW5nX2pzb25fb3V0WyJkYXRhX3Bvb2xz + Il0pID4gMToKICAgICAgICAgICAgICAgIHByaW50KAogICAgICAgICAgICAgICAgICAgICJXQVJO + SU5HOiBNdWx0aXBsZSBkYXRhIHBvb2xzIGRldGVjdGVkOiAiCiAgICAgICAgICAgICAgICAgICAg + ZiJ7W3N0cih4KSBmb3IgeCBpbiBtYXRjaGluZ19qc29uX291dFsnZGF0YV9wb29scyddXX1cbiIK + ICAgICAgICAgICAgICAgICAgICBmIlVzaW5nIHRoZSBkYXRhLXBvb2w6ICd7c2VsZi5fYXJnX3Bh + cnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWV9J1xuIgogICAgICAgICAgICAgICAgKQoKICAgIGRl + ZiBjcmVhdGVfY2hlY2tlcktleShzZWxmLCB1c2VyKToKICAgICAgICBjYXBzLCBlbnRpdHkgPSBz + ZWxmLmdldF9jYXBzX2FuZF9lbnRpdHkodXNlcikKICAgICAgICBjbWRfanNvbiA9IHsKICAgICAg + ICAgICAgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUiLAogICAgICAgICAgICAiZW50aXR5 + IjogZW50aXR5LAogICAgICAgICAgICAiY2FwcyI6IFtjYXAgZm9yIGNhcF9saXN0IGluIGxpc3Qo + Y2Fwcy5pdGVtcygpKSBmb3IgY2FwIGluIGNhcF9saXN0XSwKICAgICAgICAgICAgImZvcm1hdCI6 + ICJqc29uIiwKICAgICAgICB9CgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoK + ICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigKICAgICAgICAgICAgICAgICJjZXBoICIK + ICAgICAgICAgICAgICAgICsgY21kX2pzb25bInByZWZpeCJdCiAgICAgICAgICAgICAgICArICIg + IgogICAgICAgICAgICAgICAgKyBjbWRfanNvblsiZW50aXR5Il0KICAgICAgICAgICAgICAgICsg + IiAiCiAgICAgICAgICAgICAgICArICIgIi5qb2luKGNtZF9qc29uWyJjYXBzIl0pCiAgICAgICAg + ICAgICkKICAgICAgICAjIGNoZWNrIGlmIHVzZXIgYWxyZWFkeSBleGlzdAogICAgICAgIHVzZXJf + a2V5ID0gc2VsZi5jaGVja191c2VyX2V4aXN0KGVudGl0eSkKICAgICAgICBpZiB1c2VyX2tleSAh + PSAiIjoKICAgICAgICAgICAgcmV0dXJuIHVzZXJfa2V5CgogICAgICAgIHJldF92YWwsIGpzb25f + b3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAg + ICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgIGlmIHJldF92 + YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlv + bkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGdldC1vci1jcmVhdGUg + e3NlbGYucnVuX2FzX3VzZXJ9JyBjb21tYW5kIGZhaWxlZFxuIgogICAgICAgICAgICAgICAgZiJF + cnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElT + VH0iCiAgICAgICAgICAgICkKICAgICAgICByZXR1cm4gc3RyKGpzb25fb3V0WzBdWyJrZXkiXSkK + CiAgICBkZWYgZ2V0X2NlcGhfZGFzaGJvYXJkX2xpbmsoc2VsZik6CiAgICAgICAgY21kX2pzb24g + PSB7InByZWZpeCI6ICJtZ3Igc2VydmljZXMiLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgIGlm + IHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1 + bigiY2VwaCAiICsgY21kX2pzb25bInByZWZpeCJdKQogICAgICAgIHJldF92YWwsIGpzb25fb3V0 + LCBfID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICAjIGlmIHRo + ZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgIGlmIHJldF92YWwgIT0gMCBv + ciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJldHVybiBOb25lCiAgICAgICAgaWYg + ImRhc2hib2FyZCIgbm90IGluIGpzb25fb3V0OgogICAgICAgICAgICByZXR1cm4gTm9uZQogICAg + ICAgIHJldHVybiBqc29uX291dFsiZGFzaGJvYXJkIl0KCiAgICBkZWYgY3JlYXRlX3Jnd19hZG1p + bl9vcHNfdXNlcihzZWxmKToKICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICJyYWRvc2d3LWFk + bWluIiwKICAgICAgICAgICAgInVzZXIiLAogICAgICAgICAgICAiY3JlYXRlIiwKICAgICAgICAg + ICAgIi0tdWlkIiwKICAgICAgICAgICAgc2VsZi5FWFRFUk5BTF9SR1dfQURNSU5fT1BTX1VTRVJf + TkFNRSwKICAgICAgICAgICAgIi0tZGlzcGxheS1uYW1lIiwKICAgICAgICAgICAgIlJvb2sgUkdX + IEFkbWluIE9wcyB1c2VyIiwKICAgICAgICAgICAgIi0tY2FwcyIsCiAgICAgICAgICAgICJidWNr + ZXRzPSo7dXNlcnM9Kjt1c2FnZT1yZWFkO21ldGFkYXRhPXJlYWQ7em9uZT1yZWFkIiwKICAgICAg + ICAgICAgIi0tcmd3LXJlYWxtIiwKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVh + bG1fbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAgICAgICAgIHNlbGYu + X2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lLAogICAgICAgICAgICAiLS1yZ3ctem9uZSIs + CiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwKICAgICAgICBdCiAg + ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2Vs + Zi5kcnlfcnVuKCJjZXBoICIgKyAiICIuam9pbihjbWQpKQogICAgICAgIHRyeToKICAgICAgICAg + ICAgb3V0cHV0ID0gc3VicHJvY2Vzcy5jaGVja19vdXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vz + cy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBl + eGVjRXJyOgogICAgICAgICAgICAjIGlmIHRoZSB1c2VyIGFscmVhZHkgZXhpc3RzLCB3ZSBqdXN0 + IHF1ZXJ5IGl0CiAgICAgICAgICAgIGlmIGV4ZWNFcnIucmV0dXJuY29kZSA9PSBlcnJuby5FRVhJ + U1Q6CiAgICAgICAgICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICAgICAgICAgInJhZG9zZ3ct + YWRtaW4iLAogICAgICAgICAgICAgICAgICAgICJ1c2VyIiwKICAgICAgICAgICAgICAgICAgICAi + aW5mbyIsCiAgICAgICAgICAgICAgICAgICAgIi0tdWlkIiwKICAgICAgICAgICAgICAgICAgICBz + ZWxmLkVYVEVSTkFMX1JHV19BRE1JTl9PUFNfVVNFUl9OQU1FLAogICAgICAgICAgICAgICAgICAg + ICItLXJndy1yZWFsbSIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3df + cmVhbG1fbmFtZSwKICAgICAgICAgICAgICAgICAgICAiLS1yZ3ctem9uZWdyb3VwIiwKICAgICAg + ICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAg + ICAgICAgICAgICAgICAiLS1yZ3ctem9uZSIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJn + X3BhcnNlci5yZ3dfem9uZV9uYW1lLAogICAgICAgICAgICAgICAgXQogICAgICAgICAgICAgICAg + dHJ5OgogICAgICAgICAgICAgICAgICAgIG91dHB1dCA9IHN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0 + KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICAgICAgICAgIGV4Y2VwdCBzdWJw + cm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAgICAgICAgICAg + IGVycl9tc2cgPSAoCiAgICAgICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUg + Y29tbWFuZCB7Y21kfS4gT3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAg + ICAgICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5z + dGRlcnJ9IgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICBzeXMuc3Rk + ZXJyLndyaXRlKGVycl9tc2cpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE5vbmUsIE5vbmUs + IEZhbHNlLCAiLTEiCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlcnJfbXNnID0g + KAogICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUgY29tbWFuZCB7Y21kfS4g + T3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAgICAgICAgZiJDb2RlOiB7 + ZXhlY0Vyci5yZXR1cm5jb2RlfS4gRXJyb3I6IHtleGVjRXJyLnN0ZGVycn0iCiAgICAgICAgICAg + ICAgICApCiAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycl9tc2cpCiAgICAgICAg + ICAgICAgICByZXR1cm4gTm9uZSwgTm9uZSwgRmFsc2UsICItMSIKCiAgICAgICAgIyBzZXBhcmF0 + ZWx5IGFkZCBpbmZvPXJlYWQgY2FwcyBmb3Igcmd3LWVuZHBvaW50IGlwIHZhbGlkYXRpb24KICAg + ICAgICBpbmZvX2NhcF9zdXBwb3J0ZWQgPSBUcnVlCiAgICAgICAgY21kID0gWwogICAgICAgICAg + ICAicmFkb3Nndy1hZG1pbiIsCiAgICAgICAgICAgICJjYXBzIiwKICAgICAgICAgICAgImFkZCIs + CiAgICAgICAgICAgICItLXVpZCIsCiAgICAgICAgICAgIHNlbGYuRVhURVJOQUxfUkdXX0FETUlO + X09QU19VU0VSX05BTUUsCiAgICAgICAgICAgICItLWNhcHMiLAogICAgICAgICAgICAiaW5mbz1y + ZWFkIiwKICAgICAgICAgICAgIi0tcmd3LXJlYWxtIiwKICAgICAgICAgICAgc2VsZi5fYXJnX3Bh + cnNlci5yZ3dfcmVhbG1fbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAg + ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lLAogICAgICAgICAgICAi + LS1yZ3ctem9uZSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwK + ICAgICAgICBdCiAgICAgICAgdHJ5OgogICAgICAgICAgICBvdXRwdXQgPSBzdWJwcm9jZXNzLmNo + ZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhjZXB0IHN1 + YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4ZWNFcnI6CiAgICAgICAgICAgICMgaWYg + dGhlIGNlcGggdmVyc2lvbiBub3Qgc3VwcG9ydGVkIGZvciBhZGRpbmcgYGluZm89cmVhZGAgY2Fw + KHJnd192YWxpZGF0aW9uKQogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAiY291bGQg + bm90IGFkZCBjYXBzOiB1bmFibGUgdG8gYWRkIGNhcHM6IGluZm89cmVhZFxuIgogICAgICAgICAg + ICAgICAgaW4gZXhlY0Vyci5zdGRlcnIuZGVjb2RlKCJ1dGYtOCIpCiAgICAgICAgICAgICAgICBh + bmQgZXhlY0Vyci5yZXR1cm5jb2RlID09IDI0NAogICAgICAgICAgICApOgogICAgICAgICAgICAg + ICAgaW5mb19jYXBfc3VwcG9ydGVkID0gRmFsc2UKICAgICAgICAgICAgZWxzZToKICAgICAgICAg + ICAgICAgIGVycl9tc2cgPSAoCiAgICAgICAgICAgICAgICAgICAgZiJmYWlsZWQgdG8gZXhlY3V0 + ZSBjb21tYW5kIHtjbWR9LiBPdXRwdXQ6IHtleGVjRXJyLm91dHB1dH0uICIKICAgICAgICAgICAg + ICAgICAgICBmIkNvZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3Rk + ZXJyfSIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3JpdGUo + ZXJyX21zZykKICAgICAgICAgICAgICAgIHJldHVybiBOb25lLCBOb25lLCBGYWxzZSwgIi0xIgoK + ICAgICAgICBqc29ub3V0cHV0ID0ganNvbi5sb2FkcyhvdXRwdXQpCiAgICAgICAgcmV0dXJuICgK + ICAgICAgICAgICAganNvbm91dHB1dFsia2V5cyJdWzBdWyJhY2Nlc3Nfa2V5Il0sCiAgICAgICAg + ICAgIGpzb25vdXRwdXRbImtleXMiXVswXVsic2VjcmV0X2tleSJdLAogICAgICAgICAgICBpbmZv + X2NhcF9zdXBwb3J0ZWQsCiAgICAgICAgICAgICIiLAogICAgICAgICkKCiAgICBkZWYgdmFsaWRh + dGVfcmJkX3Bvb2woc2VsZiwgcG9vbF9uYW1lKToKICAgICAgICBpZiBub3Qgc2VsZi5jbHVzdGVy + LnBvb2xfZXhpc3RzKHBvb2xfbmFtZSk6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1 + cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCBwb29sLCAne3Bvb2xf + bmFtZX0nLCBkb2VzIG5vdCBleGlzdCIKICAgICAgICAgICAgKQoKICAgIGRlZiBpbml0X3JiZF9w + b29sKHNlbGYsIHJiZF9wb29sX25hbWUpOgogICAgICAgIGlmIGlzaW5zdGFuY2Uoc2VsZi5jbHVz + dGVyLCBEdW1teVJhZG9zKToKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgaW9jdHggPSBzZWxm + LmNsdXN0ZXIub3Blbl9pb2N0eChyYmRfcG9vbF9uYW1lKQogICAgICAgIHJiZF9pbnN0ID0gcmJk + LlJCRCgpCiAgICAgICAgcmJkX2luc3QucG9vbF9pbml0KGlvY3R4LCBUcnVlKQoKICAgIGRlZiB2 + YWxpZGF0ZV9yYWRvc19uYW1lc3BhY2Uoc2VsZik6CiAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNl + bGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh + cnNlci5yYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lOgogICAgICAgICAgICByYmRfcG9vbF9uYW1l + ID0gc2VsZi5fYXJnX3BhcnNlci5yYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lCiAgICAgICAgcmFk + b3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UKICAgICAgICBp + ZiByYWRvc19uYW1lc3BhY2UgPT0gIiI6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGlmIHJh + ZG9zX25hbWVzcGFjZS5pc2xvd2VyKCkgPT0gRmFsc2U6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1 + dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByYWRv + cyBOYW1lc3BhY2UsICd7cmFkb3NfbmFtZXNwYWNlfScsICIKICAgICAgICAgICAgICAgIGYiY29u + dGFpbnMgdXBwZXIgY2FzZSIKICAgICAgICAgICAgKQogICAgICAgIHJiZF9pbnN0ID0gcmJkLlJC + RCgpCiAgICAgICAgaW9jdHggPSBzZWxmLmNsdXN0ZXIub3Blbl9pb2N0eChyYmRfcG9vbF9uYW1l + KQogICAgICAgIGlmIHJiZF9pbnN0Lm5hbWVzcGFjZV9leGlzdHMoaW9jdHgsIHJhZG9zX25hbWVz + cGFjZSkgaXMgRmFsc2U6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRp + b24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByYWRvcyBOYW1lc3BhY2UsICd7cmFk + b3NfbmFtZXNwYWNlfScsICIKICAgICAgICAgICAgICAgIGYiaXMgbm90IGZvdW5kIGluIHRoZSBw + b29sICd7cmJkX3Bvb2xfbmFtZX0nIgogICAgICAgICAgICApCgogICAgZGVmIGdldF9vcl9jcmVh + dGVfc3Vidm9sdW1lX2dyb3VwKHNlbGYsIHN1YnZvbHVtZV9ncm91cCwgY2VwaGZzX2ZpbGVzeXN0 + ZW1fbmFtZSk6CiAgICAgICAgY21kID0gWwogICAgICAgICAgICAiY2VwaCIsCiAgICAgICAgICAg + ICJmcyIsCiAgICAgICAgICAgICJzdWJ2b2x1bWVncm91cCIsCiAgICAgICAgICAgICJnZXRwYXRo + IiwKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgc3Vidm9s + dW1lX2dyb3VwLAogICAgICAgIF0KICAgICAgICB0cnk6CiAgICAgICAgICAgIF8gPSBzdWJwcm9j + ZXNzLmNoZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhj + ZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICBjbWQgPSBbCiAg + ICAgICAgICAgICAgICAiY2VwaCIsCiAgICAgICAgICAgICAgICAiZnMiLAogICAgICAgICAgICAg + ICAgInN1YnZvbHVtZWdyb3VwIiwKICAgICAgICAgICAgICAgICJjcmVhdGUiLAogICAgICAgICAg + ICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgICAgIHN1YnZvbHVtZV9n + cm91cCwKICAgICAgICAgICAgXQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBfID0g + c3VicHJvY2Vzcy5jaGVja19vdXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAg + ICAgICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgICAg + ICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAg + IGYic3Vidm9sdW1lIGdyb3VwIHtzdWJ2b2x1bWVfZ3JvdXB9IGlzIG5vdCBhYmxlIHRvIGdldCBj + cmVhdGVkIgogICAgICAgICAgICAgICAgKQoKICAgIGRlZiBwaW5fc3Vidm9sdW1lKAogICAgICAg + IHNlbGYsIHN1YnZvbHVtZV9ncm91cCwgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwgcGluX3R5cGUs + IHBpbl9zZXR0aW5nCiAgICApOgogICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgImNlcGgiLAog + ICAgICAgICAgICAiZnMiLAogICAgICAgICAgICAic3Vidm9sdW1lZ3JvdXAiLAogICAgICAgICAg + ICAicGluIiwKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAg + c3Vidm9sdW1lX2dyb3VwLAogICAgICAgICAgICBwaW5fdHlwZSwKICAgICAgICAgICAgcGluX3Nl + dHRpbmcsCiAgICAgICAgXQogICAgICAgIHRyeToKICAgICAgICAgICAgXyA9IHN1YnByb2Nlc3Mu + Y2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICBleGNlcHQg + c3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlv + bkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmInN1YnZvbHVtZSBncm91cCB7c3Vi + dm9sdW1lX2dyb3VwfSBpcyBub3QgYWJsZSB0byBnZXQgcGlubmVkIgogICAgICAgICAgICApCgog + ICAgZGVmIGdldF9yZ3dfZnNpZChzZWxmLCBiYXNlX3VybCwgdmVyaWZ5KToKICAgICAgICBhY2Nl + c3Nfa2V5ID0gc2VsZi5vdXRfbWFwWyJSR1dfQURNSU5fT1BTX1VTRVJfQUNDRVNTX0tFWSJdCiAg + ICAgICAgc2VjcmV0X2tleSA9IHNlbGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JF + VF9LRVkiXQogICAgICAgIHJnd19lbmRwb2ludCA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBv + aW50CiAgICAgICAgYmFzZV91cmwgPSBiYXNlX3VybCArICI6Ly8iICsgcmd3X2VuZHBvaW50ICsg + Ii9hZG1pbi9pbmZvPyIKICAgICAgICBwYXJhbXMgPSB7ImZvcm1hdCI6ICJqc29uIn0KICAgICAg + ICByZXF1ZXN0X3VybCA9IGJhc2VfdXJsICsgdXJsZW5jb2RlKHBhcmFtcykKCiAgICAgICAgdHJ5 + OgogICAgICAgICAgICByID0gcmVxdWVzdHMuZ2V0KAogICAgICAgICAgICAgICAgcmVxdWVzdF91 + cmwsCiAgICAgICAgICAgICAgICBhdXRoPVMzQXV0aChhY2Nlc3Nfa2V5LCBzZWNyZXRfa2V5LCBy + Z3dfZW5kcG9pbnQpLAogICAgICAgICAgICAgICAgdmVyaWZ5PXZlcmlmeSwKICAgICAgICAgICAg + KQogICAgICAgIGV4Y2VwdCByZXF1ZXN0cy5leGNlcHRpb25zLlRpbWVvdXQ6CiAgICAgICAgICAg + IHN5cy5zdGRlcnIud3JpdGUoCiAgICAgICAgICAgICAgICBmImludmFsaWQgZW5kcG9pbnQ6LCBu + b3QgYWJsZSB0byBjYWxsIGFkbWluLW9wcyBhcGl7cmd3X2VuZHBvaW50fSIKICAgICAgICAgICAg + KQogICAgICAgICAgICByZXR1cm4gIiIsICItMSIKICAgICAgICByMSA9IHIuanNvbigpCiAgICAg + ICAgaWYgcjEgaXMgTm9uZSBvciByMS5nZXQoImluZm8iKSBpcyBOb25lOgogICAgICAgICAgICBz + eXMuc3RkZXJyLndyaXRlKAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmd3IEVuZHBv + aW50LCAne3NlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50fScsIGlzIGludmFsaWQuIgogICAg + ICAgICAgICApCiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAiIiwKICAgICAg + ICAgICAgICAgICItMSIsCiAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIHIxWyJpbmZvIl1b + InN0b3JhZ2VfYmFja2VuZHMiXVswXVsiY2x1c3Rlcl9pZCJdLCAiIgoKICAgIGRlZiB2YWxpZGF0 + ZV9yZ3dfZW5kcG9pbnQoc2VsZiwgaW5mb19jYXBfc3VwcG9ydGVkKToKICAgICAgICAjIGlmIHRo + ZSAnY2x1c3RlcicgaW5zdGFuY2UgaXMgYSBkdW1teSBvbmUsCiAgICAgICAgIyBkb24ndCB0cnkg + dG8gcmVhY2ggb3V0IHRvIHRoZSBlbmRwb2ludAogICAgICAgIGlmIGlzaW5zdGFuY2Uoc2VsZi5j + bHVzdGVyLCBEdW1teVJhZG9zKToKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgIHJnd19lbmRw + b2ludCA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50CgogICAgICAgICMgdmFsaWRhdGUg + cmd3IGVuZHBvaW50IG9ubHkgaWYgaXAgYWRkcmVzcyBpcyBwYXNzZWQKICAgICAgICBpcF90eXBl + ID0gc2VsZi5faW52YWxpZF9lbmRwb2ludChyZ3dfZW5kcG9pbnQpCgogICAgICAgICMgY2hlY2sg + aWYgdGhlIHJndyBlbmRwb2ludCBpcyByZWFjaGFibGUKICAgICAgICBjZXJ0ID0gTm9uZQogICAg + ICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnJnd19za2lwX3RscyBhbmQgc2VsZi52YWxpZGF0 + ZV9yZ3dfZW5kcG9pbnRfdGxzX2NlcnQoKToKICAgICAgICAgICAgY2VydCA9IHNlbGYuX2FyZ19w + YXJzZXIucmd3X3Rsc19jZXJ0X3BhdGgKICAgICAgICBiYXNlX3VybCwgdmVyaWZ5LCBlcnIgPSBz + ZWxmLmVuZHBvaW50X2RpYWwocmd3X2VuZHBvaW50LCBpcF90eXBlLCBjZXJ0PWNlcnQpCiAgICAg + ICAgaWYgZXJyICE9ICIiOgogICAgICAgICAgICByZXR1cm4gIi0xIgoKICAgICAgICAjIGNoZWNr + IGlmIHRoZSByZ3cgZW5kcG9pbnQgYmVsb25ncyB0byB0aGUgc2FtZSBjbHVzdGVyCiAgICAgICAg + IyBvbmx5IGNoZWNrIGlmIGBpbmZvYCBjYXAgaXMgc3VwcG9ydGVkCiAgICAgICAgaWYgaW5mb19j + YXBfc3VwcG9ydGVkOgogICAgICAgICAgICBmc2lkID0gc2VsZi5nZXRfZnNpZCgpCiAgICAgICAg + ICAgIHJnd19mc2lkLCBlcnIgPSBzZWxmLmdldF9yZ3dfZnNpZChiYXNlX3VybCwgdmVyaWZ5KQog + ICAgICAgICAgICBpZiBlcnIgPT0gIi0xIjoKICAgICAgICAgICAgICAgIHJldHVybiAiLTEiCiAg + ICAgICAgICAgIGlmIGZzaWQgIT0gcmd3X2ZzaWQ6CiAgICAgICAgICAgICAgICBzeXMuc3RkZXJy + LndyaXRlKAogICAgICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHJndyBFbmRwb2ludCwg + J3tzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludH0nLCBpcyBpbnZhbGlkLiBXZSBhcmUgdmFs + aWRhdGluZyBieSBjYWxsaW5nIHRoZSBhZG1pbm9wcyBhcGkgdGhyb3VnaCByZ3ctZW5kcG9pbnQg + YW5kIHZhbGlkYXRpbmcgdGhlIGNsdXN0ZXJfaWQgJ3tyZ3dfZnNpZH0nIGlzIGVxdWFsIHRvIHRo + ZSBjZXBoIGNsdXN0ZXIgZnNpZCAne2ZzaWR9JyIKICAgICAgICAgICAgICAgICkKICAgICAgICAg + ICAgICAgIHJldHVybiAiLTEiCgogICAgICAgICMgY2hlY2sgaWYgdGhlIHJndyBlbmRwb2ludCBw + b29sIGV4aXN0CiAgICAgICAgIyBvbmx5IHZhbGlkYXRlIGlmIHJnd19wb29sX3ByZWZpeCBpcyBw + YXNzZWQgZWxzZSBpdCB3aWxsIHRha2UgZGVmYXVsdCB2YWx1ZSBhbmQgd2UgZG9uJ3QgY3JlYXRl + IHRoZXNlIGRlZmF1bHQgcG9vbHMKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29s + X3ByZWZpeCAhPSAiZGVmYXVsdCI6CiAgICAgICAgICAgIHJnd19wb29sc190b192YWxpZGF0ZSA9 + IFsKICAgICAgICAgICAgICAgIGYie3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5y + Z3cubWV0YSIsCiAgICAgICAgICAgICAgICAiLnJndy5yb290IiwKICAgICAgICAgICAgICAgIGYi + e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuY29udHJvbCIsCiAgICAgICAg + ICAgICAgICBmIntzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmxvZyIsCiAg + ICAgICAgICAgIF0KICAgICAgICAgICAgZm9yIF9yZ3dfcG9vbF90b192YWxpZGF0ZSBpbiByZ3df + cG9vbHNfdG9fdmFsaWRhdGU6CiAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5jbHVzdGVyLnBv + b2xfZXhpc3RzKF9yZ3dfcG9vbF90b192YWxpZGF0ZSk6CiAgICAgICAgICAgICAgICAgICAgc3lz + LnN0ZGVyci53cml0ZSgKICAgICAgICAgICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcG9v + bCwgJ3tfcmd3X3Bvb2xfdG9fdmFsaWRhdGV9JywgZG9lcyBub3QgZXhpc3QiCiAgICAgICAgICAg + ICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgIHJldHVybiAiLTEiCgogICAgICAgIHJldHVy + biAiIgoKICAgIGRlZiB2YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKHNlbGYsIHJnd19tdWx0aXNpdGVf + Y29uZmlnX25hbWUsIHJnd19tdWx0aXNpdGVfY29uZmlnKToKICAgICAgICBpZiByZ3dfbXVsdGlz + aXRlX2NvbmZpZyAhPSAiIjoKICAgICAgICAgICAgY21kID0gWwogICAgICAgICAgICAgICAgInJh + ZG9zZ3ctYWRtaW4iLAogICAgICAgICAgICAgICAgcmd3X211bHRpc2l0ZV9jb25maWcsCiAgICAg + ICAgICAgICAgICAiZ2V0IiwKICAgICAgICAgICAgICAgICItLXJndy0iICsgcmd3X211bHRpc2l0 + ZV9jb25maWcsCiAgICAgICAgICAgICAgICByZ3dfbXVsdGlzaXRlX2NvbmZpZ19uYW1lLAogICAg + ICAgICAgICBdCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIF8gPSBzdWJwcm9jZXNz + LmNoZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgICAgIGV4 + Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAg + ICAgICAgZXJyX21zZyA9ICgKICAgICAgICAgICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRl + IGNvbW1hbmQge2NtZH0uIE91dHB1dDoge2V4ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAg + ICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5zdGRl + cnJ9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShl + cnJfbXNnKQogICAgICAgICAgICAgICAgcmV0dXJuICItMSIKICAgICAgICByZXR1cm4gIiIKCiAg + ICBkZWYgY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoc2VsZiwgdmFsdWUpOgogICAg + ICAgIHJldHVybiB2YWx1ZS5zcGxpdCgiLCIpCgogICAgZGVmIHJhaXNlX2V4Y2VwdGlvbl9pZl9h + bnlfdG9wb2xvZ3lfZmxhZ19pc19taXNzaW5nKHNlbGYpOgogICAgICAgIGlmICgKICAgICAgICAg + ICAgKAogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9wb29scyAhPSAi + IgogICAgICAgICAgICAgICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFy + c2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsID09ICIiCiAgICAgICAgICAgICAgICAg + ICAgb3Igc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMgPT0g + IiIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgKQogICAgICAgICAgICBvciAoCiAgICAg + ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVs + ICE9ICIiCiAgICAgICAgICAgICAgICBhbmQgKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2Fy + Z19wYXJzZXIudG9wb2xvZ3lfcG9vbHMgPT0gIiIKICAgICAgICAgICAgICAgICAgICBvciBzZWxm + Ll9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX3ZhbHVlcyA9PSAiIgogICAgICAg + ICAgICAgICAgKQogICAgICAgICAgICApCiAgICAgICAgICAgIG9yICgKICAgICAgICAgICAgICAg + IHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFpbHVyZV9kb21haW5fdmFsdWVzICE9ICIiCiAg + ICAgICAgICAgICAgICBhbmQgKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIu + dG9wb2xvZ3lfcG9vbHMgPT0gIiIKICAgICAgICAgICAgICAgICAgICBvciBzZWxmLl9hcmdfcGFy + c2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsID09ICIiCiAgICAgICAgICAgICAgICAp + CiAgICAgICAgICAgICkKICAgICAgICApOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls + dXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgInByb3ZpZGUgYWxsIHRoZSB0b3BvbG9neSBm + bGFncyAtLXRvcG9sb2d5LXBvb2xzLCAtLXRvcG9sb2d5LWZhaWx1cmUtZG9tYWluLWxhYmVsLCAt + LXRvcG9sb2d5LWZhaWx1cmUtZG9tYWluLXZhbHVlcyIKICAgICAgICAgICAgKQoKICAgIGRlZiB2 + YWxpZGF0ZV90b3BvbG9neV92YWx1ZXMoc2VsZiwgdG9wb2xvZ3lfcG9vbHMsIHRvcG9sb2d5X2Zk + KToKICAgICAgICBpZiBsZW4odG9wb2xvZ3lfcG9vbHMpICE9IGxlbih0b3BvbG9neV9mZCk6CiAg + ICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAg + ICBmIlRoZSBwcm92aWRlZCB0b3BvbG9neSBwb29scywgJ3t0b3BvbG9neV9wb29sc30nLCBhbmQg + IgogICAgICAgICAgICAgICAgZiJ0b3BvbG9neSBmYWlsdXJlIGRvbWFpbiwgJ3t0b3BvbG9neV9m + ZH0nLCIKICAgICAgICAgICAgICAgIGYiYXJlIG9mIGRpZmZlcmVudCBsZW5ndGgsICd7bGVuKHRv + cG9sb2d5X3Bvb2xzKX0nIGFuZCAne2xlbih0b3BvbG9neV9mZCl9JyByZXNwY3RpdmVseSIKICAg + ICAgICAgICAgKQogICAgICAgIHJldHVybgoKICAgIGRlZiB2YWxpZGF0ZV90b3BvbG9neV9yYmRf + cG9vbHMoc2VsZiwgdG9wb2xvZ3lfcmJkX3Bvb2xzKToKICAgICAgICBmb3IgcG9vbCBpbiB0b3Bv + bG9neV9yYmRfcG9vbHM6CiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfcmJkX3Bvb2wocG9vbCkK + CiAgICBkZWYgaW5pdF90b3BvbG9neV9yYmRfcG9vbHMoc2VsZiwgdG9wb2xvZ3lfcmJkX3Bvb2xz + KToKICAgICAgICBmb3IgcG9vbCBpbiB0b3BvbG9neV9yYmRfcG9vbHM6CiAgICAgICAgICAgIHNl + bGYuaW5pdF9yYmRfcG9vbChwb29sKQoKICAgICMgdGhpcyB3aWxsIHJldHVybiB0aGUgZmluYWwg + YXJncyB0aGF0IHNjcmlwdCB1c2VzIHRvIHByb2Nlc3MKICAgICMgdGhlIHByaW9yaXR5IHRvIHNl + dCBhIHBhcnRpY3VsYXIgdmFsdWUgaXMsCiAgICAjIGNvbW1hbmQtbGluZS1hcmdzID4gY29uZmln + LmluaSBmaWxlIHZhbHVlcyA+IGRlZmF1bHQgdmFsdWVzCiAgICBkZWYgZ2V0RmluYWxVc2VkQXJn + cyhzZWxmKToKICAgICAgICBhcmd1bWVudCA9IGYiW0NvbmZpZ3VyYXRpb25zXVxuIgogICAgICAg + IGZvciBhcmcgaW4gdmFycyhzZWxmLl9hcmdfcGFyc2VyKToKICAgICAgICAgICAgaWYgc3RyKGdl + dGF0dHIoc2VsZi5fYXJnX3BhcnNlciwgYXJnKSk6CiAgICAgICAgICAgICAgICAjIHB5dGhvbiB0 + cmVhdHMgZmxhZy1uYW1lIGFzIGZsYWdfbmFtZSBpbnRlcm5hbGx5LCBzbyBjb252ZXJ0aW5nIGJh + Y2sgdG8gZmxhZy1uYW1lLAogICAgICAgICAgICAgICAgIyBzbyB3ZSBjYW4gZ2V0IHRob3NlIHZh + bHVlcyBmcm9tIGNvbmZpZyBmaWxlCiAgICAgICAgICAgICAgICBhcmdWYWx1ZSA9IGFyZy5yZXBs + YWNlKCJfIiwgIi0iKQogICAgICAgICAgICAgICAgIyBkbyBub3QgYWRkIHRoZSBjb25maWctZmls + ZSBmbGFnIGFuZCBhbHNvIG5vdCBhZGQgdGhlIGJvb2xlYW4gZmxhZ3Mgd2hpY2ggYXJlIHNldCB0 + byBGYWxzZQogICAgICAgICAgICAgICAgIyBiZWNhdXNlIGNvbmZpZy5pbmkgZmlsZSB0cmVhdHMg + Ym9vbGVhbiBmbGFncyBhcyBUcnVlIGFsd2F5cwogICAgICAgICAgICAgICAgaWYgKAogICAgICAg + ICAgICAgICAgICAgIGFyZ1ZhbHVlICE9ICJjb25maWctZmlsZSIKICAgICAgICAgICAgICAgICAg + ICBhbmQgZ2V0YXR0cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpICE9IEZhbHNlCiAgICAgICAgICAg + ICAgICApOgogICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50ICs9IGYie2FyZ1ZhbHVlfSA9IHtz + dHIoZ2V0YXR0cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpKX1cbiIKICAgICAgICByZXR1cm4gYXJn + dW1lbnQKCiAgICBkZWYgX2dlbl9vdXRwdXRfbWFwKHNlbGYpOgogICAgICAgIGlmIHNlbGYub3V0 + X21hcDoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgIyBzdXBwb3J0IGxlZ2FjeSBmbGFnIHdp + dGggdXBncmFkZXMKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmNsdXN0ZXJfbmFtZToKICAg + ICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3Bh + cnNlci5jbHVzdGVyX25hbWUKICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25h + bWUgPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZS5sb3dl + cigpCiAgICAgICAgKSAgIyBhbHdheXMgY29udmVydCBjbHVzdGVyIG5hbWUgdG8gbG93ZXJjYXNl + IGNoYXJhY3RlcnMKICAgICAgICBzZWxmLnZhbGlkYXRlX3JiZF9wb29sKHNlbGYuX2FyZ19wYXJz + ZXIucmJkX2RhdGFfcG9vbF9uYW1lKQogICAgICAgIHNlbGYuaW5pdF9yYmRfcG9vbChzZWxmLl9h + cmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZSkKICAgICAgICBzZWxmLnZhbGlkYXRlX3JhZG9z + X25hbWVzcGFjZSgpCiAgICAgICAgc2VsZi5fZXhjbHVkZWRfa2V5cy5hZGQoIks4U19DTFVTVEVS + X05BTUUiKQogICAgICAgIHNlbGYuZ2V0X2NlcGhmc19kYXRhX3Bvb2xfZGV0YWlscygpCiAgICAg + ICAgIyBkb3VibGUgc3RyaW5nIG5lZWRlZCBmb3IgdXBzdHJlYW0gZXhwb3J0cyBvZiBmbGFncwog + ICAgICAgIHNlbGYub3V0X21hcFsiQVJHUyJdID0gZicie3NlbGYuZ2V0RmluYWxVc2VkQXJncygp + fSInCiAgICAgICAgc2VsZi5vdXRfbWFwWyJOQU1FU1BBQ0UiXSA9IHNlbGYuX2FyZ19wYXJzZXIu + bmFtZXNwYWNlCiAgICAgICAgc2VsZi5vdXRfbWFwWyJLOFNfQ0xVU1RFUl9OQU1FIl0gPSBzZWxm + Ll9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tf + RVhURVJOQUxfRlNJRCJdID0gc2VsZi5nZXRfZnNpZCgpCiAgICAgICAgc2VsZi5vdXRfbWFwWyJS + T09LX0VYVEVSTkFMX1VTRVJOQU1FIl0gPSBzZWxmLnJ1bl9hc191c2VyCiAgICAgICAgc2VsZi5v + dXRfbWFwWyJST09LX0VYVEVSTkFMX0NFUEhfTU9OX0RBVEEiXSA9IHNlbGYuZ2V0X2NlcGhfZXh0 + ZXJuYWxfbW9uX2RhdGEoKQogICAgICAgIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5BTF9VU0VS + X1NFQ1JFVCJdID0gc2VsZi5jcmVhdGVfY2hlY2tlcktleSgKICAgICAgICAgICAgImNsaWVudC5o + ZWFsdGhjaGVja2VyIgogICAgICAgICkKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJO + QUxfREFTSEJPQVJEX0xJTksiXSA9IHNlbGYuZ2V0X2NlcGhfZGFzaGJvYXJkX2xpbmsoKQogICAg + ICAgICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX05PREVfU0VDUkVUIl0sCiAg + ICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FIl0sCiAgICAg + ICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNsaWVudC5jc2ktcmJkLW5v + ZGUiKQogICAgICAgICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lP + TkVSX1NFQ1JFVCJdLAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9SQkRfUFJPVklTSU9O + RVJfU0VDUkVUX05BTUUiXSwKICAgICAgICApID0gc2VsZi5jcmVhdGVfY2VwaENTSUtleXJpbmdf + dXNlcigiY2xpZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiKQogICAgICAgIHNlbGYub3V0X21hcFsi + Q0VQSEZTX1BPT0xfTkFNRSJdID0gc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25h + bWUKICAgICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19NRVRBREFUQV9QT09MX05BTUUiXSA9ICgK + ICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfbWV0YWRhdGFfcG9vbF9uYW1lCiAg + ICAgICAgKQogICAgICAgIHNlbGYub3V0X21hcFsiQ0VQSEZTX0ZTX05BTUUiXSA9IHNlbGYuX2Fy + Z19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgIHNlbGYub3V0X21hcFsiUkVT + VFJJQ1RFRF9BVVRIX1BFUk1JU1NJT04iXSA9ICgKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl + ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbgogICAgICAgICkKICAgICAgICBzZWxmLm91dF9t + YXBbIlJBRE9TX05BTUVTUEFDRSJdID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UK + ICAgICAgICBzZWxmLm91dF9tYXBbIlNVQlZPTFVNRV9HUk9VUCJdID0gc2VsZi5fYXJnX3BhcnNl + ci5zdWJ2b2x1bWVfZ3JvdXAKICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9T + RUNSRVQiXSA9ICIiCiAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVS + X1NFQ1JFVCJdID0gIiIKICAgICAgICAjIGNyZWF0ZSBDZXBoRlMgbm9kZSBhbmQgcHJvdmlzaW9u + ZXIga2V5cmluZyBvbmx5IHdoZW4gTURTIGV4aXN0cwogICAgICAgIGlmIHNlbGYub3V0X21hcFsi + Q0VQSEZTX0ZTX05BTUUiXSBhbmQgc2VsZi5vdXRfbWFwWyJDRVBIRlNfUE9PTF9OQU1FIl06CiAg + ICAgICAgICAgICgKICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RF + X1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVf + U0VDUkVUX05BTUUiXSwKICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5n + X3VzZXIoImNsaWVudC5jc2ktY2VwaGZzLW5vZGUiKQogICAgICAgICAgICAoCiAgICAgICAgICAg + ICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUIl0sCiAgICAg + ICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05B + TUUiXSwKICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNs + aWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIikKICAgICAgICAgICAgIyBjcmVhdGUgdGhlIGRl + ZmF1bHQgImNzaSIgc3Vidm9sdW1lZ3JvdXAKICAgICAgICAgICAgc2VsZi5nZXRfb3JfY3JlYXRl + X3N1YnZvbHVtZV9ncm91cCgKICAgICAgICAgICAgICAgICJjc2kiLCBzZWxmLl9hcmdfcGFyc2Vy + LmNlcGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICAgICAgKQogICAgICAgICAgICAjIHBpbiB0 + aGUgZGVmYXVsdCAiY3NpIiBzdWJ2b2x1bWVncm91cAogICAgICAgICAgICBzZWxmLnBpbl9zdWJ2 + b2x1bWUoCiAgICAgICAgICAgICAgICAiY3NpIiwgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls + ZXN5c3RlbV9uYW1lLCAiZGlzdHJpYnV0ZWQiLCAiMSIKICAgICAgICAgICAgKQogICAgICAgICAg + ICBpZiBzZWxmLm91dF9tYXBbIlNVQlZPTFVNRV9HUk9VUCJdOgogICAgICAgICAgICAgICAgc2Vs + Zi5nZXRfb3JfY3JlYXRlX3N1YnZvbHVtZV9ncm91cCgKICAgICAgICAgICAgICAgICAgICBzZWxm + Ll9hcmdfcGFyc2VyLnN1YnZvbHVtZV9ncm91cCwKICAgICAgICAgICAgICAgICAgICBzZWxmLl9h + cmdfcGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgICAgICApCiAgICAg + ICAgICAgICAgICBzZWxmLnBpbl9zdWJ2b2x1bWUoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5f + YXJnX3BhcnNlci5zdWJ2b2x1bWVfZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJn + X3BhcnNlci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lLAogICAgICAgICAgICAgICAgICAgICJkaXN0 + cmlidXRlZCIsCiAgICAgICAgICAgICAgICAgICAgIjEiLAogICAgICAgICAgICAgICAgKQogICAg + ICAgIHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl0gPSAiIgogICAgICAgIHNlbGYub3V0X21h + cFsiTU9OSVRPUklOR19FTkRQT0lOVCJdID0gIiIKICAgICAgICBzZWxmLm91dF9tYXBbIk1PTklU + T1JJTkdfRU5EUE9JTlRfUE9SVCJdID0gIiIKICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNl + ci5za2lwX21vbml0b3JpbmdfZW5kcG9pbnQ6CiAgICAgICAgICAgICgKICAgICAgICAgICAgICAg + IHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVCJdLAogICAgICAgICAgICAgICAgc2Vs + Zi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UX1BPUlQiXSwKICAgICAgICAgICAgKSA9IHNl + bGYuZ2V0X2FjdGl2ZV9hbmRfc3RhbmRieV9tZ3JzKCkKICAgICAgICBzZWxmLm91dF9tYXBbIlJC + RF9QT09MX05BTUUiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAg + ICAgc2VsZi5vdXRfbWFwWyJSQkRfTUVUQURBVEFfRUNfUE9PTF9OQU1FIl0gPSAoCiAgICAgICAg + ICAgIHNlbGYudmFsaWRhdGVfcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZSgpCiAgICAgICAgKQog + ICAgICAgIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfUE9PTFMiXSA9IHNlbGYuX2FyZ19wYXJzZXIu + dG9wb2xvZ3lfcG9vbHMKICAgICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9N + QUlOX0xBQkVMIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFp + bHVyZV9kb21haW5fbGFiZWwKICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9H + WV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXSA9ICgKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl + ci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMKICAgICAgICApCiAgICAgICAgaWYgKAog + ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bvb2xzICE9ICIiCiAgICAgICAg + ICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsICE9 + ICIiCiAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9t + YWluX3ZhbHVlcyAhPSAiIgogICAgICAgICk6CiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfdG9w + b2xvZ3lfdmFsdWVzKAogICAgICAgICAgICAgICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFyYXRl + ZF90b19hcnJheShzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0pLAogICAgICAgICAgICAg + ICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFyYXRlZF90b19hcnJheSgKICAgICAgICAgICAgICAg + ICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlOX1ZBTFVFUyJdCiAgICAg + ICAgICAgICAgICApLAogICAgICAgICAgICApCiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfdG9w + b2xvZ3lfcmJkX3Bvb2xzKAogICAgICAgICAgICAgICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFy + YXRlZF90b19hcnJheShzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0pCiAgICAgICAgICAg + ICkKICAgICAgICAgICAgc2VsZi5pbml0X3RvcG9sb2d5X3JiZF9wb29scygKICAgICAgICAgICAg + ICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoc2VsZi5vdXRfbWFwWyJU + T1BPTE9HWV9QT09MUyJdKQogICAgICAgICAgICApCiAgICAgICAgZWxzZToKICAgICAgICAgICAg + c2VsZi5yYWlzZV9leGNlcHRpb25faWZfYW55X3RvcG9sb2d5X2ZsYWdfaXNfbWlzc2luZygpCgog + ICAgICAgIHNlbGYub3V0X21hcFsiUkdXX1BPT0xfUFJFRklYIl0gPSBzZWxmLl9hcmdfcGFyc2Vy + LnJnd19wb29sX3ByZWZpeAogICAgICAgIHNlbGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl0gPSAi + IgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50OgogICAgICAgICAgICBp + ZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgICAgICBzZWxmLmNyZWF0ZV9y + Z3dfYWRtaW5fb3BzX3VzZXIoKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgaWYg + KAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUgIT0g + IiIKICAgICAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5yZ3dfem9uZWdyb3Vw + X25hbWUgIT0gIiIKICAgICAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5yZ3df + em9uZV9uYW1lICE9ICIiCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIGVy + ciA9IHNlbGYudmFsaWRhdGVfcmd3X211bHRpc2l0ZSgKICAgICAgICAgICAgICAgICAgICAgICAg + c2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVhbG1fbmFtZSwgInJlYWxtIgogICAgICAgICAgICAgICAg + ICAgICkKICAgICAgICAgICAgICAgICAgICBlcnIgPSBzZWxmLnZhbGlkYXRlX3Jnd19tdWx0aXNp + dGUoCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91 + cF9uYW1lLCAiem9uZWdyb3VwIgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAg + ICAgICBlcnIgPSBzZWxmLnZhbGlkYXRlX3Jnd19tdWx0aXNpdGUoCiAgICAgICAgICAgICAgICAg + ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwgInpvbmUiCiAgICAgICAgICAg + ICAgICAgICAgKQoKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAgICBzZWxm + Ll9hcmdfcGFyc2VyLnJnd19yZWFsbV9uYW1lID09ICIiCiAgICAgICAgICAgICAgICAgICAgYW5k + IHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lID09ICIiCiAgICAgICAgICAgICAg + ICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSA9PSAiIgogICAgICAgICAg + ICAgICAgKSBvciAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVh + bG1fbmFtZSAhPSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnJn + d196b25lZ3JvdXBfbmFtZSAhPSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdf + cGFyc2VyLnJnd196b25lX25hbWUgIT0gIiIKICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAg + ICAgICAgICAgKAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19BRE1J + Tl9PUFNfVVNFUl9BQ0NFU1NfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYub3V0 + X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JFVF9LRVkiXSwKICAgICAgICAgICAgICAgICAg + ICAgICAgaW5mb19jYXBfc3VwcG9ydGVkLAogICAgICAgICAgICAgICAgICAgICAgICBlcnIsCiAg + ICAgICAgICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX3Jnd19hZG1pbl9vcHNfdXNlcigpCiAg + ICAgICAgICAgICAgICAgICAgZXJyID0gc2VsZi52YWxpZGF0ZV9yZ3dfZW5kcG9pbnQoaW5mb19j + YXBfc3VwcG9ydGVkKQogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3 + X3Rsc19jZXJ0X3BhdGg6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiUkdX + X1RMU19DRVJUIl0gPSAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnZhbGlkYXRl + X3Jnd19lbmRwb2ludF90bHNfY2VydCgpCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAg + ICAgICAgICAgICAgICAjIGlmIHRoZXJlIGlzIG5vIGVycm9yLCBzZXQgdGhlIFJHV19FTkRQT0lO + VAogICAgICAgICAgICAgICAgICAgIGlmIGVyciAhPSAiLTEiOgogICAgICAgICAgICAgICAgICAg + ICAgICBzZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdID0gc2VsZi5fYXJnX3BhcnNlci5yZ3df + ZW5kcG9pbnQKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgZXJyID0g + IlBsZWFzZSBwcm92aWRlIGFsbCB0aGUgUkdXIG11bHRpc2l0ZSBwYXJhbWV0ZXJzIG9yIG5vbmUg + b2YgdGhlbSIKICAgICAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycikKCiAgICBk + ZWYgZ2VuX3NoZWxsX291dChzZWxmKToKICAgICAgICBzZWxmLl9nZW5fb3V0cHV0X21hcCgpCiAg + ICAgICAgc2hPdXRJTyA9IFN0cmluZ0lPKCkKICAgICAgICBmb3IgaywgdiBpbiBzZWxmLm91dF9t + YXAuaXRlbXMoKToKICAgICAgICAgICAgaWYgdiBhbmQgayBub3QgaW4gc2VsZi5fZXhjbHVkZWRf + a2V5czoKICAgICAgICAgICAgICAgIHNoT3V0SU8ud3JpdGUoZiJleHBvcnQge2t9PXt2fXtMSU5F + U0VQfSIpCiAgICAgICAgc2hPdXQgPSBzaE91dElPLmdldHZhbHVlKCkKICAgICAgICBzaE91dElP + LmNsb3NlKCkKICAgICAgICByZXR1cm4gc2hPdXQKCiAgICBkZWYgZ2VuX2pzb25fb3V0KHNlbGYp + OgogICAgICAgIHNlbGYuX2dlbl9vdXRwdXRfbWFwKCkKICAgICAgICBpZiBzZWxmLl9hcmdfcGFy + c2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiAiIgogICAgICAgIGpzb25fb3V0ID0gWwog + ICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJleHRlcm5hbC1jbHVzdGVyLXVz + ZXItY29tbWFuZCIsCiAgICAgICAgICAgICAgICAia2luZCI6ICJDb25maWdNYXAiLAogICAgICAg + ICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgImFyZ3MiOiBzZWxmLm91dF9t + YXBbIkFSR1MiXSwKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAg + IHsKICAgICAgICAgICAgICAgICJuYW1lIjogInJvb2stY2VwaC1tb24tZW5kcG9pbnRzIiwKICAg + ICAgICAgICAgICAgICJraW5kIjogIkNvbmZpZ01hcCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6 + IHsKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5B + TF9DRVBIX01PTl9EQVRBIl0sCiAgICAgICAgICAgICAgICAgICAgIm1heE1vbklkIjogIjAiLAog + ICAgICAgICAgICAgICAgICAgICJtYXBwaW5nIjogInt9IiwKICAgICAgICAgICAgICAgIH0sCiAg + ICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogInJvb2st + Y2VwaC1tb24iLAogICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAg + ICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICJhZG1pbi1zZWNyZXQiOiAiYWRtaW4t + c2VjcmV0IiwKICAgICAgICAgICAgICAgICAgICAiZnNpZCI6IHNlbGYub3V0X21hcFsiUk9PS19F + WFRFUk5BTF9GU0lEIl0sCiAgICAgICAgICAgICAgICAgICAgIm1vbi1zZWNyZXQiOiAibW9uLXNl + Y3JldCIsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAg + ICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtb3BlcmF0b3ItY3JlZHMiLAogICAgICAg + ICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAgICJkYXRhIjogewogICAg + ICAgICAgICAgICAgICAgICJ1c2VySUQiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfVVNF + Uk5BTUUiXSwKICAgICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiUk9P + S19FWFRFUk5BTF9VU0VSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAg + fSwKICAgICAgICBdCgogICAgICAgICMgaWYgJ01PTklUT1JJTkdfRU5EUE9JTlQnIGV4aXN0cywg + dGhlbiBvbmx5IGFkZCAnbW9uaXRvcmluZy1lbmRwb2ludCcgdG8gQ2x1c3RlcgogICAgICAgIGlm + ICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UIl0KICAgICAg + ICAgICAgYW5kIHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0KICAgICAg + ICApOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAg + ICAgICAgICAgICAgICAgIm5hbWUiOiAibW9uaXRvcmluZy1lbmRwb2ludCIsCiAgICAgICAgICAg + ICAgICAgICAgImtpbmQiOiAiQ2VwaENsdXN0ZXIiLAogICAgICAgICAgICAgICAgICAgICJkYXRh + IjogewogICAgICAgICAgICAgICAgICAgICAgICAiTW9uaXRvcmluZ0VuZHBvaW50Ijogc2VsZi5v + dXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJN + b25pdG9yaW5nUG9ydCI6IHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0s + CiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQoK + ICAgICAgICAjIGlmICdDU0lfUkJEX05PREVfU0VDUkVUJyBleGlzdHMsIHRoZW4gb25seSBhZGQg + J3Jvb2stY3NpLXJiZC1wcm92aXNpb25lcicgU2VjcmV0CiAgICAgICAgaWYgKAogICAgICAgICAg + ICBzZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2Vs + Zi5vdXRfbWFwWyJDU0lfUkJEX05PREVfU0VDUkVUX05BTUUiXQogICAgICAgICk6CiAgICAgICAg + ICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAg + ICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUn + XX0iLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAg + ICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VySUQiOiBzZWxmLm91 + dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAg + ICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVCJdLAogICAgICAg + ICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAj + IGlmICdDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdy + b29rLWNzaS1yYmQtcHJvdmlzaW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAg + c2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCJdCiAgICAgICAgICAgIGFu + ZCBzZWxmLm91dF9tYXBbIkNTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXQogICAgICAg + ICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAg + ICAgICAgICAgICAgICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BST1ZJ + U0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTZWNy + ZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAg + ICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1F + Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VyS2V5Ijogc2VsZi5vdXRfbWFwWyJDU0lf + UkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAg + ICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdDU0lfQ0VQSEZTX1BST1ZJU0lP + TkVSX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNzaS1jZXBoZnMtcHJvdmlz + aW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lf + Q0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVCJdCiAgICAgICAgICAgIGFuZCBzZWxmLm91dF9tYXBb + IkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXQogICAgICAgICk6CiAgICAgICAg + ICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAg + ICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NF + Q1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAg + ICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5J + RCI6IHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSJdLAog + ICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5LZXkiOiBzZWxmLm91dF9tYXBbIkNTSV9DRVBI + RlNfUFJPVklTSU9ORVJfU0VDUkVUIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAg + ICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ0NTSV9DRVBIRlNfTk9ERV9TRUNS + RVQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktY2VwaGZzLW5vZGUnIFNlY3JldAog + ICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVfU0VD + UkVUIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JF + VF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAg + ICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBmInJvb2ste3NlbGYub3V0X21h + cFsnQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAi + a2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAg + ICAgICAgICAgICAgICAiYWRtaW5JRCI6IHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NF + Q1JFVF9OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pbktleSI6IHNlbGYub3V0 + X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAg + ICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdST09LX0VYVEVSTkFM + X0RBU0hCT0FSRF9MSU5LJyBleGlzdHMsIHRoZW4gb25seSBhZGQgJ3Jvb2stY2VwaC1kYXNoYm9h + cmQtbGluaycgU2VjcmV0CiAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0RB + U0hCT0FSRF9MSU5LIl06CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAg + ICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtZGFzaGJvYXJkLWxp + bmsiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAg + ICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VySUQiOiAiY2VwaC1k + YXNoYm9hcmQtbGluayIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VyS2V5Ijogc2VsZi5v + dXRfbWFwWyJST09LX0VYVEVSTkFMX0RBU0hCT0FSRF9MSU5LIl0sCiAgICAgICAgICAgICAgICAg + ICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ1JBRE9T + X05BTUVTUEFDRScgZXhpc3RzLCB0aGVuIG9ubHkgYWRkIHRoZSAiUkFET1NfTkFNRVNQQUNFIiBu + YW1lc3BhY2UKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiUkFET1NfTkFN + RVNQQUNFIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsiUkVTVFJJQ1RFRF9BVVRIX1BF + Uk1JU1NJT04iXQogICAgICAgICAgICBhbmQgbm90IHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRB + X0VDX1BPT0xfTkFNRSJdCiAgICAgICAgKToKICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAog + ICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICJuYW1lIjogInJhZG9zLW5hbWVz + cGFjZSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiQ2VwaEJsb2NrUG9vbFJhZG9zTmFt + ZXNwYWNlIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAg + ICAgICAgInJhZG9zTmFtZXNwYWNlTmFtZSI6IHNlbGYub3V0X21hcFsiUkFET1NfTkFNRVNQQUNF + Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9P + TF9OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAg + ICAgICAgKQogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAg + ICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQtcmFkb3MtbmFtZXNwYWNlIiwKICAg + ICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAogICAgICAgICAgICAgICAg + ICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21h + cFsiUkJEX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu + azhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NT + SV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAg + ICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhwYW5kLXNlY3JldC1uYW1lIjogZiJy + b29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAog + ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL25vZGUtc3RhZ2Utc2Vj + cmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1F + J119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAg + ICApCiAgICAgICAgZWxzZToKICAgICAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJSQkRfTUVUQURB + VEFfRUNfUE9PTF9OQU1FIl06CiAgICAgICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAg + ICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJjZXBoLXJi + ZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAg + ICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAg + ImRhdGFQb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1FIl0sCiAgICAgICAgICAgICAg + ICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xf + TkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9w + cm92aXNpb25lci1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BS + T1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJj + c2kuc3RvcmFnZS5rOHMuaW8vY29udHJvbGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2st + e3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAg + ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL25vZGUtc3RhZ2Utc2Vj + cmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1F + J119IiwKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICB9CiAg + ICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBqc29uX291 + dC5hcHBlbmQoCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAi + bmFtZSI6ICJjZXBoLXJiZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3Jh + Z2VDbGFzcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAg + ICAgICAgICAgICAgICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9QT09MX05BTUUiXSwKICAg + ICAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXIt + c2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9T + RUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu + azhzLmlvL2NvbnRyb2xsZXItZXhwYW5kLXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9t + YXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAg + ICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9ub2RlLXN0YWdlLXNlY3JldC1uYW1lIjog + ZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAg + ICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAg + ICAgKQoKICAgICAgICAjIGlmICdUT1BPTE9HWV9QT09MUycsICdUT1BPTE9HWV9GQUlMVVJFX0RP + TUFJTl9MQUJFTCcsICdUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMnICBleGlzdHMsCiAg + ICAgICAgIyB0aGVuIG9ubHkgYWRkICd0b3BvbG9neScgU3RvcmFnZUNsYXNzCiAgICAgICAgaWYg + KAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0KICAgICAgICAgICAg + YW5kIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fTEFCRUwiXQogICAgICAg + ICAgICBhbmQgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXQog + ICAgICAgICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsK + ICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJjZXBoLXJiZC10b3BvbG9neSIsCiAgICAgICAg + ICAgICAgICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwKICAgICAgICAgICAgICAgICAgICAi + ZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgInRvcG9sb2d5RmFpbHVyZURvbWFpbkxh + YmVsIjogc2VsZi5vdXRfbWFwWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRPUE9MT0dZ + X0ZBSUxVUkVfRE9NQUlOX0xBQkVMIgogICAgICAgICAgICAgICAgICAgICAgICBdLAogICAgICAg + ICAgICAgICAgICAgICAgICAidG9wb2xvZ3lGYWlsdXJlRG9tYWluVmFsdWVzIjogc2VsZi5vdXRf + bWFwWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlO + X1ZBTFVFUyIKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgICAg + ICAgInRvcG9sb2d5UG9vbHMiOiBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0sCiAgICAg + ICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXItc2VjcmV0 + LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRf + TkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vY29u + dHJvbGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JC + RF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJj + c2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v + dXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAg + IH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgIyBpZiAnQ0VQSEZT + X0ZTX05BTUUnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAnY2VwaGZzJyBTdG9yYWdlQ2xhc3MKICAg + ICAgICBpZiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl06CiAgICAgICAgICAgIGpzb25f + b3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6 + ICJjZXBoZnMiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAg + ICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJmc05h + bWUiOiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAg + ICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJDRVBIRlNfUE9PTF9OQU1FIl0sCiAgICAgICAgICAg + ICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXItc2VjcmV0LW5hbWUi + OiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFN + RSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vY29udHJv + bGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhG + U19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJj + c2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v + dXRfbWFwWydDU0lfQ0VQSEZTX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAg + ICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdSR1df + RU5EUE9JTlQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAnY2VwaC1yZ3cnIFN0b3JhZ2VDbGFzcwog + ICAgICAgIGlmIHNlbGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl06CiAgICAgICAgICAgIGpzb25f + b3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6 + ICJjZXBoLXJndyIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwK + ICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImVu + ZHBvaW50Ijogc2VsZi5vdXRfbWFwWyJSR1dfRU5EUE9JTlQiXSwKICAgICAgICAgICAgICAgICAg + ICAgICAgInBvb2xQcmVmaXgiOiBzZWxmLm91dF9tYXBbIlJHV19QT09MX1BSRUZJWCJdLAogICAg + ICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAg + ICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAg + ICAgICJuYW1lIjogInJndy1hZG1pbi1vcHMtdXNlciIsCiAgICAgICAgICAgICAgICAgICAgImtp + bmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAg + ICAgICAgICAgICAgImFjY2Vzc0tleSI6IHNlbGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VS + X0FDQ0VTU19LRVkiXSwKICAgICAgICAgICAgICAgICAgICAgICAgInNlY3JldEtleSI6IHNlbGYu + b3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JFVF9LRVkiXSwKICAgICAgICAgICAgICAg + ICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUkdX + X1RMU19DRVJUJyBleGlzdHMsIHRoZW4gb25seSBhZGQgdGhlICJjZXBoLXJndy10bHMtY2VydCIg + c2VjcmV0CiAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJSR1dfVExTX0NFUlQiXToKICAgICAgICAg + ICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAg + ICJuYW1lIjogImNlcGgtcmd3LXRscy1jZXJ0IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6 + ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAg + ICAgICAgICAiY2VydCI6IHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl0sCiAgICAgICAgICAg + ICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQoKICAgICAgICByZXR1 + cm4ganNvbi5kdW1wcyhqc29uX291dCkgKyBMSU5FU0VQCgogICAgZGVmIHVwZ3JhZGVfdXNlcnNf + cGVybWlzc2lvbnMoc2VsZik6CiAgICAgICAgdXNlcnMgPSBbCiAgICAgICAgICAgICJjbGllbnQu + Y3NpLWNlcGhmcy1ub2RlIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv + bmVyIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktcmJkLW5vZGUiLAogICAgICAgICAgICAiY2xp + ZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiLAogICAgICAgICAgICAiY2xpZW50LmhlYWx0aGNoZWNr + ZXIiLAogICAgICAgIF0KICAgICAgICBpZiBzZWxmLnJ1bl9hc191c2VyICE9ICIiIGFuZCBzZWxm + LnJ1bl9hc191c2VyIG5vdCBpbiB1c2VyczoKICAgICAgICAgICAgdXNlcnMuYXBwZW5kKHNlbGYu + cnVuX2FzX3VzZXIpCiAgICAgICAgZm9yIHVzZXIgaW4gdXNlcnM6CiAgICAgICAgICAgIHNlbGYu + dXBncmFkZV91c2VyX3Blcm1pc3Npb25zKHVzZXIpCgogICAgZGVmIGdldF9yZ3dfcG9vbF9uYW1l + X2R1cmluZ191cGdyYWRlKHNlbGYsIHVzZXIsIGNhcHMpOgogICAgICAgIGlmIHVzZXIgPT0gImNs + aWVudC5oZWFsdGhjaGVja2VyIjoKICAgICAgICAgICAgIyB3aGVuIGFkbWluIGhhcyBub3QgcHJv + dmlkZWQgcmd3IHBvb2wgbmFtZSBkdXJpbmcgdXBncmFkZSwKICAgICAgICAgICAgIyBnZXQgdGhl + IHJndyBwb29sIG5hbWUgZnJvbSBjbGllbnQuaGVhbHRoY2hlY2tlciB1c2VyIHdoaWNoIHdhcyB1 + c2VkIGR1cmluZyBjb25uZWN0aW9uCiAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2Vy + LnJnd19wb29sX3ByZWZpeDoKICAgICAgICAgICAgICAgICMgVG8gZ2V0IHZhbHVlICdkZWZhdWx0 + JyB3aGljaCBpcyByZ3cgcG9vbCBuYW1lIGZyb20gJ2FsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3 + Lm1ldGEnCiAgICAgICAgICAgICAgICBwYXR0ZXJuID0gciJwb29sPSguKj8pXC5yZ3dcLm1ldGEi + CiAgICAgICAgICAgICAgICBtYXRjaCA9IHJlLnNlYXJjaChwYXR0ZXJuLCBjYXBzKQogICAgICAg + ICAgICAgICAgaWYgbWF0Y2g6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5y + Z3dfcG9vbF9wcmVmaXggPSBtYXRjaC5ncm91cCgxKQogICAgICAgICAgICAgICAgZWxzZToKICAg + ICAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg + ICAgICAgICAgICAgICAgICAiZmFpbGVkIHRvIGdldCByZ3cgcG9vbCBuYW1lIGZvciB1cGdyYWRl + IgogICAgICAgICAgICAgICAgICAgICkKCiAgICBkZWYgdXBncmFkZV91c2VyX3Blcm1pc3Npb25z + KHNlbGYsIHVzZXIpOgogICAgICAgICMgY2hlY2sgd2hldGhlciB0aGUgZ2l2ZW4gdXNlciBleGlz + dHMgb3Igbm90CiAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJhdXRoIGdldCIsICJlbnRp + dHkiOiBmInt1c2VyfSIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmV0X3ZhbCwganNvbl9v + dXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAg + IGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHByaW50 + KGYidXNlciB7dXNlcn0gbm90IGZvdW5kIGZvciB1cGdyYWRpbmcuIikKICAgICAgICAgICAgcmV0 + dXJuCiAgICAgICAgZXhpc3RpbmdfY2FwcyA9IGpzb25fb3V0WzBdWyJjYXBzIl0KICAgICAgICBz + ZWxmLmdldF9yZ3dfcG9vbF9uYW1lX2R1cmluZ191cGdyYWRlKHVzZXIsIHN0cihleGlzdGluZ19j + YXBzKSkKICAgICAgICBuZXdfY2FwLCBfID0gc2VsZi5nZXRfY2Fwc19hbmRfZW50aXR5KHVzZXIp + CiAgICAgICAgY2FwX2tleXMgPSBbIm1vbiIsICJtZ3IiLCAib3NkIiwgIm1kcyJdCiAgICAgICAg + Y2FwcyA9IFtdCiAgICAgICAgZm9yIGVhY2hDYXAgaW4gY2FwX2tleXM6CiAgICAgICAgICAgIGN1 + cl9jYXBfdmFsdWVzID0gZXhpc3RpbmdfY2Fwcy5nZXQoZWFjaENhcCwgIiIpCiAgICAgICAgICAg + IG5ld19jYXBfdmFsdWVzID0gbmV3X2NhcC5nZXQoZWFjaENhcCwgIiIpCiAgICAgICAgICAgIGN1 + cl9jYXBfcGVybV9saXN0ID0gWwogICAgICAgICAgICAgICAgeC5zdHJpcCgpIGZvciB4IGluIGN1 + cl9jYXBfdmFsdWVzLnNwbGl0KCIsIikgaWYgeC5zdHJpcCgpCiAgICAgICAgICAgIF0KICAgICAg + ICAgICAgbmV3X2NhcF9wZXJtX2xpc3QgPSBbCiAgICAgICAgICAgICAgICB4LnN0cmlwKCkgZm9y + IHggaW4gbmV3X2NhcF92YWx1ZXMuc3BsaXQoIiwiKSBpZiB4LnN0cmlwKCkKICAgICAgICAgICAg + XQogICAgICAgICAgICAjIGFwcGVuZCBuZXdfY2FwX2xpc3QgdG8gY3VyX2NhcF9saXN0IHRvIG1h + aW50YWluIHRoZSBvcmRlciBvZiBjYXBzCiAgICAgICAgICAgIGN1cl9jYXBfcGVybV9saXN0LmV4 + dGVuZChuZXdfY2FwX3Blcm1fbGlzdCkKICAgICAgICAgICAgIyBlbGltaW5hdGUgZHVwbGljYXRl + cyB3aXRob3V0IHVzaW5nICdzZXQnCiAgICAgICAgICAgICMgc2V0IHJlLW9yZGVycyBpdGVtcyBp + biB0aGUgbGlzdCBhbmQgd2UgaGF2ZSB0byBrZWVwIHRoZSBvcmRlcgogICAgICAgICAgICBuZXdf + Y2FwX2xpc3QgPSBbXQogICAgICAgICAgICBbbmV3X2NhcF9saXN0LmFwcGVuZCh4KSBmb3IgeCBp + biBjdXJfY2FwX3Blcm1fbGlzdCBpZiB4IG5vdCBpbiBuZXdfY2FwX2xpc3RdCiAgICAgICAgICAg + IGV4aXN0aW5nX2NhcHNbZWFjaENhcF0gPSAiLCAiLmpvaW4obmV3X2NhcF9saXN0KQogICAgICAg + ICAgICBpZiBleGlzdGluZ19jYXBzW2VhY2hDYXBdOgogICAgICAgICAgICAgICAgY2Fwcy5hcHBl + bmQoZWFjaENhcCkKICAgICAgICAgICAgICAgIGNhcHMuYXBwZW5kKGV4aXN0aW5nX2NhcHNbZWFj + aENhcF0pCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJwcmVmaXgiOiAiYXV0aCBj + YXBzIiwKICAgICAgICAgICAgImVudGl0eSI6IHVzZXIsCiAgICAgICAgICAgICJjYXBzIjogY2Fw + cywKICAgICAgICAgICAgImZvcm1hdCI6ICJqc29uIiwKICAgICAgICB9CiAgICAgICAgcmV0X3Zh + bCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29u + KQogICAgICAgIGlmIHJldF92YWwgIT0gMDoKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFp + bHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiJ2F1dGggY2FwcyB7dXNlcn0nIGNvbW1h + bmQgZmFpbGVkLlxuIEVycm9yOiB7ZXJyX21zZ30iCiAgICAgICAgICAgICkKICAgICAgICBwcmlu + dChmIlVwZGF0ZWQgdXNlciB7dXNlcn0gc3VjY2Vzc2Z1bGx5LiIpCgogICAgZGVmIG1haW4oc2Vs + Zik6CiAgICAgICAgZ2VuZXJhdGVkX291dHB1dCA9ICIiCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh + cnNlci51cGdyYWRlOgogICAgICAgICAgICBzZWxmLnVwZ3JhZGVfdXNlcnNfcGVybWlzc2lvbnMo + KQogICAgICAgIGVsaWYgc2VsZi5fYXJnX3BhcnNlci5mb3JtYXQgPT0gImpzb24iOgogICAgICAg + ICAgICBnZW5lcmF0ZWRfb3V0cHV0ID0gc2VsZi5nZW5fanNvbl9vdXQoKQogICAgICAgIGVsaWYg + c2VsZi5fYXJnX3BhcnNlci5mb3JtYXQgPT0gImJhc2giOgogICAgICAgICAgICBnZW5lcmF0ZWRf + b3V0cHV0ID0gc2VsZi5nZW5fc2hlbGxfb3V0KCkKICAgICAgICBlbHNlOgogICAgICAgICAgICBy + YWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJVbnN1cHBv + cnRlZCBmb3JtYXQ6IHtzZWxmLl9hcmdfcGFyc2VyLmZvcm1hdH0iCiAgICAgICAgICAgICkKICAg + ICAgICBwcmludChnZW5lcmF0ZWRfb3V0cHV0KQogICAgICAgIGlmIHNlbGYub3V0cHV0X2ZpbGUg + YW5kIGdlbmVyYXRlZF9vdXRwdXQ6CiAgICAgICAgICAgIGZPdXQgPSBvcGVuKHNlbGYub3V0cHV0 + X2ZpbGUsIG1vZGU9InciLCBlbmNvZGluZz0iVVRGLTgiKQogICAgICAgICAgICBmT3V0LndyaXRl + KGdlbmVyYXRlZF9vdXRwdXQpCiAgICAgICAgICAgIGZPdXQuY2xvc2UoKQoKCiMjIyMjIyMjIyMj + IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMj + IyMgTUFJTiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj + IyMjIyMjIyMjIyMjIyMjIyMjIyMjCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICByak9i + aiA9IFJhZG9zSlNPTigpCiAgICB0cnk6CiAgICAgICAgcmpPYmoubWFpbigpCiAgICBleGNlcHQg + RXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbiBhcyBlcnI6CiAgICAgICAgcHJpbnQoZiJFeGVjdXRp + b24gRmFpbGVkOiB7ZXJyfSIpCiAgICAgICAgcmFpc2UgZXJyCiAgICBleGNlcHQgS2V5RXJyb3Ig + YXMga0VycjoKICAgICAgICBwcmludChmIktleUVycm9yOiB7a0Vycn0iKQogICAgZXhjZXB0IE9T + RXJyb3IgYXMgb3NFcnI6CiAgICAgICAgcHJpbnQoZiJFcnJvciB3aGlsZSB0cnlpbmcgdG8gb3V0 + cHV0IHRoZSBkYXRhOiB7b3NFcnJ9IikKICAgIGZpbmFsbHk6CiAgICAgICAgcmpPYmouc2h1dGRv + d24oKQo= +kind: ConfigMap +metadata: + name: rook-ceph-external-cluster-script-config From 55d985409d810233cfa36ae29d29dffb6e7a55c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:21:44 +0000 Subject: [PATCH 18/54] build(deps): bump github/codeql-action from 3.26.6 to 3.26.7 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.6 to 3.26.7. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4dd16135b69a43b6c8efb853346f8437d92d3c93...8214744c546c1e5c8f03dde8fab3a7353211988d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 315c4b6d3789..2a8dca108edb 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6 + uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 with: sarif_file: results.sarif From 609634e01954a4ef8e9cfbf0eb3c2affba8fc6c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:21:47 +0000 Subject: [PATCH 19/54] build(deps): bump DavidAnson/markdownlint-cli2-action Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 16.0.0 to 17.0.0. - [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases) - [Commits](https://github.com/davidanson/markdownlint-cli2-action/compare/b4c9feab76d8025d1e83c653fa3990936df0e6c8...db43aef879112c3119a410d69f66701e0d530809) --- updated-dependencies: - dependency-name: DavidAnson/markdownlint-cli2-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index c110b2b7dc07..6a61cd4adc38 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -36,7 +36,7 @@ jobs: with: python-version: 3.9 - - uses: DavidAnson/markdownlint-cli2-action@b4c9feab76d8025d1e83c653fa3990936df0e6c8 # v16.0.0 + - uses: DavidAnson/markdownlint-cli2-action@db43aef879112c3119a410d69f66701e0d530809 # v17.0.0 with: globs: | Documentation/**/*.md From b2c39ace252b4548253c035efdcafff23ed7dd8b Mon Sep 17 00:00:00 2001 From: Artem Torubarov Date: Mon, 16 Sep 2024 14:51:49 +0200 Subject: [PATCH 20/54] exporter: move config to cluster CRD allows to set prio-limit and stats-period options to ceph exporter Signed-off-by: Artem Torubarov --- .../CRDs/Cluster/ceph-cluster-crd.md | 3 ++ Documentation/CRDs/specification.md | 53 +++++++++++++++++++ .../charts/rook-ceph/templates/resources.yaml | 14 +++++ deploy/examples/cluster.yaml | 9 ++++ deploy/examples/crds.yaml | 14 +++++ pkg/apis/ceph.rook.io/v1/types.go | 14 +++++ .../ceph/cluster/nodedaemon/exporter.go | 11 ++-- .../ceph/cluster/nodedaemon/exporter_test.go | 20 +++++++ 8 files changed, 135 insertions(+), 3 deletions(-) diff --git a/Documentation/CRDs/Cluster/ceph-cluster-crd.md b/Documentation/CRDs/Cluster/ceph-cluster-crd.md index 67a4d3945de7..29ded5c34a8b 100755 --- a/Documentation/CRDs/Cluster/ceph-cluster-crd.md +++ b/Documentation/CRDs/Cluster/ceph-cluster-crd.md @@ -52,6 +52,9 @@ If this value is empty, each pod will get an ephemeral directory to store their * `externalMgrPrometheusPort`: external prometheus manager module port. See [external cluster configuration](./external-cluster/external-cluster.md) for more details. * `port`: The internal prometheus manager module port where the prometheus mgr module listens. The port may need to be configured when host networking is enabled. * `interval`: The interval for the prometheus module to to scrape targets. + * `exporter`: Ceph exporter metrics config. + * `perfCountersPrioLimit`: Specifies which performance counters are exported. Corresponds to `--prio-limit` Ceph exporter flag. `0` - all counters are exported, default is `5`. + * `statsPeriodSeconds`: Time to wait before sending requests again to exporter server (seconds). Corresponds to `--stats-period` Ceph exporter flag. Default is `5`. * `network`: For the network settings for the cluster, refer to the [network configuration settings](#network-configuration-settings) * `mon`: contains mon related options [mon settings](#mon-settings) For more details on the mons and when to choose a number other than `3`, see the [mon health doc](../../Storage-Configuration/Advanced/ceph-mon-health.md). diff --git a/Documentation/CRDs/specification.md b/Documentation/CRDs/specification.md index 662c8575c97f..ebd043d22f6e 100644 --- a/Documentation/CRDs/specification.md +++ b/Documentation/CRDs/specification.md @@ -3686,6 +3686,45 @@ map[string]int +

CephExporterSpec +

+

+(Appears on:MonitoringSpec) +

+
+
+ + + + + + + + + + + + + + + + + +
FieldDescription
+perfCountersPrioLimit
+ +int64 + +
+

Only performance counters greater than or equal to this option are fetched

+
+statsPeriodSeconds
+ +int64 + +
+

Time to wait before sending requests again to exporter server (seconds)

+

CephFilesystemStatus

@@ -8527,6 +8566,20 @@ Kubernetes meta/v1.Duration

Interval determines prometheus scrape interval

+ + +exporter
+ + +CephExporterSpec + + + + +(Optional) +

Ceph exporter configuration

+ +

MultiClusterServiceSpec diff --git a/deploy/charts/rook-ceph/templates/resources.yaml b/deploy/charts/rook-ceph/templates/resources.yaml index 767e08498461..0092ad799fad 100644 --- a/deploy/charts/rook-ceph/templates/resources.yaml +++ b/deploy/charts/rook-ceph/templates/resources.yaml @@ -2341,6 +2341,20 @@ spec: Enabled determines whether to create the prometheus rules for the ceph cluster. If true, the prometheus types must exist or the creation will fail. Default is false. type: boolean + exporter: + description: Ceph exporter configuration + properties: + perfCountersPrioLimit: + default: 5 + description: Only performance counters greater than or equal to this option are fetched + format: int64 + type: integer + statsPeriodSeconds: + default: 5 + description: Time to wait before sending requests again to exporter server (seconds) + format: int64 + type: integer + type: object externalMgrEndpoints: description: ExternalMgrEndpoints points to an existing Ceph prometheus exporter endpoint items: diff --git a/deploy/examples/cluster.yaml b/deploy/examples/cluster.yaml index 11860340376e..a01f99f396b0 100644 --- a/deploy/examples/cluster.yaml +++ b/deploy/examples/cluster.yaml @@ -85,6 +85,15 @@ spec: # Whether to disable the metrics reported by Ceph. If false, the prometheus mgr module and Ceph exporter are enabled. # If true, the prometheus mgr module and Ceph exporter are both disabled. Default is false. metricsDisabled: false + # Ceph exporter metrics config. + exporter: + # Specifies which performance counters are exported. + # Corresponds to --prio-limit Ceph exporter flag + # 0 - all counters are exported + perfCountersPrioLimit: 5 + # Time to wait before sending requests again to exporter server (seconds) + # Corresponds to --stats-period Ceph exporter flag + statsPeriodSeconds: 5 network: connections: # Whether to encrypt the data in transit across the wire to prevent eavesdropping the data on the network. diff --git a/deploy/examples/crds.yaml b/deploy/examples/crds.yaml index 9f7a3d225655..aa8759c17784 100644 --- a/deploy/examples/crds.yaml +++ b/deploy/examples/crds.yaml @@ -2339,6 +2339,20 @@ spec: Enabled determines whether to create the prometheus rules for the ceph cluster. If true, the prometheus types must exist or the creation will fail. Default is false. type: boolean + exporter: + description: Ceph exporter configuration + properties: + perfCountersPrioLimit: + default: 5 + description: Only performance counters greater than or equal to this option are fetched + format: int64 + type: integer + statsPeriodSeconds: + default: 5 + description: Time to wait before sending requests again to exporter server (seconds) + format: int64 + type: integer + type: object externalMgrEndpoints: description: ExternalMgrEndpoints points to an existing Ceph prometheus exporter endpoint items: diff --git a/pkg/apis/ceph.rook.io/v1/types.go b/pkg/apis/ceph.rook.io/v1/types.go index c817ac41ac73..d06c20081f95 100755 --- a/pkg/apis/ceph.rook.io/v1/types.go +++ b/pkg/apis/ceph.rook.io/v1/types.go @@ -406,6 +406,20 @@ type MonitoringSpec struct { // Interval determines prometheus scrape interval // +optional Interval *metav1.Duration `json:"interval,omitempty"` + + // Ceph exporter configuration + // +optional + Exporter *CephExporterSpec `json:"exporter,omitempty"` +} + +type CephExporterSpec struct { + // Only performance counters greater than or equal to this option are fetched + // +kubebuilder:default=5 + PerfCountersPrioLimit int64 `json:"perfCountersPrioLimit,omitempty"` + + // Time to wait before sending requests again to exporter server (seconds) + // +kubebuilder:default=5 + StatsPeriodSeconds int64 `json:"statsPeriodSeconds,omitempty"` } // ClusterStatus represents the status of a Ceph cluster diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter.go b/pkg/operator/ceph/cluster/nodedaemon/exporter.go index 070bee756301..dec1809eb163 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/exporter.go +++ b/pkg/operator/ceph/cluster/nodedaemon/exporter.go @@ -42,8 +42,8 @@ const ( monitoringPath = "/etc/ceph-monitoring/" serviceMonitorFile = "exporter-service-monitor.yaml" sockDir = "/run/ceph" - perfCountersPrioLimit = "5" - statsPeriod = "5" + defaultPrioLimit = "5" + defaultStatsPeriod = "5" DefaultMetricsPort uint16 = 9926 exporterServiceMetricName = "ceph-exporter-http-metrics" exporterKeyringUsername = "client.ceph-exporter" @@ -179,10 +179,15 @@ func getCephExporterDaemonContainer(cephCluster cephv1.CephCluster, cephVersion exporterEnvVar := generateExporterEnvVar() envVars := append(controller.DaemonEnvVars(&cephCluster.Spec), exporterEnvVar) + prioLimit, statsPeriod := defaultPrioLimit, defaultStatsPeriod + if cephCluster.Spec.Monitoring.Exporter != nil { + prioLimit = strconv.Itoa(int(cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit)) + statsPeriod = strconv.Itoa(int(cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds)) + } args := []string{ "--sock-dir", sockDir, "--port", strconv.Itoa(int(DefaultMetricsPort)), - "--prio-limit", perfCountersPrioLimit, + "--prio-limit", prioLimit, "--stats-period", statsPeriod, } diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go b/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go index 2a6adc90cd22..17ab9132dbff 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go +++ b/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go @@ -121,6 +121,26 @@ func TestCreateOrUpdateCephExporter(t *testing.T) { assert.Equal(t, tolerations, podSpec.Spec.Tolerations) assert.Equal(t, true, podSpec.Spec.HostNetwork) assert.Equal(t, "test-priority-class", podSpec.Spec.PriorityClassName) + + t.Run("exporter config", func(t *testing.T) { + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{ + PerfCountersPrioLimit: 3, + StatsPeriodSeconds: 7, + } + res, err := r.createOrUpdateCephExporter(node, tolerations, cephCluster, cephVersion) + assert.NoError(t, err) + assert.Equal(t, controllerutil.OperationResult("updated"), res) + + err = r.client.Get(ctx, types.NamespacedName{Namespace: "rook-ceph", Name: name}, &deploy) + assert.NoError(t, err) + + podSpec := deploy.Spec.Template + args := podSpec.Spec.Containers[0].Args + assert.Equal(t, "--prio-limit", args[4]) + assert.Equal(t, "3", args[5]) + assert.Equal(t, "--stats-period", args[6]) + assert.Equal(t, "7", args[7]) + }) } func TestCephExporterBindAddress(t *testing.T) { From 18d32ba3816adf1555ed04bd215c692d15f0c933 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:46:20 +0000 Subject: [PATCH 21/54] build(deps): bump the github-dependencies group with 4 updates Bumps the github-dependencies group with 4 updates: [github.com/hashicorp/vault/api](https://github.com/hashicorp/vault), [github.com/k8snetworkplumbingwg/network-attachment-definition-client](https://github.com/k8snetworkplumbingwg/network-attachment-definition-client), [github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring](https://github.com/prometheus-operator/prometheus-operator) and [github.com/prometheus-operator/prometheus-operator/pkg/client](https://github.com/prometheus-operator/prometheus-operator). Updates `github.com/hashicorp/vault/api` from 1.14.0 to 1.15.0 - [Release notes](https://github.com/hashicorp/vault/releases) - [Changelog](https://github.com/hashicorp/vault/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/vault/compare/v1.14.0...v1.15.0) Updates `github.com/k8snetworkplumbingwg/network-attachment-definition-client` from 1.7.1 to 1.7.3 - [Release notes](https://github.com/k8snetworkplumbingwg/network-attachment-definition-client/releases) - [Commits](https://github.com/k8snetworkplumbingwg/network-attachment-definition-client/compare/v1.7.1...v1.7.3) Updates `github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring` from 0.76.1 to 0.76.2 - [Release notes](https://github.com/prometheus-operator/prometheus-operator/releases) - [Changelog](https://github.com/prometheus-operator/prometheus-operator/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus-operator/prometheus-operator/compare/v0.76.1...v0.76.2) Updates `github.com/prometheus-operator/prometheus-operator/pkg/client` from 0.76.1 to 0.76.2 - [Release notes](https://github.com/prometheus-operator/prometheus-operator/releases) - [Changelog](https://github.com/prometheus-operator/prometheus-operator/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus-operator/prometheus-operator/compare/v0.76.1...v0.76.2) --- updated-dependencies: - dependency-name: github.com/hashicorp/vault/api dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-dependencies - dependency-name: github.com/k8snetworkplumbingwg/network-attachment-definition-client dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-dependencies - dependency-name: github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-dependencies - dependency-name: github.com/prometheus-operator/prometheus-operator/pkg/client dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-dependencies ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 19 ++++++++++--------- pkg/apis/go.mod | 6 +++--- pkg/apis/go.sum | 11 ++++++----- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 789a8464d54b..79f415c05d60 100644 --- a/go.mod +++ b/go.mod @@ -26,13 +26,13 @@ require ( github.com/go-ini/ini v1.67.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 - github.com/hashicorp/vault/api v1.14.0 - github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.1 + github.com/hashicorp/vault/api v1.15.0 + github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.3 github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1 github.com/libopenstorage/secrets v0.0.0-20240416031220-a17cf7f72c6c github.com/pkg/errors v0.9.1 - github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.1 - github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.1 + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.2 + github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.2 github.com/rook/rook/pkg/apis v0.0.0-20231204200402-5287527732f7 github.com/sethvargo/go-password v0.3.1 github.com/spf13/cobra v1.8.1 @@ -66,6 +66,7 @@ require ( github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect @@ -82,7 +83,6 @@ require ( github.com/ansel1/merry v1.8.0 // indirect github.com/ansel1/merry/v2 v2.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/ceph/ceph-csi/api v0.0.0-20231227104434-06f9a98b7a83 github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containernetworking/cni v1.2.0-rc1 // indirect diff --git a/go.sum b/go.sum index ccec62e8dcf6..76c1460b89f6 100644 --- a/go.sum +++ b/go.sum @@ -161,8 +161,9 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/ceph/ceph-csi-operator/api v0.0.0-20240819112305-88e6db254d6c h1:JOhwt7+iM18pm9s9zAhAKGRJm615AdIaKklbUd7Z8So= github.com/ceph/ceph-csi-operator/api v0.0.0-20240819112305-88e6db254d6c/go.mod h1:odEUoarG26wXBCC2l4O4nMWhAz6VTKr2FRkv9yELgi8= @@ -555,8 +556,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck= -github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= -github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= +github.com/hashicorp/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= +github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= github.com/hashicorp/vault/api/auth/approle v0.5.0/go.mod h1:CHOQIA1AZACfjTzHggmyfiOZ+xCSKNRFqe48FTCzH0k= github.com/hashicorp/vault/api/auth/approle v0.6.0 h1:ELfFFQlTM/e97WJKu1HvNFa7lQ3tlTwwzrR1NJE1V7Y= github.com/hashicorp/vault/api/auth/approle v0.6.0/go.mod h1:CCoIl1xBC3lAWpd1HV+0ovk76Z8b8Mdepyk21h3pGk0= @@ -597,8 +598,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= -github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.1 h1:n4FpoJ6aGDx8ULfya/C4ycrMDuPZlf7AtPyrT4+rIP4= -github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.1/go.mod h1:CM7HAH5PNuIsqjMN0fGc1ydM74Uj+0VZFhob620nklw= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.3 h1:W44yEuOvwcBErGzSjjVGEbmHh8oRGLmxDSC2yVJQ2aM= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.3/go.mod h1:CM7HAH5PNuIsqjMN0fGc1ydM74Uj+0VZFhob620nklw= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -778,11 +779,11 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.44.1/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.46.0/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.1 h1:QU2cs0xxKYvF1JfibP/8vs+pFy6OvIpqNR2lYC4jYNU= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.1/go.mod h1:Rd8YnCqz+2FYsiGmE2DMlaLjQRB4v2jFNnzCt9YY4IM= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.2 h1:BpGDC87A2SaxbKgONsFLEX3kRcRJee2aLQbjXsuz0hA= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.76.2/go.mod h1:Rd8YnCqz+2FYsiGmE2DMlaLjQRB4v2jFNnzCt9YY4IM= github.com/prometheus-operator/prometheus-operator/pkg/client v0.46.0/go.mod h1:k4BrWlVQQsvBiTcDnKEMgyh/euRxyxgrHdur/ZX/sdA= -github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.1 h1:wMPmeRdflJFu14F0YaIiOIYGkBDDKipkeWW0q53d2+s= -github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.1/go.mod h1:7vND+IkdMpZyfSyRs6P5/uXz6BlFDaOj8olErODi8I0= +github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.2 h1:yncs8NglhE3hB+viNsabCAF9TBBDOBljHUyxHC5fSGY= +github.com/prometheus-operator/prometheus-operator/pkg/client v0.76.2/go.mod h1:AfbzyEUFxJmSoTiMcgNHHjDKcorBVd9TIwx0viURgEw= github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod index 27790be77987..79f7c259da9e 100644 --- a/pkg/apis/go.mod +++ b/pkg/apis/go.mod @@ -15,8 +15,8 @@ replace ( ) require ( - github.com/hashicorp/vault/api v1.14.0 - github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.1 + github.com/hashicorp/vault/api v1.15.0 + github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.3 github.com/kube-object-storage/lib-bucket-provisioner v0.0.0-20221122204822-d1a8c34382f1 github.com/libopenstorage/secrets v0.0.0-20240416031220-a17cf7f72c6c github.com/pkg/errors v0.9.1 @@ -27,6 +27,7 @@ require ( require ( github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/google/go-cmp v0.6.0 // indirect @@ -39,7 +40,6 @@ require ( ) require ( - github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/containernetworking/cni v1.2.0-rc1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect diff --git a/pkg/apis/go.sum b/pkg/apis/go.sum index 795621de221e..50cf57cc5b93 100644 --- a/pkg/apis/go.sum +++ b/pkg/apis/go.sum @@ -125,8 +125,9 @@ github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -470,8 +471,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= github.com/hashicorp/vault/api v1.12.0/go.mod h1:si+lJCYO7oGkIoNPAN8j3azBLTn9SjMGS+jFaHd1Cck= -github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU= -github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk= +github.com/hashicorp/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= +github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= github.com/hashicorp/vault/api/auth/approle v0.5.0/go.mod h1:CHOQIA1AZACfjTzHggmyfiOZ+xCSKNRFqe48FTCzH0k= github.com/hashicorp/vault/api/auth/approle v0.6.0 h1:ELfFFQlTM/e97WJKu1HvNFa7lQ3tlTwwzrR1NJE1V7Y= github.com/hashicorp/vault/api/auth/approle v0.6.0/go.mod h1:CCoIl1xBC3lAWpd1HV+0ovk76Z8b8Mdepyk21h3pGk0= @@ -502,8 +503,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.1 h1:n4FpoJ6aGDx8ULfya/C4ycrMDuPZlf7AtPyrT4+rIP4= -github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.1/go.mod h1:CM7HAH5PNuIsqjMN0fGc1ydM74Uj+0VZFhob620nklw= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.3 h1:W44yEuOvwcBErGzSjjVGEbmHh8oRGLmxDSC2yVJQ2aM= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.3/go.mod h1:CM7HAH5PNuIsqjMN0fGc1ydM74Uj+0VZFhob620nklw= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= From c8a64c49757aec1ddcad3aee1aa6109079bd1a47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:45:51 +0000 Subject: [PATCH 22/54] build(deps): bump the k8s-dependencies group with 6 updates Bumps the k8s-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.31.0` | `0.31.1` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.31.0` | `0.31.1` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.31.0` | `0.31.1` | | [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) | `0.31.0` | `0.31.1` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.31.0` | `0.31.1` | | [k8s.io/cloud-provider](https://github.com/kubernetes/cloud-provider) | `0.31.0` | `0.31.1` | Updates `k8s.io/api` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/api/compare/v0.31.0...v0.31.1) Updates `k8s.io/apiextensions-apiserver` from 0.31.0 to 0.31.1 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.31.0...v0.31.1) Updates `k8s.io/apimachinery` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.31.0...v0.31.1) Updates `k8s.io/cli-runtime` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.31.0...v0.31.1) Updates `k8s.io/client-go` from 0.31.0 to 0.31.1 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.31.0...v0.31.1) Updates `k8s.io/cloud-provider` from 0.31.0 to 0.31.1 - [Commits](https://github.com/kubernetes/cloud-provider/compare/v0.31.0...v0.31.1) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/cli-runtime dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies - dependency-name: k8s.io/cloud-provider dependency-type: direct:production update-type: version-update:semver-patch dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ pkg/apis/go.mod | 6 +++--- pkg/apis/go.sum | 12 ++++++------ 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 789a8464d54b..85d836fed9d5 100644 --- a/go.mod +++ b/go.mod @@ -45,12 +45,12 @@ require ( golang.org/x/sync v0.8.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.31.0 - k8s.io/apiextensions-apiserver v0.31.0 - k8s.io/apimachinery v0.31.0 - k8s.io/cli-runtime v0.31.0 - k8s.io/client-go v0.31.0 - k8s.io/cloud-provider v0.31.0 + k8s.io/api v0.31.1 + k8s.io/apiextensions-apiserver v0.31.1 + k8s.io/apimachinery v0.31.1 + k8s.io/cli-runtime v0.31.1 + k8s.io/client-go v0.31.1 + k8s.io/cloud-provider v0.31.1 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 sigs.k8s.io/controller-runtime v0.19.0 sigs.k8s.io/mcs-api v0.1.0 diff --git a/go.sum b/go.sum index ccec62e8dcf6..75f7f6a2888b 100644 --- a/go.sum +++ b/go.sum @@ -1604,15 +1604,15 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg= -k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= -k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= k8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE= k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= +k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= @@ -1624,14 +1624,14 @@ k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRp k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= -k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw= k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= -k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= +k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk= +k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g= @@ -1640,10 +1640,10 @@ k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= k8s.io/client-go v0.20.0/go.mod h1:4KWh/g+Ocd8KkCwKF8vUNnmqgv+EVnQDK4MBF4oB5tY= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4= -k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= -k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= -k8s.io/cloud-provider v0.31.0 h1:qNOs78I2/7zQmyStfDtY2M7EdilUl9fCSYMcqBju/tA= -k8s.io/cloud-provider v0.31.0/go.mod h1:QgUPqLoL6aXhLlrNg1U4IrJk/PvvxgeOnT2ixkgnqT0= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/cloud-provider v0.31.1 h1:40b6AgDizwm5eWratZbqubTHMob25VWr6NX2Ei5TwZA= +k8s.io/cloud-provider v0.31.1/go.mod h1:xAdkE7fdZdu9rKLuOZUMBfagu7bM+bas3iPux/2nLGg= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod index 27790be77987..0748da9216ee 100644 --- a/pkg/apis/go.mod +++ b/pkg/apis/go.mod @@ -21,8 +21,8 @@ require ( github.com/libopenstorage/secrets v0.0.0-20240416031220-a17cf7f72c6c github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.9.0 - k8s.io/api v0.31.0 - k8s.io/apimachinery v0.31.0 + k8s.io/api v0.31.1 + k8s.io/apimachinery v0.31.1 ) require ( @@ -33,7 +33,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/x448/float16 v0.8.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/client-go v0.31.0 // indirect + k8s.io/client-go v0.31.1 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/pkg/apis/go.sum b/pkg/apis/go.sum index 795621de221e..288ff694accf 100644 --- a/pkg/apis/go.sum +++ b/pkg/apis/go.sum @@ -1409,8 +1409,8 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg= -k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= -k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= k8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= @@ -1423,8 +1423,8 @@ k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRp k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= -k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= @@ -1433,8 +1433,8 @@ k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= k8s.io/client-go v0.20.0/go.mod h1:4KWh/g+Ocd8KkCwKF8vUNnmqgv+EVnQDK4MBF4oB5tY= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4= -k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= -k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.20.0/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= From 1e3d08f11409dcf3e1f0119fe9388ba840bb98d6 Mon Sep 17 00:00:00 2001 From: Niraj Yadav Date: Thu, 12 Sep 2024 18:25:09 +0530 Subject: [PATCH 23/54] docs: add documentation for volumegroupsnapshot This PR adds the sample YAMLs and documentation for the VolumeGroupSnapshot feature. Signed-off-by: Niraj Yadav --- .../Storage-Configuration/Ceph-CSI/.pages | 1 + .../Ceph-CSI/ceph-csi-snapshot.md | 5 - .../ceph-csi-volume-group-snapshot.md | 109 ++++++++++++++++++ deploy/examples/csi/cephfs/groupsnapshot.yaml | 13 +++ .../csi/cephfs/groupsnapshotclass.yaml | 15 +++ deploy/examples/csi/cephfs/pvc.yaml | 2 + 6 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-volume-group-snapshot.md create mode 100644 deploy/examples/csi/cephfs/groupsnapshot.yaml create mode 100644 deploy/examples/csi/cephfs/groupsnapshotclass.yaml diff --git a/Documentation/Storage-Configuration/Ceph-CSI/.pages b/Documentation/Storage-Configuration/Ceph-CSI/.pages index a117ff7ddd87..47db28e1cd34 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/.pages +++ b/Documentation/Storage-Configuration/Ceph-CSI/.pages @@ -1,6 +1,7 @@ nav: - ceph-csi-drivers.md - ceph-csi-snapshot.md + - ceph-csi-volume-group-snapshot.md - ceph-csi-volume-clone.md - custom-images.md - ... diff --git a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-snapshot.md b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-snapshot.md index 1a8d888d14ce..c436b7198821 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-snapshot.md +++ b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-snapshot.md @@ -178,8 +178,3 @@ kubectl delete -f deploy/examples/csi/cephfs/pvc-restore.yaml kubectl delete -f deploy/examples/csi/cephfs/snapshot.yaml kubectl delete -f deploy/examples/csi/cephfs/snapshotclass.yaml ``` - -## Limitations - -- There is a limit of 400 snapshots per cephFS filesystem. -- The PVC cannot be deleted if it has snapshots. make sure all the snapshots on the PVC are deleted before you delete the PVC. diff --git a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-volume-group-snapshot.md b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-volume-group-snapshot.md new file mode 100644 index 000000000000..33d58b807fa2 --- /dev/null +++ b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-volume-group-snapshot.md @@ -0,0 +1,109 @@ +--- +title: Volume Group Snapshots +--- + +Ceph provides the ability to create crash-consistent snapshots of multiple volumes. +A group snapshot represents “copies” from multiple volumes that are taken at the same point in time. +A group snapshot can be used either to rehydrate new volumes (pre-populated with the snapshot data) +or to restore existing volumes to a previous state (represented by the snapshots) + + +## Prerequisites + +- Install the [snapshot controller, volume group snapshot and snapshot CRDs](https://github.com/kubernetes-csi/external-snapshotter/tree/master#usage), +refer to VolumeGroupSnapshot documentation +[here](https://github.com/kubernetes-csi/external-snapshotter/tree/master#volume-group-snapshot-support) for more details. + +- A `VolumeGroupSnapshotClass` is needed for the volume group snapshot to work. The purpose of a `VolumeGroupSnapshotClass` is +defined in [the kubernetes +documentation](https://kubernetes.io/blog/2023/05/08/kubernetes-1-27-volume-group-snapshot-alpha/). +In short, as the documentation describes it: + +!!! info + Created by cluster administrators to describe how volume group snapshots + should be created. including the driver information, the deletion policy, etc. + +## Volume Group Snapshots + +### CephFS VolumeGroupSnapshotClass + +In [VolumeGroupSnapshotClass](https://github.com/rook/rook/tree/master/deploy/examples/csi/cephfs/groupsnapshotclass.yaml), +the `csi.storage.k8s.io/group-snapshotter-secret-name` parameter should reference the +name of the secret created for the cephfs-plugin. + +In the `VolumeGroupSnapshotClass`, update the value of the `clusterID` field to match the namespace +that Rook is running in. When Ceph CSI is deployed by Rook, the operator will automatically +maintain a configmap whose contents will match this key. By default this is +"rook-ceph". + +```console +kubectl create -f deploy/examples/csi/cephfs/groupsnapshotclass.yaml +``` + +### CephFS VolumeGroupSnapshot + +In [VolumeGroupSnapshot](https://github.com/rook/rook/tree/master/deploy/examples/csi/cephfs/groupsnapshot.yaml), +`volumeGroupSnapshotClassName` should be the name of the `VolumeGroupSnapshotClass` +previously created. The labels inside `matchLabels` should be present on the +PVCs that are already created by the CephFS CSI driver. + +```console +kubectl create -f deploy/examples/csi/cephfs/groupsnapshot.yaml +``` + +### Verify CephFS GroupSnapshot Creation + +```console +$ kubectl get volumegroupsnapshotclass +NAME DRIVER DELETIONPOLICY AGE +csi-cephfsplugin-groupsnapclass rook-ceph.cephfs.csi.ceph.com Delete 21m +``` + +```console +$ kubectl get volumegroupsnapshot +NAME READYTOUSE VOLUMEGROUPSNAPSHOTCLASS VOLUMEGROUPSNAPSHOTCONTENT CREATIONTIME AGE +cephfs-groupsnapshot true csi-cephfsplugin-groupsnapclass groupsnapcontent-d13f4d95-8822-4729-9586-4f222a3f788e 5m37s 5m39s +``` + +The snapshot will be ready to restore to a new PVC when `READYTOUSE` field of the +`volumegroupsnapshot` is set to true. + +### Restore the CephFS volume group snapshot to a new PVC + +Find the name of the snapshots created by the `VolumeGroupSnapshot` first by running: + +```console +$ kubectl get volumegroupsnapshot/cephfs-groupsnapshot -o=jsonpath='{range .status.pvcVolumeSnapshotRefList[*]}PVC: {.persistentVolumeClaimRef.name}, Snapshot: {.volumeSnapshotRef.name}{"\n"}{end}' +PVC: cephfs-pvc, Snapshot: snapshot-9d21b143904c10f49ddc92664a7e8fe93c23387d0a88549c14337484ebaf1011-2024-09-12-3.49.13 +``` + +It will list the PVC's name followed by its snapshot name. + +In +[pvc-restore](https://github.com/rook/rook/tree/master/deploy/examples/csi/cephfs/pvc-restore.yaml), +`dataSource` should be one of the `Snapshot` that we just +found. The `dataSource` kind should be the `VolumeSnapshot`. + +Create a new PVC from the snapshot + +```console +kubectl create -f deploy/examples/csi/cephfs/pvc-restore.yaml +``` + +### Verify CephFS Restore PVC Creation + +```console +$ kubectl get pvc +cephfs-pvc Bound pvc-9ae60bf9-4931-4f9a-9de1-7f45f31fe4da 1Gi RWO rook-cephfs 171m +cephfs-pvc-restore Bound pvc-b4b73cbb-5061-48c7-9ac8-e1202508cf97 1Gi RWO rook-cephfs 46s +``` + +## CephFS volume group snapshot resource Cleanup + +To clean the resources created by this example, run the following: + +```console +kubectl delete -f deploy/examples/csi/cephfs/pvc-restore.yaml +kubectl delete -f deploy/examples/csi/cephfs/groupsnapshot.yaml +kubectl delete -f deploy/examples/csi/cephfs/groupsnapshotclass.yaml +``` diff --git a/deploy/examples/csi/cephfs/groupsnapshot.yaml b/deploy/examples/csi/cephfs/groupsnapshot.yaml new file mode 100644 index 000000000000..98a8a6d46cfe --- /dev/null +++ b/deploy/examples/csi/cephfs/groupsnapshot.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: groupsnapshot.storage.k8s.io/v1alpha1 +kind: VolumeGroupSnapshot +metadata: + name: cephfs-groupsnapshot +spec: + source: + selector: + matchLabels: + # The PVCs require this label for them to be + # included in the VolumeGroupSnapshot + group: snapshot-test + volumeGroupSnapshotClassName: csi-cephfsplugin-groupsnapclass diff --git a/deploy/examples/csi/cephfs/groupsnapshotclass.yaml b/deploy/examples/csi/cephfs/groupsnapshotclass.yaml new file mode 100644 index 000000000000..fe8d2e775c24 --- /dev/null +++ b/deploy/examples/csi/cephfs/groupsnapshotclass.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: groupsnapshot.storage.k8s.io/v1alpha1 +kind: VolumeGroupSnapshotClass +metadata: + name: csi-cephfsplugin-groupsnapclass +driver: rook-ceph.cephfs.csi.ceph.com # csi-provisioner-name +parameters: + # Specify a string that identifies your cluster. Ceph CSI supports any + # unique string. When Ceph CSI is deployed by Rook use the Rook namespace, + # for example "rook-ceph". + clusterID: rook-ceph # namespace: cluster + fsName: myfs + csi.storage.k8s.io/group-snapshotter-secret-name: rook-csi-cephfs-provisioner + csi.storage.k8s.io/group-snapshotter-secret-namespace: rook-ceph +deletionPolicy: Delete diff --git a/deploy/examples/csi/cephfs/pvc.yaml b/deploy/examples/csi/cephfs/pvc.yaml index 0f6addb69fae..cf3057de3115 100644 --- a/deploy/examples/csi/cephfs/pvc.yaml +++ b/deploy/examples/csi/cephfs/pvc.yaml @@ -3,6 +3,8 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cephfs-pvc + labels: + group: snapshot-test spec: accessModes: - ReadWriteOnce From 32c5d99ef565e9aaf88f5f1f36c4aeca083b8347 Mon Sep 17 00:00:00 2001 From: subhamkrai Date: Tue, 17 Sep 2024 15:03:21 +0530 Subject: [PATCH 24/54] external: mds caps to healthchecker/cephfs users for cephfs fencing in external mode, we run command `ceph tell mds ***` which requires user user to include cap mds allow * in permission. So, we need to add this in healthchercker and cephfs provisioner user Signed-off-by: subhamkrai --- .../create-external-cluster-resources.py | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/deploy/examples/create-external-cluster-resources.py b/deploy/examples/create-external-cluster-resources.py index 45b972d1114c..268176c4f607 100644 --- a/deploy/examples/create-external-cluster-resources.py +++ b/deploy/examples/create-external-cluster-resources.py @@ -96,8 +96,8 @@ def _init_cmd_output_map(self): """{"dashboard":"https://ceph-dashboard:8443/","prometheus":"http://ceph-dashboard-db:9283/"}""" ) self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command quorum_status", "osd", "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow x pool=default.rgw.buckets.index"], "entity": "client.healthchecker", "format": "json", "prefix": "auth get-or-create"}""" - ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon":"allow r, allow command quorum_status","osd":"profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow x pool=default.rgw.buckets.index"}}]""" + """{"caps": ["mon", "allow r, allow command quorum_status", "osd", "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow x pool=default.rgw.buckets.index", "mds", "allow *"], "entity": "client.healthchecker", "format": "json", "prefix": "auth get-or-create"}""" + ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon":"allow r, allow command quorum_status","osd":"profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow x pool=default.rgw.buckets.index","mds":"allow *"}}]""" self.cmd_output_map[ """{"caps": ["mon", "profile rbd, allow command 'osd blocklist'", "osd", "profile rbd"], "entity": "client.csi-rbd-node", "format": "json", "prefix": "auth get-or-create"}""" ] = """[{"entity":"client.csi-rbd-node","key":"AQBOgrNeHbK1AxAAubYBeV8S1U/GPzq5SVeq6g==","caps":{"mon":"profile rbd, allow command 'osd blocklist'","osd":"profile rbd"}}]""" @@ -108,20 +108,20 @@ def _init_cmd_output_map(self): """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs *=*", "mds", "allow rw"], "entity": "client.csi-cephfs-node", "format": "json", "prefix": "auth get-or-create"}""" ] = """[{"entity":"client.csi-cephfs-node","key":"AQBOgrNeENunKxAAPCmgE7R6G8DcXnaJ1F32qg==","caps":{"mds":"allow rw","mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs *=*"}}]""" self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=*"], "entity": "client.csi-cephfs-provisioner", "format": "json", "prefix": "auth get-or-create"}""" - ] = """[{"entity":"client.csi-cephfs-provisioner","key":"AQBOgrNeAFgcGBAAvGqKOAD0D3xxmVY0R912dg==","caps":{"mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs metadata=*"}}]""" + """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=*", "mds", "allow *"], "entity": "client.csi-cephfs-provisioner", "format": "json", "prefix": "auth get-or-create"}""" + ] = """[{"entity":"client.csi-cephfs-provisioner","key":"AQBOgrNeAFgcGBAAvGqKOAD0D3xxmVY0R912dg==","caps":{"mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs metadata=*","mds":"allow *"}}]""" self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=*"], "entity": "client.csi-cephfs-provisioner-openshift-storage", "format": "json", "prefix": "auth get-or-create"}""" - ] = """[{"entity":"client.csi-cephfs-provisioner-openshift-storage","key":"BQBOgrNeAFgcGBAAvGqKOAD0D3xxmVY0R912dg==","caps":{"mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs metadata=*"}}]""" + """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=*", "mds", "allow *"], "entity": "client.csi-cephfs-provisioner-openshift-storage", "format": "json", "prefix": "auth get-or-create"}""" + ] = """[{"entity":"client.csi-cephfs-provisioner-openshift-storage","key":"BQBOgrNeAFgcGBAAvGqKOAD0D3xxmVY0R912dg==","caps":{"mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs metadata=*", "mds":"allow *"}}]""" self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=myfs"], "entity": "client.csi-cephfs-provisioner-openshift-storage-myfs", "format": "json", "prefix": "auth get-or-create"}""" - ] = """[{"entity":"client.csi-cephfs-provisioner-openshift-storage-myfs","key":"CQBOgrNeAFgcGBAAvGqKOAD0D3xxmVY0R912dg==","caps":{"mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs metadata=myfs"}}]""" + """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=myfs", "mds", "allow *"], "entity": "client.csi-cephfs-provisioner-openshift-storage-myfs", "format": "json", "prefix": "auth get-or-create"}""" + ] = """[{"entity":"client.csi-cephfs-provisioner-openshift-storage-myfs","key":"CQBOgrNeAFgcGBAAvGqKOAD0D3xxmVY0R912dg==","caps":{"mgr":"allow rw","mon":"allow r, allow command 'osd blocklist'","osd":"allow rw tag cephfs metadata=myfs","mds":"allow *"}}]""" self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command quorum_status, allow command version", "mgr", "allow command config", "osd", "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index"], "entity": "client.healthchecker", "format": "json", "prefix": "auth get-or-create"}""" - ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index"}}]""" + """{"caps": ["mon", "allow r, allow command quorum_status, allow command version", "mgr", "allow command config", "osd", "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index", "mds", "allow *"], "entity": "client.healthchecker", "format": "json", "prefix": "auth get-or-create"}""" + ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index","mds":"allow *"}}]""" self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command quorum_status, allow command version", "mgr", "allow command config", "osd", "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index"], "entity": "client.healthchecker", "format": "json", "prefix": "auth caps"}""" - ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSRKruozxiZi3lrdA==","caps":{"mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index"}}]""" + """{"caps": ["mon", "allow r, allow command quorum_status, allow command version", "mgr", "allow command config", "osd", "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index", "mds", "allow *"], "entity": "client.healthchecker", "format": "json", "prefix": "auth caps"}""" + ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSRKruozxiZi3lrdA==","caps":{"mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index","mds":"allow *"}}]""" self.cmd_output_map["""{"format": "json", "prefix": "mgr services"}"""] = ( """{"dashboard": "http://rook-ceph-mgr-a-57cf9f84bc-f4jnl:7000/", "prometheus": "http://rook-ceph-mgr-a-57cf9f84bc-f4jnl:9283/"}""" ) @@ -130,7 +130,7 @@ def _init_cmd_output_map(self): ] = """{"dashboard": "http://rook-ceph-mgr-a-57cf9f84bc-f4jnl:7000/", "prometheus": "http://rook-ceph-mgr-a-57cf9f84bc-f4jnl:9283/"}""" self.cmd_output_map[ """{"entity": "client.healthchecker", "format": "json", "prefix": "auth get"}""" - ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index"}}]""" + ] = """[{"entity":"client.healthchecker","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": "profile rbd-read-only, allow rwx pool=default.rgw.meta, allow r pool=.rgw.root, allow rw pool=default.rgw.control, allow rx pool=default.rgw.log, allow x pool=default.rgw.buckets.index","mds":"allow *"}}]""" self.cmd_output_map[ """{"entity": "client.csi-cephfs-node", "format": "json", "prefix": "auth get"}""" ] = """[]""" @@ -151,10 +151,10 @@ def _init_cmd_output_map(self): ] = """[]""" self.cmd_output_map[ """{"entity": "client.csi-cephfs-provisioner", "format": "json", "prefix": "auth get"}""" - ] = """[{"entity":"client.csi-cephfs-provisioner","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon":"allow r", "mgr":"allow rw", "osd":"allow rw tag cephfs metadata=*"}}]""" + ] = """[{"entity":"client.csi-cephfs-provisioner","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon":"allow r", "mgr":"allow rw", "osd":"allow rw tag cephfs metadata=*","mds":"allow *"}}]""" self.cmd_output_map[ - """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=*"], "entity": "client.csi-cephfs-provisioner", "format": "json", "prefix": "auth caps"}""" - ] = """[{"entity":"client.csi-cephfs-provisioner","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon":"allow r, allow command 'osd blocklist'", "mgr":"allow rw", "osd":"allow rw tag cephfs metadata=*"}}]""" + """{"caps": ["mon", "allow r, allow command 'osd blocklist'", "mgr", "allow rw", "osd", "allow rw tag cephfs metadata=*", "mds", "allow *"], "entity": "client.csi-cephfs-provisioner", "format": "json", "prefix": "auth caps"}""" + ] = """[{"entity":"client.csi-cephfs-provisioner","key":"AQDFkbNeft5bFRAATndLNUSEKruozxiZi3lrdA==","caps":{"mon":"allow r, allow command 'osd blocklist'", "mgr":"allow rw", "osd":"allow rw tag cephfs metadata=*","mds":"allow *"}}]""" self.cmd_output_map['{"format": "json", "prefix": "status"}'] = ceph_status_str def shutdown(self): @@ -868,6 +868,7 @@ def get_cephfs_provisioner_caps_and_entity(self): "mon": "allow r, allow command 'osd blocklist'", "mgr": "allow rw", "osd": "allow rw tag cephfs metadata=*", + "mds": "allow *", } if self._arg_parser.restricted_auth_permission: k8s_cluster_name = self._arg_parser.k8s_cluster_name @@ -1017,6 +1018,7 @@ def get_defaultUser_caps_and_entity(self): "mon": "allow r, allow command quorum_status, allow command version", "mgr": "allow command config", "osd": f"profile rbd-read-only, allow rwx pool={self._arg_parser.rgw_pool_prefix}.rgw.meta, allow r pool=.rgw.root, allow rw pool={self._arg_parser.rgw_pool_prefix}.rgw.control, allow rx pool={self._arg_parser.rgw_pool_prefix}.rgw.log, allow x pool={self._arg_parser.rgw_pool_prefix}.rgw.buckets.index", + "mds": "allow *", } return caps, entity From fa2941d098f98fafc9529ee6c6f989ad29fce27e Mon Sep 17 00:00:00 2001 From: Travis Nielsen Date: Tue, 17 Sep 2024 14:24:40 -0600 Subject: [PATCH 25/54] core: enable annotations on crash collector The crash collector daemon had missed the ability to add custom annotations via the cephcluster CR, as already supported for all the other daemons. Signed-off-by: Travis Nielsen --- pkg/apis/ceph.rook.io/v1/annotations.go | 5 +++++ pkg/apis/ceph.rook.io/v1/annotations_test.go | 11 ++++++++--- pkg/operator/ceph/cluster/nodedaemon/crash.go | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/apis/ceph.rook.io/v1/annotations.go b/pkg/apis/ceph.rook.io/v1/annotations.go index 9610420be28c..efd40793f01f 100644 --- a/pkg/apis/ceph.rook.io/v1/annotations.go +++ b/pkg/apis/ceph.rook.io/v1/annotations.go @@ -77,6 +77,11 @@ func GetCmdReporterAnnotations(a AnnotationsSpec) Annotations { return mergeAllAnnotationsWithKey(a, KeyCmdReporter) } +// GetCrashCollectorAnnotations returns the Annotations for the crash collector +func GetCrashCollectorAnnotations(a AnnotationsSpec) Annotations { + return mergeAllAnnotationsWithKey(a, KeyCrashCollector) +} + func GetClusterMetadataAnnotations(a AnnotationsSpec) Annotations { return a[KeyClusterMetadata] } diff --git a/pkg/apis/ceph.rook.io/v1/annotations_test.go b/pkg/apis/ceph.rook.io/v1/annotations_test.go index b832690c3567..c3137d8ed549 100644 --- a/pkg/apis/ceph.rook.io/v1/annotations_test.go +++ b/pkg/apis/ceph.rook.io/v1/annotations_test.go @@ -58,9 +58,10 @@ func TestCephAnnotationsMerge(t *testing.T) { // Merge with "all" testAnnotations = AnnotationsSpec{ - "all": {"allkey1": "allval1", "allkey2": "allval2"}, - "mgr": {"mgrkey": "mgrval"}, - "cmdreporter": {"myversions": "detect"}, + "all": {"allkey1": "allval1", "allkey2": "allval2"}, + "mgr": {"mgrkey": "mgrval"}, + "cmdreporter": {"myversions": "detect"}, + "crashcollector": {"crash": "crashval"}, } a = GetMonAnnotations(testAnnotations) assert.Equal(t, "allval1", a["allkey1"]) @@ -75,6 +76,10 @@ func TestCephAnnotationsMerge(t *testing.T) { assert.Equal(t, "detect", b["myversions"]) assert.Equal(t, "allval1", b["allkey1"]) assert.Equal(t, "allval2", b["allkey2"]) + c := GetCrashCollectorAnnotations(testAnnotations) + assert.Equal(t, "crashval", c["crash"]) + assert.Equal(t, "allval1", c["allkey1"]) + assert.Equal(t, "allval2", c["allkey2"]) } func TestAnnotationsSpec(t *testing.T) { diff --git a/pkg/operator/ceph/cluster/nodedaemon/crash.go b/pkg/operator/ceph/cluster/nodedaemon/crash.go index 97abb34a3f9d..87ed94fb7ee8 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/crash.go +++ b/pkg/operator/ceph/cluster/nodedaemon/crash.go @@ -124,6 +124,7 @@ func (r *ReconcileNode) createOrUpdateCephCrash(node corev1.Node, tolerations [] ServiceAccountName: k8sutil.DefaultServiceAccount, }, } + cephv1.GetCrashCollectorAnnotations(cephCluster.Spec.Annotations).ApplyToObjectMeta(&deploy.Spec.Template.ObjectMeta) return nil } From afad40e404ae2af7ab0419fc6923a31fe59a2383 Mon Sep 17 00:00:00 2001 From: Praveen M Date: Wed, 18 Sep 2024 11:40:07 +0530 Subject: [PATCH 26/54] csi: update csi-addons to v0.10.0 The csi-addons v0.10.0 release is now available. Ref: https://github.com/csi-addons/kubernetes-csi-addons/releases/tag/v0.10.0 Signed-off-by: Praveen M --- Documentation/Helm-Charts/operator-chart.md | 2 +- .../Ceph-CSI/ceph-csi-drivers.md | 32 +++++++++---------- .../Ceph-CSI/custom-images.md | 2 +- deploy/charts/rook-ceph/values.yaml | 2 +- deploy/examples/images.txt | 2 +- deploy/examples/operator-openshift.yaml | 2 +- deploy/examples/operator.yaml | 2 +- go.mod | 6 ++-- go.sum | 16 +++++----- pkg/apis/go.mod | 6 ++-- pkg/apis/go.sum | 14 ++++---- pkg/operator/ceph/csi/spec.go | 2 +- tests/scripts/csiaddons.sh | 2 +- 13 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Documentation/Helm-Charts/operator-chart.md b/Documentation/Helm-Charts/operator-chart.md index 7ff471e7df16..ebb42204fb1f 100644 --- a/Documentation/Helm-Charts/operator-chart.md +++ b/Documentation/Helm-Charts/operator-chart.md @@ -67,7 +67,7 @@ The following table lists the configurable parameters of the rook-operator chart | `csi.clusterName` | Cluster name identifier to set as metadata on the CephFS subvolume and RBD images. This will be useful in cases like for example, when two container orchestrator clusters (Kubernetes/OCP) are using a single ceph cluster | `nil` | | `csi.csiAddons.enabled` | Enable CSIAddons | `false` | | `csi.csiAddons.repository` | CSIAddons sidecar image repository | `"quay.io/csiaddons/k8s-sidecar"` | -| `csi.csiAddons.tag` | CSIAddons sidecar image tag | `"v0.9.1"` | +| `csi.csiAddons.tag` | CSIAddons sidecar image tag | `"v0.10.0"` | | `csi.csiAddonsPort` | CSI Addons server port | `9070` | | `csi.csiCephFSPluginResource` | CEPH CSI CephFS plugin resource requirement list | see values.yaml | | `csi.csiCephFSPluginVolume` | The volume of the CephCSI CephFS plugin DaemonSet | `nil` | diff --git a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md index dc5df80b8847..d06bb58ae9d4 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md +++ b/Documentation/Storage-Configuration/Ceph-CSI/ceph-csi-drivers.md @@ -166,9 +166,9 @@ that the controller inspects and forwards to one or more CSI-Addons sidecars for Deploy the controller by running the following commands: ```console -kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.9.1/crds.yaml -kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.9.1/rbac.yaml -kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.9.1/setup-controller.yaml +kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.10.0/crds.yaml +kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.10.0/rbac.yaml +kubectl create -f https://github.com/csi-addons/kubernetes-csi-addons/releases/download/v0.10.0/setup-controller.yaml ``` This creates the required CRDs and configures permissions. @@ -196,22 +196,22 @@ Execute the following to enable the CSI-Addons sidecars: CSI-Addons supports the following operations: * Reclaim Space - * [Creating a ReclaimSpaceJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#reclaimspacejob) - * [Creating a ReclaimSpaceCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#reclaimspacecronjob) - * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#annotating-perstentvolumeclaims) - * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#annotating-namespace) - * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/reclaimspace.md#annotating-storageclass) + * [Creating a ReclaimSpaceJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/reclaimspace.md#reclaimspacejob) + * [Creating a ReclaimSpaceCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/reclaimspace.md#reclaimspacecronjob) + * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/reclaimspace.md#annotating-perstentvolumeclaims) + * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/reclaimspace.md#annotating-namespace) + * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/reclaimspace.md#annotating-storageclass) * Network Fencing - * [Creating a NetworkFence](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/networkfence.md) + * [Creating a NetworkFence](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/networkfence.md) * Volume Replication - * [Creating VolumeReplicationClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/volumereplicationclass.md) - * [Creating VolumeReplication CR](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/volumereplication.md) + * [Creating VolumeReplicationClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/volumereplicationclass.md) + * [Creating VolumeReplication CR](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/volumereplication.md) * Key Rotation Job for PV encryption - * [Creating EncryptionKeyRotationJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#encryptionkeyrotationjob) - * [Creating EncryptionKeyRotationCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#encryptionkeyrotationcronjob) - * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#annotating-persistentvolumeclaims) - * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#annotating-namespace) - * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.9.1/docs/encryptionkeyrotation.md#annotating-storageclass) + * [Creating EncryptionKeyRotationJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/encryptionkeyrotation.md#encryptionkeyrotationjob) + * [Creating EncryptionKeyRotationCronJob](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/encryptionkeyrotation.md#encryptionkeyrotationcronjob) + * [Annotating PersistentVolumeClaims](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/encryptionkeyrotation.md#annotating-persistentvolumeclaims) + * [Annotating Namespace](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/encryptionkeyrotation.md#annotating-namespace) + * [Annotating StorageClass](https://github.com/csi-addons/kubernetes-csi-addons/blob/v0.10.0/docs/encryptionkeyrotation.md#annotating-storageclass) ## Enable RBD and CephFS Encryption Support diff --git a/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md b/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md index 8629bbcc1b55..86beab48d9a1 100644 --- a/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md +++ b/Documentation/Storage-Configuration/Ceph-CSI/custom-images.md @@ -24,7 +24,7 @@ ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v5.0.1" ROOK_CSI_ATTACHER_IMAGE: "registry.k8s.io/sig-storage/csi-attacher:v4.6.1" ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.11.1" ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1" -ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.9.1" +ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.10.0" ``` ### **Use private repository** diff --git a/deploy/charts/rook-ceph/values.yaml b/deploy/charts/rook-ceph/values.yaml index 387712a37e2f..4cf7c298d6a4 100644 --- a/deploy/charts/rook-ceph/values.yaml +++ b/deploy/charts/rook-ceph/values.yaml @@ -537,7 +537,7 @@ csi: # -- CSIAddons sidecar image repository repository: quay.io/csiaddons/k8s-sidecar # -- CSIAddons sidecar image tag - tag: v0.9.1 + tag: v0.10.0 nfs: # -- Enable the nfs csi driver diff --git a/deploy/examples/images.txt b/deploy/examples/images.txt index faab1198c12c..b84f8adbdd97 100644 --- a/deploy/examples/images.txt +++ b/deploy/examples/images.txt @@ -3,7 +3,7 @@ quay.io/ceph/ceph:v18.2.4 quay.io/ceph/cosi:v0.1.2 quay.io/cephcsi/cephcsi:v3.12.2 - quay.io/csiaddons/k8s-sidecar:v0.9.1 + quay.io/csiaddons/k8s-sidecar:v0.10.0 registry.k8s.io/sig-storage/csi-attacher:v4.6.1 registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1 registry.k8s.io/sig-storage/csi-provisioner:v5.0.1 diff --git a/deploy/examples/operator-openshift.yaml b/deploy/examples/operator-openshift.yaml index 396f022dd420..82ed8f14f141 100644 --- a/deploy/examples/operator-openshift.yaml +++ b/deploy/examples/operator-openshift.yaml @@ -558,7 +558,7 @@ data: CSI_ENABLE_CSIADDONS: "false" # Enable watch for faster recovery from rbd rwo node loss ROOK_WATCH_FOR_NODE_FAILURE: "true" - # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.9.1" + # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.10.0" # The GCSI RPC timeout value (in seconds). It should be >= 120. If this variable is not set or is an invalid value, it's default to 150. CSI_GRPC_TIMEOUT_SECONDS: "150" diff --git a/deploy/examples/operator.yaml b/deploy/examples/operator.yaml index 1d60f5638559..e0faa4d2a6b4 100644 --- a/deploy/examples/operator.yaml +++ b/deploy/examples/operator.yaml @@ -508,7 +508,7 @@ data: CSI_ENABLE_CSIADDONS: "false" # Enable watch for faster recovery from rbd rwo node loss ROOK_WATCH_FOR_NODE_FAILURE: "true" - # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.9.1" + # ROOK_CSIADDONS_IMAGE: "quay.io/csiaddons/k8s-sidecar:v0.10.0" # The CSI GRPC timeout value (in seconds). It should be >= 120. If this variable is not set or is an invalid value, it's default to 150. CSI_GRPC_TIMEOUT_SECONDS: "150" diff --git a/go.mod b/go.mod index bc4e4229b027..add877c686ef 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/rook/rook -go 1.22.0 +go 1.22.6 -toolchain go1.22.5 +toolchain go1.22.7 replace ( github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.4.1 @@ -21,7 +21,7 @@ require ( github.com/ceph/ceph-csi-operator/api v0.0.0-20240819112305-88e6db254d6c github.com/ceph/go-ceph v0.29.0 github.com/coreos/pkg v0.0.0-20230601102743-20bbbf26f4d8 - github.com/csi-addons/kubernetes-csi-addons v0.9.1 + github.com/csi-addons/kubernetes-csi-addons v0.10.0 github.com/gemalto/kmip-go v0.0.10 github.com/go-ini/ini v1.67.0 github.com/google/go-cmp v0.6.0 diff --git a/go.sum b/go.sum index f52f6da23a6c..b58bb5fb030f 100644 --- a/go.sum +++ b/go.sum @@ -214,8 +214,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/csi-addons/kubernetes-csi-addons v0.9.1 h1:2m8/Pls7Ws3ld1zr/w6lL6BWwsXqqLg2JnW0jP8AX6I= -github.com/csi-addons/kubernetes-csi-addons v0.9.1/go.mod h1:32kTa/Ngp7hMK2GEjx+Zk8yfKupR5WG4JG+oRzkM1TM= +github.com/csi-addons/kubernetes-csi-addons v0.10.0 h1:bBc6nb1oROz4RLhqoLFNeGymk2jIRXcx7LvAup9+3Jg= +github.com/csi-addons/kubernetes-csi-addons v0.10.0/go.mod h1:nqi369YuYMIdysBbHjtYJcWFpcxujPot1HS6tnNWBV4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -465,8 +465,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -724,8 +724,8 @@ github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8Ay github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= -github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw= -github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= +github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -740,8 +740,8 @@ github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/openshift/api v0.0.0-20210105115604-44119421ec6b/go.mod h1:aqU5Cq+kqKKPbDMqxo9FojgDeSpNJI7iuskjXjtojDg= github.com/openshift/api v0.0.0-20240301093301-ce10821dc999 h1:+S998xHiJApsJZjRAO8wyedU9GfqFd8mtwWly6LqHDo= github.com/openshift/api v0.0.0-20240301093301-ce10821dc999/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod index 495151118d30..0230510aa324 100644 --- a/pkg/apis/go.mod +++ b/pkg/apis/go.mod @@ -1,8 +1,8 @@ module github.com/rook/rook/pkg/apis -go 1.22.0 +go 1.22.6 -toolchain go1.22.5 +toolchain go1.22.7 replace ( github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.4.1 @@ -32,6 +32,8 @@ require ( github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/onsi/ginkgo/v2 v2.20.2 // indirect + github.com/onsi/gomega v1.34.2 // indirect github.com/x448/float16 v0.8.4 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/client-go v0.31.1 // indirect diff --git a/pkg/apis/go.sum b/pkg/apis/go.sum index 0e8f95c6872e..f0be261e2938 100644 --- a/pkg/apis/go.sum +++ b/pkg/apis/go.sum @@ -388,8 +388,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -610,8 +610,8 @@ github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8Ay github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= -github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw= -github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= +github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -625,8 +625,8 @@ github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/openshift/api v0.0.0-20210105115604-44119421ec6b/go.mod h1:aqU5Cq+kqKKPbDMqxo9FojgDeSpNJI7iuskjXjtojDg= github.com/openshift/api v0.0.0-20240301093301-ce10821dc999 h1:+S998xHiJApsJZjRAO8wyedU9GfqFd8mtwWly6LqHDo= github.com/openshift/api v0.0.0-20240301093301-ce10821dc999/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= @@ -820,8 +820,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/pkg/operator/ceph/csi/spec.go b/pkg/operator/ceph/csi/spec.go index ab029bce5ec4..de30e74a87c0 100644 --- a/pkg/operator/ceph/csi/spec.go +++ b/pkg/operator/ceph/csi/spec.go @@ -156,7 +156,7 @@ var ( DefaultAttacherImage = "registry.k8s.io/sig-storage/csi-attacher:v4.6.1" DefaultSnapshotterImage = "registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1" DefaultResizerImage = "registry.k8s.io/sig-storage/csi-resizer:v1.11.1" - DefaultCSIAddonsImage = "quay.io/csiaddons/k8s-sidecar:v0.9.1" + DefaultCSIAddonsImage = "quay.io/csiaddons/k8s-sidecar:v0.10.0" // image pull policy DefaultCSIImagePullPolicy = string(corev1.PullIfNotPresent) diff --git a/tests/scripts/csiaddons.sh b/tests/scripts/csiaddons.sh index 60daf61e217e..6b91a847b289 100755 --- a/tests/scripts/csiaddons.sh +++ b/tests/scripts/csiaddons.sh @@ -16,7 +16,7 @@ set -xEo pipefail -CSIADDONS_VERSION="v0.9.1" +CSIADDONS_VERSION="v0.10.0" CSIADDONS_CRD_NAME="csiaddonsnodes.csiaddons.openshift.io" CSIADDONS_CONTAINER_NAME="csi-addons" From f6474445152822ff1635fe33cb84565b254031e0 Mon Sep 17 00:00:00 2001 From: subhamkrai Date: Thu, 19 Sep 2024 15:03:59 +0530 Subject: [PATCH 27/54] ci: fix ci permission issue with minikube start this commit upgrade the minikube, k8s, crictl versions in CI and also fix permission error in the github runner. Signed-off-by: subhamkrai --- .github/workflows/canary-test-config/action.yaml | 2 +- tests/scripts/github-action-helper.sh | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/canary-test-config/action.yaml b/.github/workflows/canary-test-config/action.yaml index e38c6f8c3484..358e08c02eb1 100644 --- a/.github/workflows/canary-test-config/action.yaml +++ b/.github/workflows/canary-test-config/action.yaml @@ -19,7 +19,7 @@ runs: - name: Setup Minikube shell: bash --noprofile --norc -eo pipefail -x {0} run: | - tests/scripts/github-action-helper.sh install_minikube_with_none_driver v1.30.0 + tests/scripts/github-action-helper.sh install_minikube_with_none_driver v1.31.0 - name: install deps shell: bash --noprofile --norc -eo pipefail -x {0} diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index cd10c8bb1a14..277a6f5f5739 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -707,8 +707,8 @@ function test_csi_nfs_workload { } function install_minikube_with_none_driver() { - CRICTL_VERSION="v1.30.0" - MINIKUBE_VERSION="v1.32.0" + CRICTL_VERSION="v1.31.1" + MINIKUBE_VERSION="v1.34.0" sudo apt update sudo apt install -y conntrack socat @@ -716,16 +716,16 @@ function install_minikube_with_none_driver() { sudo dpkg -i minikube_latest_amd64.deb rm -f minikube_latest_amd64.deb - curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.9/cri-dockerd_0.3.9.3-0.ubuntu-focal_amd64.deb - sudo dpkg -i cri-dockerd_0.3.9.3-0.ubuntu-focal_amd64.deb - rm -f cri-dockerd_0.3.9.3-0.ubuntu-focal_amd64.deb + curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.15/cri-dockerd_0.3.15.3-0.ubuntu-focal_amd64.deb + sudo dpkg -i cri-dockerd_0.3.15.3-0.ubuntu-focal_amd64.deb + rm -f cri-dockerd_0.3.15.3-0.ubuntu-focal_amd64.deb wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$CRICTL_VERSION/crictl-$CRICTL_VERSION-linux-amd64.tar.gz sudo tar zxvf crictl-$CRICTL_VERSION-linux-amd64.tar.gz -C /usr/local/bin rm -f crictl-$CRICTL_VERSION-linux-amd64.tar.gz sudo sysctl fs.protected_regular=0 - CNI_PLUGIN_VERSION="v1.4.0" + CNI_PLUGIN_VERSION="v1.5.1" CNI_PLUGIN_TAR="cni-plugins-linux-amd64-$CNI_PLUGIN_VERSION.tgz" # change arch if not on amd64 CNI_PLUGIN_INSTALL_DIR="/opt/cni/bin" @@ -735,7 +735,7 @@ function install_minikube_with_none_driver() { rm "$CNI_PLUGIN_TAR" export MINIKUBE_HOME=$HOME CHANGE_MINIKUBE_NONE_USER=true KUBECONFIG=$HOME/.kube/config - sudo -E minikube start --kubernetes-version="$1" --driver=none --memory 6g --cpus=2 --addons ingress --cni=calico + minikube start --kubernetes-version="$1" --driver=none --memory 6g --cpus=2 --addons ingress --cni=calico } FUNCTION="$1" From 99337b648d61d65d354324ba1d9d584cef52e908 Mon Sep 17 00:00:00 2001 From: subhamkrai Date: Fri, 20 Sep 2024 17:03:37 +0530 Subject: [PATCH 28/54] build: update toolchain to latest version this commits update the toolchain version to go v1.22.7 Signed-off-by: subhamkrai --- go.mod | 2 +- pkg/apis/go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 789a8464d54b..a46e225edce7 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/rook/rook go 1.22.0 -toolchain go1.22.5 +toolchain go1.22.7 replace ( github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.4.1 diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod index 27790be77987..b1670dd52b88 100644 --- a/pkg/apis/go.mod +++ b/pkg/apis/go.mod @@ -2,7 +2,7 @@ module github.com/rook/rook/pkg/apis go 1.22.0 -toolchain go1.22.5 +toolchain go1.22.7 replace ( github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.4.1 From 467578d368763a9c0964b6a669407747881eee7b Mon Sep 17 00:00:00 2001 From: parth-gr Date: Thu, 12 Sep 2024 13:33:52 +0530 Subject: [PATCH 29/54] docs: update external docs with a better structure step1 to improve the external docs and make it more clear to end user Signed-off-by: parth-gr --- .../CRDs/Cluster/external-cluster/.pages | 4 + .../external-cluster/advance-external.md | 70 ++++ .../external-cluster/consumer-import.md | 76 ++++ .../external-cluster/external-cluster.md | 324 +----------------- .../external-cluster/provider-export.md | 125 +++++++ .../external-cluster/upgrade-external.md | 58 ++++ 6 files changed, 345 insertions(+), 312 deletions(-) create mode 100644 Documentation/CRDs/Cluster/external-cluster/advance-external.md create mode 100644 Documentation/CRDs/Cluster/external-cluster/consumer-import.md create mode 100644 Documentation/CRDs/Cluster/external-cluster/provider-export.md create mode 100644 Documentation/CRDs/Cluster/external-cluster/upgrade-external.md diff --git a/Documentation/CRDs/Cluster/external-cluster/.pages b/Documentation/CRDs/Cluster/external-cluster/.pages index 5a3a6ca9e41c..a225b612db12 100644 --- a/Documentation/CRDs/Cluster/external-cluster/.pages +++ b/Documentation/CRDs/Cluster/external-cluster/.pages @@ -1,3 +1,7 @@ nav: - external-cluster.md + - provider-export.md + - consumer-import.md + - upgrade-external.md + - advance-external.md - topology-for-external-mode.md diff --git a/Documentation/CRDs/Cluster/external-cluster/advance-external.md b/Documentation/CRDs/Cluster/external-cluster/advance-external.md new file mode 100644 index 000000000000..5034b0da9a69 --- /dev/null +++ b/Documentation/CRDs/Cluster/external-cluster/advance-external.md @@ -0,0 +1,70 @@ +# External Cluster Options + +## NFS storage + +Rook suggests a different mechanism for making use of an [NFS service running on the external Ceph standalone cluster](../../../Storage-Configuration/NFS/nfs-csi-driver.md#consuming-nfs-from-an-external-source), if desired. + +## Exporting Rook to another cluster + +If you have multiple K8s clusters running, and want to use the local `rook-ceph` cluster as the central storage, +you can export the settings from this cluster with the following steps. + +1. Copy create-external-cluster-resources.py into the directory `/etc/ceph/` of the toolbox. + + ```console + toolbox=$(kubectl get pod -l app=rook-ceph-tools -n rook-ceph -o jsonpath='{.items[*].metadata.name}') + kubectl -n rook-ceph cp deploy/examples/external/create-external-cluster-resources.py $toolbox:/etc/ceph + ``` + +2. Exec to the toolbox pod and execute create-external-cluster-resources.py with needed options to create required [users and keys](/Documentation/CRDs/Cluster/external-cluster/provider-export.md#1-create-all-users-and-keys). + +!!! important + For other clusters to connect to storage in this cluster, Rook must be configured with a networking configuration that is accessible from other clusters. Most commonly this is done by enabling host networking in the CephCluster CR so the Ceph daemons will be addressable by their host IPs. + +## Admin privileges + +If in case the cluster needs the admin keyring to configure, update the admin key `rook-ceph-mon` secret with client.admin keyring + +!!! note + Sharing the admin key with the external cluster is not generally recommended + +1. Get the `client.admin` keyring from the ceph cluster + + ```console + ceph auth get client.admin + ``` + +2. Update two values in the `rook-ceph-mon` secret: + - `ceph-username`: Set to `client.admin` + - `ceph-secret`: Set the client.admin keyring + +After restarting the rook operator (and the toolbox if in use), rook will configure ceph with admin privileges. + +## Connect to an External Object Store + +Create the [external object store CR](https://github.com/rook/rook/blob/master/deploy/examples/external/object-external.yaml) to configure connection to external gateways. + +```console +cd deploy/examples/external +kubectl create -f object-external.yaml +``` + +Consume the S3 Storage, in two different ways: + +1. Create an [Object store user](https://github.com/rook/rook/blob/master/deploy/examples/object-user.yaml) for credentials to access the S3 endpoint. + + ```console + cd deploy/examples + kubectl create -f object-user.yaml + ``` + +2. Create a [bucket storage class](https://github.com/rook/rook/blob/master/deploy/examples/external/storageclass-bucket-delete.yaml) where a client can request creating buckets and then create the [Object Bucket Claim](https://github.com/rook/rook/blob/master/deploy/examples/external/object-bucket-claim-delete.yaml), which will create an individual bucket for reading and writing objects. + + ```console + cd deploy/examples/external + kubectl create -f storageclass-bucket-delete.yaml + kubectl create -f object-bucket-claim-delete.yaml + ``` + +!!! hint + For more details see the [Object Store topic](../../../Storage-Configuration/Object-Storage-RGW/object-storage.md#connect-to-an-external-object-store) diff --git a/Documentation/CRDs/Cluster/external-cluster/consumer-import.md b/Documentation/CRDs/Cluster/external-cluster/consumer-import.md new file mode 100644 index 000000000000..3a8a5f352b47 --- /dev/null +++ b/Documentation/CRDs/Cluster/external-cluster/consumer-import.md @@ -0,0 +1,76 @@ +# Import Ceph configuration to the Rook consumer cluster + +## Installation types + +Install Rook in the the consumer cluster, either with [Helm](#helm-installation) +or the [manifests](#manifest-installation). + +### Helm Installation + +To install with Helm, the rook cluster helm chart will configure the necessary resources for the external cluster with the example `values-external.yaml`. + +```console +clusterNamespace=rook-ceph +operatorNamespace=rook-ceph +cd deploy/examples/charts/rook-ceph-cluster +helm repo add rook-release https://charts.rook.io/release +helm install --create-namespace --namespace $clusterNamespace rook-ceph rook-release/rook-ceph -f values.yaml +helm install --create-namespace --namespace $clusterNamespace rook-ceph-cluster \ +--set operatorNamespace=$operatorNamespace rook-release/rook-ceph-cluster -f values-external.yaml +``` + +### Manifest Installation + +If not installing with Helm, here are the steps to install with manifests. + +1. Deploy Rook, create [common.yaml](https://github.com/rook/rook/blob/master/deploy/examples/common.yaml), [crds.yaml](https://github.com/rook/rook/blob/master/deploy/examples/crds.yaml) and [operator.yaml](https://github.com/rook/rook/blob/master/deploy/examples/operator.yaml) manifests. + +2. Create [common-external.yaml](https://github.com/rook/rook/blob/master/deploy/examples/external/common-external.yaml) and [cluster-external.yaml](https://github.com/rook/rook/blob/master/deploy/examples/external/cluster-external.yaml) + +## Import the Provider Data + +1. Paste the above output from `create-external-cluster-resources.py` into your current shell to allow importing the provider data. + +2. The import script in the next step uses the current kubeconfig context by + default. If you want to specify the kubernetes cluster to use without + changing the current context, you can specify the cluster name by setting + the KUBECONTEXT environment variable. + + ```console + export KUBECONTEXT= + ``` + +3. Here is the link for [import](https://github.com/rook/rook/blob/master/deploy/examples/external/import-external-cluster.sh) script. The script has used the `rook-ceph` namespace and few parameters that also have referenced from namespace variable. If user's external cluster has a different namespace, change the namespace parameter in the script according to their external cluster. For example with `new-namespace` namespace, this change is needed on the namespace parameter in the script. + + ```console + NAMESPACE=${NAMESPACE:="new-namespace"} + ``` + +4. Run the import script. + + !!! note + If your Rook cluster nodes are running a kernel earlier than or equivalent to 5.4, remove + `fast-diff, object-map, deep-flatten,exclusive-lock` from the `imageFeatures` line. + + ```console + . import-external-cluster.sh + ``` + +## Cluster Verification + +1. Verify the consumer cluster is connected to the provider ceph cluster: + + ```console + $ kubectl -n rook-ceph get CephCluster + NAME DATADIRHOSTPATH MONCOUNT AGE STATE HEALTH + rook-ceph-external /var/lib/rook 162m Connected HEALTH_OK + ``` + +2. Verify the creation of the storage class depending on the rbd pools and filesystem provided. + `ceph-rbd` and `cephfs` would be the respective names for the RBD and CephFS storage classes. + + ```console + kubectl -n rook-ceph get sc + ``` + +3. Create a [persistent volume](https://github.com/rook/rook/tree/master/deploy/examples/csi) based on these StorageClass. diff --git a/Documentation/CRDs/Cluster/external-cluster/external-cluster.md b/Documentation/CRDs/Cluster/external-cluster/external-cluster.md index adc7405f2545..28dd279bfbf1 100644 --- a/Documentation/CRDs/Cluster/external-cluster/external-cluster.md +++ b/Documentation/CRDs/Cluster/external-cluster/external-cluster.md @@ -8,9 +8,9 @@ In external mode, Rook will provide the configuration for the CSI driver and oth ## External configuration -* Source cluster: The cluster providing the data, usually configured by [cephadm](https://docs.ceph.com/en/pacific/cephadm/#cephadm) +* Provider cluster: The cluster providing the data, usually configured by [cephadm](https://docs.ceph.com/en/pacific/cephadm/#cephadm) -* Consumer cluster: The K8s cluster that will be consuming the external source cluster +* Consumer cluster: The K8s cluster that will be consuming the external provider cluster ## Prerequisites @@ -19,324 +19,24 @@ Create the desired types of storage in the provider Ceph cluster: * [RBD pools](https://docs.ceph.com/en/latest/rados/operations/pools/#create-a-pool) * [CephFS filesystem](https://docs.ceph.com/en/quincy/cephfs/createfs/) -## Commands on the source Ceph cluster +## Connect the external Ceph Provider cluster to the Rook consumer cluster -In order to configure an external Ceph cluster with Rook, we need to extract some information in order to connect to that cluster. +1) [Export config from the Provider Ceph cluster](/Documentation/CRDs/Cluster/external-cluster/provider-export.md). Configuration must be exported by the Ceph admin, such as a Ceph keyring and mon endpoints, that allows connection to the Ceph cluster. -### 1. Create all users and keys +2) [Import config to the Rook consumer cluster](/Documentation/CRDs/Cluster/external-cluster/consumer-import.md). The configuration exported from the Ceph cluster is imported to Rook to provide the needed connection details. -Run the python script [create-external-cluster-resources.py](https://github.com/rook/rook/blob/master/deploy/examples/external/create-external-cluster-resources.py) for creating all users and keys. +## Advance Options -```console -python3 create-external-cluster-resources.py --rbd-data-pool-name --cephfs-filesystem-name --rgw-endpoint --namespace --format bash -``` +* [NFS storage](/Documentation/CRDs/Cluster/external-cluster/advance-external.md#nfs-storage) -* `--namespace`: Namespace where CephCluster will run, for example `rook-ceph` -* `--format bash`: The format of the output -* `--rbd-data-pool-name`: The name of the RBD data pool -* `--alias-rbd-data-pool-name`: Provides an alias for the RBD data pool name, necessary if a special character is present in the pool name such as a period or underscore -* `--rgw-endpoint`: (optional) The RADOS Gateway endpoint in the format `:` or `:`. -* `--rgw-pool-prefix`: (optional) The prefix of the RGW pools. If not specified, the default prefix is `default` -* `--rgw-tls-cert-path`: (optional) RADOS Gateway endpoint TLS certificate file path -* `--rgw-skip-tls`: (optional) Ignore TLS certification validation when a self-signed certificate is provided (NOT RECOMMENDED) -* `--rbd-metadata-ec-pool-name`: (optional) Provides the name of erasure coded RBD metadata pool, used for creating ECRBDStorageClass. -* `--monitoring-endpoint`: (optional) Ceph Manager prometheus exporter endpoints (comma separated list of IP entries of active and standby mgrs) -* `--monitoring-endpoint-port`: (optional) Ceph Manager prometheus exporter port -* `--skip-monitoring-endpoint`: (optional) Skip prometheus exporter endpoints, even if they are available. Useful if the prometheus module is not enabled -* `--ceph-conf`: (optional) Provide a Ceph conf file -* `--keyring`: (optional) Path to Ceph keyring file, to be used with `--ceph-conf` -* `--k8s-cluster-name`: (optional) Kubernetes cluster name -* `--output`: (optional) Output will be stored into the provided file -* `--dry-run`: (optional) Prints the executed commands without running them -* `--run-as-user`: (optional) Provides a user name to check the cluster's health status, must be prefixed by `client`. -* `--cephfs-metadata-pool-name`: (optional) Provides the name of the cephfs metadata pool -* `--cephfs-filesystem-name`: (optional) The name of the filesystem, used for creating CephFS StorageClass -* `--cephfs-data-pool-name`: (optional) Provides the name of the CephFS data pool, used for creating CephFS StorageClass -* `--rados-namespace`: (optional) Divides a pool into separate logical namespaces, used for creating RBD PVC in a CephBlockPoolRadosNamespace (should be lower case) -* `--subvolume-group`: (optional) Provides the name of the subvolume group, used for creating CephFS PVC in a subvolumeGroup -* `--rgw-realm-name`: (optional) Provides the name of the rgw-realm -* `--rgw-zone-name`: (optional) Provides the name of the rgw-zone -* `--rgw-zonegroup-name`: (optional) Provides the name of the rgw-zone-group -* `--upgrade`: (optional) Upgrades the cephCSIKeyrings(For example: client.csi-cephfs-provisioner) and client.healthchecker ceph users with new permissions needed for the new cluster version and older permission will still be applied. -* `--restricted-auth-permission`: (optional) Restrict cephCSIKeyrings auth permissions to specific pools, and cluster. Mandatory flags that need to be set are `--rbd-data-pool-name`, and `--k8s-cluster-name`. `--cephfs-filesystem-name` flag can also be passed in case of CephFS user restriction, so it can restrict users to particular CephFS filesystem. -* `--v2-port-enable`: (optional) Enables the v2 mon port (3300) for mons. -* `--topology-pools`: (optional) Comma-separated list of topology-constrained rbd pools -* `--topology-failure-domain-label`: (optional) K8s cluster failure domain label (example: zone, rack, or host) for the topology-pools that match the ceph domain -* `--topology-failure-domain-values`: (optional) Comma-separated list of the k8s cluster failure domain values corresponding to each of the pools in the `topology-pools` list -* `--config-file`: Path to the configuration file, Priority: command-line-args > config.ini values > default values +* [Exporting Rook to another cluster](/Documentation/CRDs/Cluster/external-cluster/advance-external.md#exporting-rook-to-another-cluster) -### Config-file +* [Run consumer Rook cluster with Admin privileges](/Documentation/CRDs/Cluster/external-cluster/advance-external.md#admin-privileges) -Use the config file to set the user configuration file, add the flag `--config-file` to set the file path. - -Example: - -`/config.ini` - -```console -[Configurations] -format = bash -cephfs-filesystem-name = -rbd-data-pool-name = -... -``` - -```console -python3 create-external-cluster-resources.py --config-file /config.ini -``` - -!!! note - You can use both config file and other arguments at the same time - Priority: command-line-args > config.ini file values > default values - - -### Multi-tenancy - -To enable multi-tenancy, run the script with the `--restricted-auth-permission` flag and pass the mandatory flags with it, -It will generate the secrets which you can use for creating new `Consumer cluster` deployment using the same `Source cluster`(ceph cluster). -So you would be running different isolated consumer clusters on top of single `Source cluster`. - -!!! note - Restricting the csi-users per pool, and per cluster will require creating new csi-users and new secrets for that csi-users. - So apply these secrets only to new `Consumer cluster` deployment while using the same `Source cluster`. - -```console -python3 create-external-cluster-resources.py --cephfs-filesystem-name --rbd-data-pool-name --k8s-cluster-name --restricted-auth-permission true --format --rgw-endpoint --namespace -``` - -### RGW Multisite - -Pass the `--rgw-realm-name`, `--rgw-zonegroup-name` and `--rgw-zone-name` flags to create the admin ops user in a master zone, zonegroup and realm. -See the [Multisite doc](https://docs.ceph.com/en/quincy/radosgw/multisite/#configuring-a-master-zone) for creating a zone, zonegroup and realm. - -```console -python3 create-external-cluster-resources.py --rbd-data-pool-name --format bash --rgw-endpoint --rgw-realm-name > --rgw-zonegroup-name --rgw-zone-name > -``` - -### Topology Based Provisioning - -Enable Topology Based Provisioning for RBD pools by passing `--topology-pools`, `--topology-failure-domain-label` and `--topology-failure-domain-values` flags. -A new storageclass named `ceph-rbd-topology` will be created by the import script with `volumeBindingMode: WaitForFirstConsumer`. -The storageclass is used to create a volume in the pool matching the topology where a pod is scheduled. - -For more details, see the [Topology-Based Provisioning](topology-for-external-mode.md) - -### Admin privileges - -If in case the cluster needs the admin keyring to configure, update the admin key `rook-ceph-mon` secret with client.admin keyring - -!!! note - Sharing the admin key with the external cluster is not generally recommended - -1. Get the `client.admin` keyring from the ceph cluster - - ```console - ceph auth get client.admin - ``` - -2. Update two values in the `rook-ceph-mon` secret: - - `ceph-username`: Set to `client.admin` - - `ceph-secret`: Set the client.admin keyring - -After restarting the rook operator (and the toolbox if in use), rook will configure ceph with admin privileges. - -### 2. Copy the bash output - -Example Output: - -```console -export ROOK_EXTERNAL_FSID=797f411a-aafe-11ec-a254-fa163e1539f5 -export ROOK_EXTERNAL_USERNAME=client.healthchecker -export ROOK_EXTERNAL_CEPH_MON_DATA=ceph-rados-upstream-w4pdvq-node1-installer=10.0.210.83:6789 -export ROOK_EXTERNAL_USER_SECRET=AQAdm0FilZDSJxAAMucfuu/j0ZYYP4Bia8Us+w== -export ROOK_EXTERNAL_DASHBOARD_LINK=https://10.0.210.83:8443/ -export CSI_RBD_NODE_SECRET=AQC1iDxip45JDRAAVahaBhKz1z0WW98+ACLqMQ== -export CSI_RBD_PROVISIONER_SECRET=AQC1iDxiMM+LLhAA0PucjNZI8sG9Eh+pcvnWhQ== -export MONITORING_ENDPOINT=10.0.210.83 -export MONITORING_ENDPOINT_PORT=9283 -export RBD_POOL_NAME=replicated_2g -export RGW_POOL_PREFIX=default -``` - -## Commands on the K8s consumer cluster - -### Helm Installation - -To install with Helm, the rook cluster helm chart will configure the necessary resources for the external cluster with the example `values-external.yaml`. - -```console -clusterNamespace=rook-ceph -operatorNamespace=rook-ceph -cd deploy/examples/charts/rook-ceph-cluster -helm repo add rook-release https://charts.rook.io/release -helm install --create-namespace --namespace $clusterNamespace rook-ceph rook-release/rook-ceph -f values.yaml -helm install --create-namespace --namespace $clusterNamespace rook-ceph-cluster \ ---set operatorNamespace=$operatorNamespace rook-release/rook-ceph-cluster -f values-external.yaml -``` - -Skip the manifest installation section and continue with [Cluster Verification](#cluster-verification). - -### Manifest Installation - -If not installing with Helm, here are the steps to install with manifests. - -1. Deploy Rook, create [common.yaml](https://github.com/rook/rook/blob/master/deploy/examples/common.yaml), [crds.yaml](https://github.com/rook/rook/blob/master/deploy/examples/crds.yaml) and [operator.yaml](https://github.com/rook/rook/blob/master/deploy/examples/operator.yaml) manifests. - -2. Create [common-external.yaml](https://github.com/rook/rook/blob/master/deploy/examples/external/common-external.yaml) and [cluster-external.yaml](https://github.com/rook/rook/blob/master/deploy/examples/external/cluster-external.yaml) - -### Import the Source Data - -1. Paste the above output from `create-external-cluster-resources.py` into your current shell to allow importing the source data. - -2. The import script in the next step uses the current kubeconfig context by - default. If you want to specify the kubernetes cluster to use without - changing the current context, you can specify the cluster name by setting - the KUBECONTEXT environment variable. - - ```console - export KUBECONTEXT= - ``` - -3. Here is the link for [import](https://github.com/rook/rook/blob/master/deploy/examples/external/import-external-cluster.sh) script. The script has used the `rook-ceph` namespace and few parameters that also have referenced from namespace variable. If user's external cluster has a different namespace, change the namespace parameter in the script according to their external cluster. For example with `new-namespace` namespace, this change is needed on the namespace parameter in the script. - - ```console - NAMESPACE=${NAMESPACE:="new-namespace"} - ``` - -4. Run the import script. - - !!! note - If your Rook cluster nodes are running a kernel earlier than or equivalent to 5.4, remove - `fast-diff, object-map, deep-flatten,exclusive-lock` from the `imageFeatures` line. - - ```console - . import-external-cluster.sh - ``` - -### Cluster Verification - -1. Verify the consumer cluster is connected to the source ceph cluster: - - ```console - $ kubectl -n rook-ceph get CephCluster - NAME DATADIRHOSTPATH MONCOUNT AGE STATE HEALTH - rook-ceph-external /var/lib/rook 162m Connected HEALTH_OK - ``` - -2. Verify the creation of the storage class depending on the rbd pools and filesystem provided. - `ceph-rbd` and `cephfs` would be the respective names for the RBD and CephFS storage classes. - - ```console - kubectl -n rook-ceph get sc - ``` - -3. Then you can now create a [persistent volume](https://github.com/rook/rook/tree/master/deploy/examples/csi) based on these StorageClass. - -### Connect to an External Object Store - -Create the [external object store CR](https://github.com/rook/rook/blob/master/deploy/examples/external/object-external.yaml) to configure connection to external gateways. - -```console -cd deploy/examples/external -kubectl create -f object-external.yaml -``` - -Consume the S3 Storage, in two different ways: - -1. Create an [Object store user](https://github.com/rook/rook/blob/master/deploy/examples/object-user.yaml) for credentials to access the S3 endpoint. - - ```console - cd deploy/examples - kubectl create -f object-user.yaml - ``` - -2. Create a [bucket storage class](https://github.com/rook/rook/blob/master/deploy/examples/external/storageclass-bucket-delete.yaml) where a client can request creating buckets and then create the [Object Bucket Claim](https://github.com/rook/rook/blob/master/deploy/examples/external/object-bucket-claim-delete.yaml), which will create an individual bucket for reading and writing objects. - - ```console - cd deploy/examples/external - kubectl create -f storageclass-bucket-delete.yaml - kubectl create -f object-bucket-claim-delete.yaml - ``` - -!!! hint - For more details see the [Object Store topic](../../../Storage-Configuration/Object-Storage-RGW/object-storage.md#connect-to-an-external-object-store) - -### Connect to v2 mon port - -If encryption or compression on the wire is needed, specify the `--v2-port-enable` flag. -If the v2 address type is present in the `ceph quorum_status`, then the output of 'ceph mon data' i.e, `ROOK_EXTERNAL_CEPH_MON_DATA` will use the v2 port(`3300`). - -### NFS storage - -Rook suggests a different mechanism for making use of an [NFS service running on the external Ceph standalone cluster](../../../Storage-Configuration/NFS/nfs-csi-driver.md#consuming-nfs-from-an-external-source), if desired. - -## Exporting Rook to another cluster - -If you have multiple K8s clusters running, and want to use the local `rook-ceph` cluster as the central storage, -you can export the settings from this cluster with the following steps. - -1. Copy create-external-cluster-resources.py into the directory `/etc/ceph/` of the toolbox. - - ```console - toolbox=$(kubectl get pod -l app=rook-ceph-tools -n rook-ceph -o jsonpath='{.items[*].metadata.name}') - kubectl -n rook-ceph cp deploy/examples/external/create-external-cluster-resources.py $toolbox:/etc/ceph - ``` - -2. Exec to the toolbox pod and execute create-external-cluster-resources.py with needed options to create required [users and keys](#1-create-all-users-and-keys). - -!!! important - For other clusters to connect to storage in this cluster, Rook must be configured with a networking configuration that is accessible from other clusters. Most commonly this is done by enabling host networking in the CephCluster CR so the Ceph daemons will be addressable by their host IPs. +* [Connect to an External Object Store](/Documentation/CRDs/Cluster/external-cluster/advance-external.md#connect-to-an-external-object-store) ## Upgrades -Upgrading the cluster would be different for restricted caps and non-restricted caps, - -1. If consumer cluster doesn't have restricted caps, this will upgrade all the default CSI users (non-restricted) - - ```console - python3 create-external-cluster-resources.py --upgrade - ``` - -2. If the consumer cluster has restricted caps - - Restricted users created using `--restricted-auth-permission` flag need to pass mandatory flags: '`--rbd-data-pool-name`(if it is a rbd user), `--k8s-cluster-name` and `--run-as-user`' flags while upgrading, in case of cephfs users if you have passed `--cephfs-filesystem-name` flag while creating CSI users then while upgrading it will be mandatory too. In this example the user would be `client.csi-rbd-node-rookstorage-replicapool` (following the pattern `csi-user-clusterName-poolName`) - - ```console - python3 create-external-cluster-resources.py --upgrade --rbd-data-pool-name replicapool --k8s-cluster-name rookstorage --run-as-user client.csi-rbd-node-rookstorage-replicapool - ``` - - !!! note - 1) An existing non-restricted user cannot be converted to a restricted user by upgrading. - 2) The upgrade flag should only be used to append new permissions to users. It shouldn't be used for changing a CSI user already applied permissions. For example, be careful not to change pools(s) that a user has access to. - -### Upgrade cluster to utilize new feature - -Some Rook upgrades may require re-running the import steps, or may introduce new external cluster features that can be most easily enabled by re-running the import steps. - -To re-run the import steps with new options, the python script should be re-run using the same configuration options that were used for past invocations, plus the configurations that are being added or modified. - -Starting with Rook v1.15, the script stores the configuration in the external-cluster-user-command configmap for easy future reference. - -* arg: Exact arguments that were used for for processing the script. Argument that are decided using the Priority: command-line-args > config.ini file values > default values. - -#### Example `external-cluster-user-command` ConfigMap: - -1. Get the last-applied config, if its available - - ```console - $ kubectl get configmap -namespace rook-ceph external-cluster-user-command --output jsonpath='{.data.args}' - ``` - -2. Copy the output to config.ini - -3. Make any desired modifications and additions to `config.ini`` - -4. Run the python script again using the [config file](#config-file) - -5. [Copy the bash output](#2-copy-the-bash-output) - -6. Run the steps under [import-the-source-data](#import-the-source-data) +* [Upgrade external cluster](/Documentation/CRDs/Cluster/external-cluster/upgrade-external.md#upgrade-external-cluster) -!!! warning - If the last-applied config is unavailable, run the current version of the script again using previously-applied config and CLI flags. - Failure to reuse the same configuration options when re-invoking the python script can result in unexpected changes when re-running the import script. +* [Utilize new features in upgrade](/Documentation/CRDs/Cluster/external-cluster/upgrade-external.md#upgrade-cluster-to-utilize-new-feature) diff --git a/Documentation/CRDs/Cluster/external-cluster/provider-export.md b/Documentation/CRDs/Cluster/external-cluster/provider-export.md new file mode 100644 index 000000000000..7f3b3e8e7abf --- /dev/null +++ b/Documentation/CRDs/Cluster/external-cluster/provider-export.md @@ -0,0 +1,125 @@ +# Export config from the Ceph provider cluster + +In order to configure an external Ceph cluster with Rook, we need to extract some information in order to connect to that cluster. + +## 1. Create all users and keys + +Run the python script [create-external-cluster-resources.py](https://github.com/rook/rook/blob/master/deploy/examples/external/create-external-cluster-resources.py) for creating all users and keys. + +```console +python3 create-external-cluster-resources.py --rbd-data-pool-name --cephfs-filesystem-name --rgw-endpoint --namespace --format bash +``` + +* `--namespace`: Namespace where CephCluster will run, for example `rook-ceph` +* `--format bash`: The format of the output +* `--rbd-data-pool-name`: The name of the RBD data pool +* `--alias-rbd-data-pool-name`: Provides an alias for the RBD data pool name, necessary if a special character is present in the pool name such as a period or underscore +* `--rgw-endpoint`: (optional) The RADOS Gateway endpoint in the format `:` or `:`. +* `--rgw-pool-prefix`: (optional) The prefix of the RGW pools. If not specified, the default prefix is `default` +* `--rgw-tls-cert-path`: (optional) RADOS Gateway endpoint TLS certificate file path +* `--rgw-skip-tls`: (optional) Ignore TLS certification validation when a self-signed certificate is provided (NOT RECOMMENDED) +* `--rbd-metadata-ec-pool-name`: (optional) Provides the name of erasure coded RBD metadata pool, used for creating ECRBDStorageClass. +* `--monitoring-endpoint`: (optional) Ceph Manager prometheus exporter endpoints (comma separated list of IP entries of active and standby mgrs) +* `--monitoring-endpoint-port`: (optional) Ceph Manager prometheus exporter port +* `--skip-monitoring-endpoint`: (optional) Skip prometheus exporter endpoints, even if they are available. Useful if the prometheus module is not enabled +* `--ceph-conf`: (optional) Provide a Ceph conf file +* `--keyring`: (optional) Path to Ceph keyring file, to be used with `--ceph-conf` +* `--k8s-cluster-name`: (optional) Kubernetes cluster name +* `--output`: (optional) Output will be stored into the provided file +* `--dry-run`: (optional) Prints the executed commands without running them +* `--run-as-user`: (optional) Provides a user name to check the cluster's health status, must be prefixed by `client`. +* `--cephfs-metadata-pool-name`: (optional) Provides the name of the cephfs metadata pool +* `--cephfs-filesystem-name`: (optional) The name of the filesystem, used for creating CephFS StorageClass +* `--cephfs-data-pool-name`: (optional) Provides the name of the CephFS data pool, used for creating CephFS StorageClass +* `--rados-namespace`: (optional) Divides a pool into separate logical namespaces, used for creating RBD PVC in a CephBlockPoolRadosNamespace (should be lower case) +* `--subvolume-group`: (optional) Provides the name of the subvolume group, used for creating CephFS PVC in a subvolumeGroup +* `--rgw-realm-name`: (optional) Provides the name of the rgw-realm +* `--rgw-zone-name`: (optional) Provides the name of the rgw-zone +* `--rgw-zonegroup-name`: (optional) Provides the name of the rgw-zone-group +* `--upgrade`: (optional) Upgrades the cephCSIKeyrings(For example: client.csi-cephfs-provisioner) and client.healthchecker ceph users with new permissions needed for the new cluster version and older permission will still be applied. +* `--restricted-auth-permission`: (optional) Restrict cephCSIKeyrings auth permissions to specific pools, and cluster. Mandatory flags that need to be set are `--rbd-data-pool-name`, and `--k8s-cluster-name`. `--cephfs-filesystem-name` flag can also be passed in case of CephFS user restriction, so it can restrict users to particular CephFS filesystem. +* `--v2-port-enable`: (optional) Enables the v2 mon port (3300) for mons. +* `--topology-pools`: (optional) Comma-separated list of topology-constrained rbd pools +* `--topology-failure-domain-label`: (optional) K8s cluster failure domain label (example: zone, rack, or host) for the topology-pools that match the ceph domain +* `--topology-failure-domain-values`: (optional) Comma-separated list of the k8s cluster failure domain values corresponding to each of the pools in the `topology-pools` list +* `--config-file`: Path to the configuration file, Priority: command-line-args > config.ini values > default values + +## 2. Copy the bash output + +Example Output: + +```console +export ROOK_EXTERNAL_FSID=797f411a-aafe-11ec-a254-fa163e1539f5 +export ROOK_EXTERNAL_USERNAME=client.healthchecker +export ROOK_EXTERNAL_CEPH_MON_DATA=ceph-rados-upstream-w4pdvq-node1-installer=10.0.210.83:6789 +export ROOK_EXTERNAL_USER_SECRET=AQAdm0FilZDSJxAAMucfuu/j0ZYYP4Bia8Us+w== +export ROOK_EXTERNAL_DASHBOARD_LINK=https://10.0.210.83:8443/ +export CSI_RBD_NODE_SECRET=AQC1iDxip45JDRAAVahaBhKz1z0WW98+ACLqMQ== +export CSI_RBD_PROVISIONER_SECRET=AQC1iDxiMM+LLhAA0PucjNZI8sG9Eh+pcvnWhQ== +export MONITORING_ENDPOINT=10.0.210.83 +export MONITORING_ENDPOINT_PORT=9283 +export RBD_POOL_NAME=replicated_2g +export RGW_POOL_PREFIX=default +``` + +## Examples on utilizing Advance flags + +### Config-file + +Use the config file to set the user configuration file, add the flag `--config-file` to set the file path. + +Example: + +`/config.ini` + +```console +[Configurations] +format = bash +cephfs-filesystem-name = +rbd-data-pool-name = +... +``` + +```console +python3 create-external-cluster-resources.py --config-file /config.ini +``` + +!!! note + You can use both config file and other arguments at the same time + Priority: command-line-args has more priority than config.ini file values, and config.ini file values have more priority than default values. + +### Multi-tenancy + +To enable multi-tenancy, run the script with the `--restricted-auth-permission` flag and pass the mandatory flags with it, +It will generate the secrets which you can use for creating new `Consumer cluster` deployment using the same `Provider cluster`(ceph cluster). +So you would be running different isolated consumer clusters on top of single `Provider cluster`. + +!!! note + Restricting the csi-users per pool, and per cluster will require creating new csi-users and new secrets for that csi-users. + So apply these secrets only to new `Consumer cluster` deployment while using the same `Provider cluster`. + +```console +python3 create-external-cluster-resources.py --cephfs-filesystem-name --rbd-data-pool-name --k8s-cluster-name --restricted-auth-permission true --format --rgw-endpoint --namespace +``` + +### RGW Multisite + +Pass the `--rgw-realm-name`, `--rgw-zonegroup-name` and `--rgw-zone-name` flags to create the admin ops user in a master zone, zonegroup and realm. +See the [Multisite doc](https://docs.ceph.com/en/quincy/radosgw/multisite/#configuring-a-master-zone) for creating a zone, zonegroup and realm. + +```console +python3 create-external-cluster-resources.py --rbd-data-pool-name --format bash --rgw-endpoint --rgw-realm-name > --rgw-zonegroup-name --rgw-zone-name > +``` + +### Topology Based Provisioning + +Enable Topology Based Provisioning for RBD pools by passing `--topology-pools`, `--topology-failure-domain-label` and `--topology-failure-domain-values` flags. +A new storageclass named `ceph-rbd-topology` will be created by the import script with `volumeBindingMode: WaitForFirstConsumer`. +The storageclass is used to create a volume in the pool matching the topology where a pod is scheduled. + +For more details, see the [Topology-Based Provisioning](topology-for-external-mode.md) + +### Connect to v2 mon port + +If encryption or compression on the wire is needed, specify the `--v2-port-enable` flag. +If the v2 address type is present in the `ceph quorum_status`, then the output of 'ceph mon data' i.e, `ROOK_EXTERNAL_CEPH_MON_DATA` will use the v2 port(`3300`). diff --git a/Documentation/CRDs/Cluster/external-cluster/upgrade-external.md b/Documentation/CRDs/Cluster/external-cluster/upgrade-external.md new file mode 100644 index 000000000000..7ee3110ca525 --- /dev/null +++ b/Documentation/CRDs/Cluster/external-cluster/upgrade-external.md @@ -0,0 +1,58 @@ +# External Cluster Upgrades + +When upgrading an external cluster, Ceph and Rook versions will be updated independently. During the Rook update, the external provider cluster connection also needs to be updated with any settings and permissions for new features. + +## Upgrade the cluster to consume latest ceph user caps (mandatory) + +Upgrading the cluster would be different for restricted caps and non-restricted caps, + +1. If consumer cluster doesn't have restricted caps, this will upgrade all the default CSI users (non-restricted) + + ```console + python3 create-external-cluster-resources.py --upgrade + ``` + +2. If the consumer cluster has restricted caps + + Restricted users created using `--restricted-auth-permission` flag need to pass mandatory flags: '`--rbd-data-pool-name`(if it is a rbd user), `--k8s-cluster-name` and `--run-as-user`' flags while upgrading, in case of cephfs users if you have passed `--cephfs-filesystem-name` flag while creating CSI users then while upgrading it will be mandatory too. In this example the user would be `client.csi-rbd-node-rookstorage-replicapool` (following the pattern `csi-user-clusterName-poolName`) + + ```console + python3 create-external-cluster-resources.py --upgrade --rbd-data-pool-name replicapool --k8s-cluster-name rookstorage --run-as-user client.csi-rbd-node-rookstorage-replicapool + ``` + + !!! note + 1) An existing non-restricted user cannot be converted to a restricted user by upgrading. + 2) The upgrade flag should only be used to append new permissions to users. It shouldn't be used for changing a CSI user already applied permissions. For example, be careful not to change pools(s) that a user has access to. + +## Upgrade cluster to utilize a new feature (optional) + +Some Rook upgrades may require re-running the import steps, or may introduce new external cluster features that can be most easily enabled by re-running the import steps. + +To re-run the import steps with new options, the python script should be re-run using the same configuration options that were used for past invocations, plus the configurations that are being added or modified. + +Starting with Rook v1.15, the script stores the configuration in the external-cluster-user-command configmap for easy future reference. + +* arg: Exact arguments that were used for for processing the script. +Argument that are decided using the Priority: command-line-args has more priority than config.ini file values, and config.ini file values have more priority than default values. + +### Example `external-cluster-user-command` ConfigMap: + +1. Get the last-applied config, if its available + + ```console + $ kubectl get configmap -namespace rook-ceph external-cluster-user-command --output jsonpath='{.data.args}' + ``` + +2. Copy the output to config.ini + +3. Make any desired modifications and additions to `config.ini`` + +4. Run the python script again using the [config file](/Documentation/CRDs/Cluster/external-cluster/provider-export.md#config-file) + +5. [Copy the bash output](/Documentation/CRDs/Cluster/external-cluster/provider-export.md#2-copy-the-bash-output) + +6. [Import-the-provider-data](/Documentation/CRDs/Cluster/external-cluster/consumer-import.md#import-the-provider-data) + +!!! warning + If the last-applied config is unavailable, run the current version of the script again using previously-applied config and CLI flags. + Failure to reuse the same configuration options when re-invoking the python script can result in unexpected changes when re-running the import script. From 166e4f35b2364121403b1c5a2d55e02e06482056 Mon Sep 17 00:00:00 2001 From: parth-gr Date: Fri, 20 Sep 2024 15:27:12 +0530 Subject: [PATCH 30/54] csi: fix the disable driver flag in the csi driver reconcile ROOK_CSI_DISABLE_DRIVER was not working accurate from https://github.com/rook/rook/pull/14489 The csi driver was installed even if its not expected Signed-off-by: parth-gr --- pkg/operator/ceph/csi/controller.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/operator/ceph/csi/controller.go b/pkg/operator/ceph/csi/controller.go index b93fe7a09bb8..31c9d7924a0f 100644 --- a/pkg/operator/ceph/csi/controller.go +++ b/pkg/operator/ceph/csi/controller.go @@ -332,8 +332,7 @@ func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, e } } - if !EnableCSIOperator() { - + if !disableCSI && !EnableCSIOperator() { err = r.validateAndConfigureDrivers(serverVersion, ownerInfo) if err != nil { return opcontroller.ImmediateRetryResult, errors.Wrap(err, "failed to configure ceph csi") From 33c9bdf652d02b8d9013c16fa0e8dc51c0fe7236 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:24:01 +0000 Subject: [PATCH 31/54] build(deps): bump github/codeql-action from 3.26.7 to 3.26.8 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.7 to 3.26.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/8214744c546c1e5c8f03dde8fab3a7353211988d...294a9d92911152fe08befb9ec03e240add280cb3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 2a8dca108edb..3e68e8d803cb 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 with: sarif_file: results.sarif From 9ecd6a250003eec0f127409ae43b8cd872790ad9 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 20 Sep 2024 13:52:42 +0200 Subject: [PATCH 32/54] build: support golang 1.23 Signed-off-by: Michael Adam --- .github/workflows/build.yml | 2 +- build/makelib/golang.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d7b9462dd49..844c71b7cb0e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: ["1.22"] + go-version: ["1.22", "1.23"] steps: - name: checkout uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 diff --git a/build/makelib/golang.mk b/build/makelib/golang.mk index e1ae8468e0af..44814e2b577a 100644 --- a/build/makelib/golang.mk +++ b/build/makelib/golang.mk @@ -48,7 +48,7 @@ GO_TEST_FLAGS ?= # ==================================================================================== # Setup go environment -GO_SUPPORTED_VERSIONS ?= 1.22 +GO_SUPPORTED_VERSIONS ?= 1.22|1.23 GO_PACKAGES := $(foreach t,$(GO_SUBDIRS),$(GO_PROJECT)/$(t)/...) GO_INTEGRATION_TEST_PACKAGES := $(foreach t,$(GO_INTEGRATION_TESTS_SUBDIRS),$(GO_PROJECT)/$(t)/integration) From 1c9727c271667d2b4faadb164735996a3c757187 Mon Sep 17 00:00:00 2001 From: Travis Nielsen Date: Fri, 20 Sep 2024 14:04:51 -0600 Subject: [PATCH 33/54] docs: declare cephconfig settings stable The cephConfig settings in the CephCluster CR have been stable and there are no planned changes, so remove the experimental documentation indicator. Also, clarify the usage and the precedence of the ceph config options. Signed-off-by: Travis Nielsen --- Documentation/CRDs/Cluster/ceph-cluster-crd.md | 14 +++++++++++--- .../Advanced/ceph-configuration.md | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Documentation/CRDs/Cluster/ceph-cluster-crd.md b/Documentation/CRDs/Cluster/ceph-cluster-crd.md index 29ded5c34a8b..38edb30d8eb0 100755 --- a/Documentation/CRDs/Cluster/ceph-cluster-crd.md +++ b/Documentation/CRDs/Cluster/ceph-cluster-crd.md @@ -825,9 +825,6 @@ set the `allowUninstallWithVolumes` to true under `spec.CleanupPolicy`. ## Ceph Config -!!! attention - This feature is experimental. - The Ceph config options are applied after the MONs are all in quorum and running. To set Ceph config options, you can add them to your `CephCluster` spec as shown below. See the [Ceph config reference](https://docs.ceph.com/en/latest/rados/configuration/general-config-ref/) @@ -848,6 +845,17 @@ spec: osd_max_scrubs: "10" ``` +The Rook operator will actively apply these values, whereas the +[ceph.conf settings](../../Storage-Configuration/Advanced/ceph-configuration/#custom-cephconf-settings) +only take effect after the Ceph daemon pods are restarted. + +If both these `cephConfig` and [ceph.conf settings](../../Storage-Configuration/Advanced/ceph-configuration/#custom-cephconf-settings) +are applied, the `cephConfig` settings will take higher precedence if there is an overlap. + +If Ceph settings need to be applied to mons before quorum is initially created, the +[ceph.conf settings](../../Storage-Configuration/Advanced/ceph-configuration/#custom-cephconf-settings) +should be used instead. + !!! warning Rook performs no direct validation on these config options, so the validity of the settings is the user's responsibility. diff --git a/Documentation/Storage-Configuration/Advanced/ceph-configuration.md b/Documentation/Storage-Configuration/Advanced/ceph-configuration.md index 399b78a24a0e..3b439e27ecb5 100644 --- a/Documentation/Storage-Configuration/Advanced/ceph-configuration.md +++ b/Documentation/Storage-Configuration/Advanced/ceph-configuration.md @@ -208,7 +208,7 @@ ceph osd pool set rbd pg_num 512 ## Custom `ceph.conf` Settings -!!! warning +!!! info The advised method for controlling Ceph configuration is to use the [`cephConfig:` structure](../../CRDs/Cluster/ceph-cluster-crd.md#ceph-config) in the `CephCluster` CRD.

It is highly recommended that this only be used when absolutely necessary and that the `config` be From b818dd1c7d3fdf90532d23e23dd401c4bb5be172 Mon Sep 17 00:00:00 2001 From: subhamkrai Date: Tue, 24 Sep 2024 16:59:13 +0530 Subject: [PATCH 34/54] build: keep specific z version in go mod 1.22.5 let's keep specific z version in go.mod 1.22.5. Signed-off-by: subhamkrai --- go.mod | 6 +++--- go.sum | 8 ++++---- pkg/apis/go.mod | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index add877c686ef..306f52aff40f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/rook/rook -go 1.22.6 +go 1.22.5 toolchain go1.22.7 @@ -18,10 +18,10 @@ require ( github.com/IBM/keyprotect-go-client v0.15.1 github.com/aws/aws-sdk-go v1.55.5 github.com/banzaicloud/k8s-objectmatcher v1.8.0 - github.com/ceph/ceph-csi-operator/api v0.0.0-20240819112305-88e6db254d6c + github.com/ceph/ceph-csi-operator/api v0.0.0-20240918113437-f3030b0ac9f4 github.com/ceph/go-ceph v0.29.0 github.com/coreos/pkg v0.0.0-20230601102743-20bbbf26f4d8 - github.com/csi-addons/kubernetes-csi-addons v0.10.0 + github.com/csi-addons/kubernetes-csi-addons v0.10.1-0.20240924092040-c11db0b867a1 github.com/gemalto/kmip-go v0.0.10 github.com/go-ini/ini v1.67.0 github.com/google/go-cmp v0.6.0 diff --git a/go.sum b/go.sum index b58bb5fb030f..35c658de2e3a 100644 --- a/go.sum +++ b/go.sum @@ -165,8 +165,8 @@ github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/ceph/ceph-csi-operator/api v0.0.0-20240819112305-88e6db254d6c h1:JOhwt7+iM18pm9s9zAhAKGRJm615AdIaKklbUd7Z8So= -github.com/ceph/ceph-csi-operator/api v0.0.0-20240819112305-88e6db254d6c/go.mod h1:odEUoarG26wXBCC2l4O4nMWhAz6VTKr2FRkv9yELgi8= +github.com/ceph/ceph-csi-operator/api v0.0.0-20240918113437-f3030b0ac9f4 h1:VYmHuPxEeiZ9jusRzgGybte2ByOUxAD0btQ0Wvac4VA= +github.com/ceph/ceph-csi-operator/api v0.0.0-20240918113437-f3030b0ac9f4/go.mod h1:odEUoarG26wXBCC2l4O4nMWhAz6VTKr2FRkv9yELgi8= github.com/ceph/ceph-csi/api v0.0.0-20231227104434-06f9a98b7a83 h1:xWhLO5MR+diAsZoOcPe0zVe+JcJrqMaVbScShye6pXw= github.com/ceph/ceph-csi/api v0.0.0-20231227104434-06f9a98b7a83/go.mod h1:ZSvtS90FCB/becFi/rjy85sSw1igchaWZfUigxN9FxY= github.com/ceph/go-ceph v0.29.0 h1:pJQY+++PyY2FMP0ffVaE7FbIdivemBPCu4MWr4S8CtI= @@ -214,8 +214,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/csi-addons/kubernetes-csi-addons v0.10.0 h1:bBc6nb1oROz4RLhqoLFNeGymk2jIRXcx7LvAup9+3Jg= -github.com/csi-addons/kubernetes-csi-addons v0.10.0/go.mod h1:nqi369YuYMIdysBbHjtYJcWFpcxujPot1HS6tnNWBV4= +github.com/csi-addons/kubernetes-csi-addons v0.10.1-0.20240924092040-c11db0b867a1 h1:9mh79gS8O8uO5okZ2DhFO0LSrhpVXd9R9DLvbnh2He4= +github.com/csi-addons/kubernetes-csi-addons v0.10.1-0.20240924092040-c11db0b867a1/go.mod h1:LeY7UYm8nEBCG1RcJG0DHmJbva0ILmtp+kcegxRuHhc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= diff --git a/pkg/apis/go.mod b/pkg/apis/go.mod index 0230510aa324..2626abd58642 100644 --- a/pkg/apis/go.mod +++ b/pkg/apis/go.mod @@ -1,6 +1,6 @@ module github.com/rook/rook/pkg/apis -go 1.22.6 +go 1.22.5 toolchain go1.22.7 From f7cb8a2e081cb6c90f67a8364a59e811d9df0943 Mon Sep 17 00:00:00 2001 From: Ceph Jenkins Date: Tue, 24 Sep 2024 09:30:59 -0400 Subject: [PATCH 35/54] csv: add additional csv changes that other commits bring add generated csv changes Signed-off-by: Ceph Jenkins --- build/csv/ceph/ceph.rook.io_cephclusters.yaml | 11 + ...al-cluster-script-config_v1_configmap.yaml | 3189 +++++++++-------- ...k-ceph-operator.clusterserviceversion.yaml | 3189 +++++++++-------- 3 files changed, 3205 insertions(+), 3184 deletions(-) diff --git a/build/csv/ceph/ceph.rook.io_cephclusters.yaml b/build/csv/ceph/ceph.rook.io_cephclusters.yaml index db2978259122..862a6f38ace2 100644 --- a/build/csv/ceph/ceph.rook.io_cephclusters.yaml +++ b/build/csv/ceph/ceph.rook.io_cephclusters.yaml @@ -843,6 +843,17 @@ spec: properties: enabled: type: boolean + exporter: + properties: + perfCountersPrioLimit: + default: 5 + format: int64 + type: integer + statsPeriodSeconds: + default: 5 + format: int64 + type: integer + type: object externalMgrEndpoints: items: properties: diff --git a/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml b/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml index f1e95f9061d1..6a28b767f694 100644 --- a/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml +++ b/build/csv/ceph/rook-ceph-external-cluster-script-config_v1_configmap.yaml @@ -74,1473 +74,1466 @@ data: bGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMiLCAib3NkIiwgInByb2ZpbGUgcmJk LXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBwb29s PS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyB4IHBv - b2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJdLCAiZW50aXR5IjogImNsaWVudC5oZWFsdGhj - aGVja2VyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUi - fSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuaGVhbHRoY2hlY2tlciIsImtl - eSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNscmRBPT0iLCJjYXBzIjp7Im1v - biI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1cyIsIm9zZCI6InByb2ZpbGUg - cmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBw - b29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyB4 - IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9v - dXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJwcm9maWxlIHJiZCwg - YWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAib3NkIiwgInByb2ZpbGUgcmJkIl0sICJl - bnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtbm9kZSIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgi - OiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5IjoiY2xp - ZW50LmNzaS1yYmQtbm9kZSIsImtleSI6IkFRQk9nck5lSGJLMUF4QUF1YllCZVY4UzFVL0dQenE1 - U1ZlcTZnPT0iLCJjYXBzIjp7Im1vbiI6InByb2ZpbGUgcmJkLCBhbGxvdyBjb21tYW5kICdvc2Qg - YmxvY2tsaXN0JyIsIm9zZCI6InByb2ZpbGUgcmJkIn19XSIiIgogICAgICAgIHNlbGYuY21kX291 - dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgInByb2ZpbGUgcmJkLCBh - bGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwg - InByb2ZpbGUgcmJkIl0sICJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiLCAi + b2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCIsICJtZHMiLCAiYWxsb3cgKiJdLCAiZW50aXR5 + IjogImNsaWVudC5oZWFsdGhjaGVja2VyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJh + dXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQu + aGVhbHRoY2hlY2tlciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNs + cmRBPT0iLCJjYXBzIjp7Im1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1 + cyIsIm9zZCI6InByb2ZpbGUgcmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5y + Z3cubWV0YSwgYWxsb3cgciBwb29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJn + dy5jb250cm9sLCBhbGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCIsIm1kcyI6 + ImFsbG93ICoifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAg + IiIieyJjYXBzIjogWyJtb24iLCAicHJvZmlsZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9j + a2xpc3QnIiwgIm9zZCIsICJwcm9maWxlIHJiZCJdLCAiZW50aXR5IjogImNsaWVudC5jc2ktcmJk + LW5vZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9 + IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktcmJkLW5vZGUiLCJrZXki + OiJBUUJPZ3JOZUhiSzFBeEFBdWJZQmVWOFMxVS9HUHpxNVNWZXE2Zz09IiwiY2FwcyI6eyJtb24i + OiJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJwcm9m + aWxlIHJiZCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAi + IiJ7ImNhcHMiOiBbIm1vbiIsICJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2Nr + bGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIsICJwcm9maWxlIHJiZCJdLCAiZW50aXR5 + IjogImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZp + eCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJj + bGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIsImtleSI6IkFRQk5nck5lMWdleUt4QUE4ZWtWaVJk + RStoc3M1T3dlWUJrd05nPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoicHJvZmls + ZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwib3NkIjoicHJvZmlsZSByYmQi + fX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBz + IjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdy + IiwgImFsbG93IHJ3IiwgIm9zZCIsICJhbGxvdyBydyB0YWcgY2VwaGZzICo9KiIsICJtZHMiLCAi + YWxsb3cgcnciXSwgImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1ub2RlIiwgImZvcm1hdCI6 + ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAi + IiJbeyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1ub2RlIiwia2V5IjoiQVFCT2dyTmVFTnVu + S3hBQVBDbWdFN1I2RzhEY1huYUoxRjMycWc9PSIsImNhcHMiOnsibWRzIjoiYWxsb3cgcnciLCJt + Z3IiOiJhbGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xp + c3QnIiwib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyAqPSoifX1dIiIiCiAgICAgICAgc2VsZi5j + bWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBzIjogWyJtb24iLCAiYWxsb3cgciwg + YWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIs + ICJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiLCAibWRzIiwgImFsbG93ICoiXSwgImVu + dGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQiOiAianNvbiIs + ICJwcmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50 + aXR5IjoiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCJrZXkiOiJBUUJPZ3JOZUFGZ2NH + QkFBdkdxS09BRDBEM3h4bVZZMFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJhbGxvdyBydyIsIm1v + biI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwib3NkIjoiYWxsb3cg + cncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIiwibWRzIjoiYWxsb3cgKiJ9fV0iIiIKICAgICAgICBz + ZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxv + dyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAi + b3NkIiwgImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiIsICJtZHMiLCAiYWxsb3cgKiJd + LCAiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9y + YWdlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIi + IgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25l + ci1vcGVuc2hpZnQtc3RvcmFnZSIsImtleSI6IkJRQk9nck5lQUZnY0dCQUF2R3FLT0FEMEQzeHht + VlkwUjkxMmRnPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxs + b3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1l + dGFkYXRhPSoiLCAibWRzIjoiYWxsb3cgKiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRf + bWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21t + YW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3 + IHRhZyBjZXBoZnMgbWV0YWRhdGE9bXlmcyIsICJtZHMiLCAiYWxsb3cgKiJdLCAiZW50aXR5Ijog + ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMiLCAi Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9IiIiCiAgICAg - ICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiwia2V5Ijoi - QVFCTmdyTmUxZ2V5S3hBQThla1ZpUmRFK2hzczVPd2VZQmt3Tmc9PSIsImNhcHMiOnsibWdyIjoi - YWxsb3cgcnciLCJtb24iOiJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlz - dCciLCJvc2QiOiJwcm9maWxlIHJiZCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFw - WwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5k - ICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3IHRh - ZyBjZXBoZnMgKj0qIiwgIm1kcyIsICJhbGxvdyBydyJdLCAiZW50aXR5IjogImNsaWVudC5jc2kt - Y2VwaGZzLW5vZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNy - ZWF0ZSJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLW5v - ZGUiLCJrZXkiOiJBUUJPZ3JOZUVOdW5LeEFBUENtZ0U3UjZHOERjWG5hSjFGMzJxZz09IiwiY2Fw - cyI6eyJtZHMiOiJhbGxvdyBydyIsIm1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxs - b3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzICo9 - KiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNh - cHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJt - Z3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiJd - LCAiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJq - c29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJb - eyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsImtleSI6IkFRQk9nck5l - QUZnY0dCQUF2R3FLT0FEMEQzeHhtVlkwUjkxMmRnPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3 - IiwibW9uIjoiYWxsb3cgciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJh - bGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0 - cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBzIjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cg - Y29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIsICJhbGxv - dyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiXSwgImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhm - cy1wcm92aXNpb25lci1vcGVuc2hpZnQtc3RvcmFnZSIsICJmb3JtYXQiOiAianNvbiIsICJwcmVm - aXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5Ijoi - Y2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UiLCJrZXkiOiJC - UUJPZ3JOZUFGZ2NHQkFBdkdxS09BRDBEM3h4bVZZMFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJh - bGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwi - b3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIn19XSIiIgogICAgICAgIHNlbGYu - Y21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgImFsbG93IHIs - IGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJhbGxvdyBydyIsICJvc2Qi - LCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT1teWZzIl0sICJlbnRpdHkiOiAiY2xpZW50 - LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UtbXlmcyIsICJmb3JtYXQi - OiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0g - IiIiW3siZW50aXR5IjoiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0 - b3JhZ2UtbXlmcyIsImtleSI6IkNRQk9nck5lQUZnY0dCQUF2R3FLT0FEMEQzeHhtVlkwUjkxMmRn - PT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxsb3cgY29tbWFu - ZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPW15 - ZnMifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJj - YXBzIjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxv - dyBjb21tYW5kIHZlcnNpb24iLCAibWdyIiwgImFsbG93IGNvbW1hbmQgY29uZmlnIiwgIm9zZCIs - ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3Lm1ldGEs - IGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9ZGVmYXVsdC5yZ3cuY29udHJv - bCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93IHggcG9vbD1kZWZhdWx0LnJn - dy5idWNrZXRzLmluZGV4Il0sICJlbnRpdHkiOiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCAiZm9y - bWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9IiIiCiAgICAgICAg - XSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5oZWFsdGhjaGVja2VyIiwia2V5IjoiQVFERmtiTmVm - dDViRlJBQVRuZExOVVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjogImFsbG93IHIs - IGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1cywgYWxsb3cgY29tbWFuZCB2ZXJzaW9uIiwgIm1n - ciI6ICJhbGxvdyBjb21tYW5kIGNvbmZpZyIsICJvc2QiOiAicHJvZmlsZSByYmQtcmVhZC1vbmx5 - LCBhbGxvdyByd3ggcG9vbD1kZWZhdWx0LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290 - LCBhbGxvdyBydyBwb29sPWRlZmF1bHQucmd3LmNvbnRyb2wsIGFsbG93IHJ4IHBvb2w9ZGVmYXVs - dC5yZ3cubG9nLCBhbGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIK + ICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5z + aGlmdC1zdG9yYWdlLW15ZnMiLCJrZXkiOiJDUUJPZ3JOZUFGZ2NHQkFBdkdxS09BRDBEM3h4bVZZ + MFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJhbGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93 + IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRh + ZGF0YT1teWZzIiwibWRzIjoiYWxsb3cgKiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRf + bWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21t + YW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQgdmVyc2lvbiIsICJtZ3IiLCAiYWxsb3cg + Y29tbWFuZCBjb25maWciLCAib3NkIiwgInByb2ZpbGUgcmJkLXJlYWQtb25seSwgYWxsb3cgcnd4 + IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBwb29sPS5yZ3cucm9vdCwgYWxsb3cgcncg + cG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyByeCBwb29sPWRlZmF1bHQucmd3LmxvZywg + YWxsb3cgeCBwb29sPWRlZmF1bHQucmd3LmJ1Y2tldHMuaW5kZXgiLCAibWRzIiwgImFsbG93ICoi + XSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJw + cmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5 + IjoiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0NWJGUkFBVG5kTE5VU0VL + cnVvenhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBx + dW9ydW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdyIjogImFsbG93IGNvbW1h + bmQgY29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29s + PWRlZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9 + ZGVmYXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93 + IHggcG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4IiwibWRzIjoiYWxsb3cgKiJ9fV0iIiIK ICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1v biIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQg dmVyc2lvbiIsICJtZ3IiLCAiYWxsb3cgY29tbWFuZCBjb25maWciLCAib3NkIiwgInByb2ZpbGUg cmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBw b29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyBy eCBwb29sPWRlZmF1bHQucmd3LmxvZywgYWxsb3cgeCBwb29sPWRlZmF1bHQucmd3LmJ1Y2tldHMu - aW5kZXgiXSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNv - biIsICJwcmVmaXgiOiAiYXV0aCBjYXBzIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5Ijoi - Y2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0NWJGUkFBVG5kTE5VU1JLcnVv - enhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBxdW9y - dW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdyIjogImFsbG93IGNvbW1hbmQg - Y29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPWRl - ZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9ZGVm - YXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93IHgg - cG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4In19XSIiIgogICAgICAgIHNlbGYuY21kX291 - dHB1dF9tYXBbIiIieyJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAibWdyIHNlcnZpY2VzIn0i - IiJdID0gKAogICAgICAgICAgICAiIiJ7ImRhc2hib2FyZCI6ICJodHRwOi8vcm9vay1jZXBoLW1n - ci1hLTU3Y2Y5Zjg0YmMtZjRqbmw6NzAwMC8iLCAicHJvbWV0aGV1cyI6ICJodHRwOi8vcm9vay1j - ZXBoLW1nci1hLTU3Y2Y5Zjg0YmMtZjRqbmw6OTI4My8ifSIiIgogICAgICAgICkKICAgICAgICBz - ZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuaGVh - bHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgog - ICAgICAgIF0gPSAiIiJ7ImRhc2hib2FyZCI6ICJodHRwOi8vcm9vay1jZXBoLW1nci1hLTU3Y2Y5 - Zjg0YmMtZjRqbmw6NzAwMC8iLCAicHJvbWV0aGV1cyI6ICJodHRwOi8vcm9vay1jZXBoLW1nci1h - LTU3Y2Y5Zjg0YmMtZjRqbmw6OTI4My8ifSIiIgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBb - CiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5oZWFsdGhjaGVja2VyIiwgImZvcm1h - dCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVu - dGl0eSI6ImNsaWVudC5oZWFsdGhjaGVja2VyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExO - VVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjogImFsbG93IHIsIGFsbG93IGNvbW1h - bmQgcXVvcnVtX3N0YXR1cywgYWxsb3cgY29tbWFuZCB2ZXJzaW9uIiwgIm1nciI6ICJhbGxvdyBj - b21tYW5kIGNvbmZpZyIsICJvc2QiOiAicHJvZmlsZSByYmQtcmVhZC1vbmx5LCBhbGxvdyByd3gg - cG9vbD1kZWZhdWx0LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290LCBhbGxvdyBydyBw - b29sPWRlZmF1bHQucmd3LmNvbnRyb2wsIGFsbG93IHJ4IHBvb2w9ZGVmYXVsdC5yZ3cubG9nLCBh - bGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIKICAgICAgICBzZWxm - LmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuY3NpLWNl - cGhmcy1ub2RlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAg - ICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAg - ICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtbm9kZSIsICJmb3JtYXQiOiAianNvbiIs - ICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIiIgogICAgICAgIHNl - bGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5jc2kt - cmJkLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9 - IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAg - ICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAi - Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0gIiIi - W10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0 - eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lci1vcGVuc2hpZnQtc3RvcmFnZSIsICJm - b3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJb - XSIiIgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5 - IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMi - LCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0g - IiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVu - dGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQiOiAianNvbiIs - ICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGll - bnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVT - RUtydW96eGlaaTNscmRBPT0iLCJjYXBzIjp7Im1vbiI6ImFsbG93IHIiLCAibWdyIjoiYWxsb3cg - cnciLCAib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIn19XSIiIgogICAgICAg - IHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgImFs - bG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJhbGxvdyBydyIs - ICJvc2QiLCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIl0sICJlbnRpdHkiOiAiY2xp - ZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4Ijog - ImF1dGggY2FwcyJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2Vw - aGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExOVVNFS3J1b3p4aVpp - M2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cgciwgIGFsbG93IGNvbW1hbmQgJ29zZCBibG9j - a2xpc3QnIiwgIm1nciI6ImFsbG93IHJ3IiwgIm9zZCI6ImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0 - YWRhdGE9KiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWyd7ImZvcm1hdCI6ICJq - c29uIiwgInByZWZpeCI6ICJzdGF0dXMifSddID0gY2VwaF9zdGF0dXNfc3RyCgogICAgZGVmIHNo - dXRkb3duKHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgZ2V0X2ZzaWQoc2VsZik6CiAgICAg - ICAgcmV0dXJuICJhZjRlMTY3My0wYjcyLTQwMmQtOTkwYS0yMmQyOTE5ZDBmMWMiCgogICAgZGVm - IGNvbmZfcmVhZF9maWxlKHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgY29ubmVjdChzZWxm - KToKICAgICAgICBwYXNzCgogICAgZGVmIHBvb2xfZXhpc3RzKHNlbGYsIHBvb2xfbmFtZSk6CiAg - ICAgICAgcmV0dXJuIFRydWUKCiAgICBkZWYgbW9uX2NvbW1hbmQoc2VsZiwgY21kLCBvdXQpOgog - ICAgICAgIGpzb25fY21kID0ganNvbi5sb2FkcyhjbWQpCiAgICAgICAganNvbl9jbWRfc3RyID0g - anNvbi5kdW1wcyhqc29uX2NtZCwgc29ydF9rZXlzPVRydWUpCiAgICAgICAgY21kX291dHB1dCA9 - IHNlbGYuY21kX291dHB1dF9tYXBbanNvbl9jbWRfc3RyXQogICAgICAgIHJldHVybiBzZWxmLnJl - dHVybl92YWwsIGNtZF9vdXRwdXQsIHN0cihzZWxmLmVycl9tZXNzYWdlLmVuY29kZSgidXRmLTgi - KSkKCiAgICBkZWYgX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoc2VsZiwgaG9zdF9uYW1lKToKICAg - ICAgICBpcF9yZWdfeCA9IHJlLmNvbXBpbGUociJcZHsxLDN9LlxkezEsM30uXGR7MSwzfS5cZHsx - LDN9IikKICAgICAgICAjIGlmIHByb3ZpZGVkIGhvc3QgaXMgZGlyZWN0bHkgYW4gSVAgYWRkcmVz - cywgcmV0dXJuIHRoZSBzYW1lCiAgICAgICAgaWYgaXBfcmVnX3gubWF0Y2goaG9zdF9uYW1lKToK - ICAgICAgICAgICAgcmV0dXJuIGhvc3RfbmFtZQogICAgICAgIGltcG9ydCByYW5kb20KCiAgICAg - ICAgaG9zdF9pcCA9IHNlbGYuZHVtbXlfaG9zdF9pcF9tYXAuZ2V0KGhvc3RfbmFtZSwgIiIpCiAg - ICAgICAgaWYgbm90IGhvc3RfaXA6CiAgICAgICAgICAgIGhvc3RfaXAgPSBmIjE3Mi45LntyYW5k - b20ucmFuZGludCgwLCAyNTQpfS57cmFuZG9tLnJhbmRpbnQoMCwgMjU0KX0iCiAgICAgICAgICAg - IHNlbGYuZHVtbXlfaG9zdF9pcF9tYXBbaG9zdF9uYW1lXSA9IGhvc3RfaXAKICAgICAgICBkZWwg - cmFuZG9tCiAgICAgICAgcmV0dXJuIGhvc3RfaXAKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBS - YWRvcyhjb25mZmlsZT1Ob25lKToKICAgICAgICByZXR1cm4gRHVtbXlSYWRvcygpCgoKY2xhc3Mg - UzNBdXRoKEF1dGhCYXNlKToKICAgICIiIkF0dGFjaGVzIEFXUyBBdXRoZW50aWNhdGlvbiB0byB0 - aGUgZ2l2ZW4gUmVxdWVzdCBvYmplY3QuIiIiCgogICAgc2VydmljZV9iYXNlX3VybCA9ICJzMy5h - bWF6b25hd3MuY29tIgoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhY2Nlc3Nfa2V5LCBzZWNyZXRf - a2V5LCBzZXJ2aWNlX3VybD1Ob25lKToKICAgICAgICBpZiBzZXJ2aWNlX3VybDoKICAgICAgICAg - ICAgc2VsZi5zZXJ2aWNlX2Jhc2VfdXJsID0gc2VydmljZV91cmwKICAgICAgICBzZWxmLmFjY2Vz - c19rZXkgPSBzdHIoYWNjZXNzX2tleSkKICAgICAgICBzZWxmLnNlY3JldF9rZXkgPSBzdHIoc2Vj - cmV0X2tleSkKCiAgICBkZWYgX19jYWxsX18oc2VsZiwgcik6CiAgICAgICAgIyBDcmVhdGUgZGF0 - ZSBoZWFkZXIgaWYgaXQgaXMgbm90IGNyZWF0ZWQgeWV0LgogICAgICAgIGlmICJkYXRlIiBub3Qg - aW4gci5oZWFkZXJzIGFuZCAieC1hbXotZGF0ZSIgbm90IGluIHIuaGVhZGVyczoKICAgICAgICAg - ICAgci5oZWFkZXJzWyJkYXRlIl0gPSBmb3JtYXRkYXRlKHRpbWV2YWw9Tm9uZSwgbG9jYWx0aW1l - PUZhbHNlLCB1c2VnbXQ9VHJ1ZSkKICAgICAgICBzaWduYXR1cmUgPSBzZWxmLmdldF9zaWduYXR1 - cmUocikKICAgICAgICBzaWduYXR1cmUgPSBzaWduYXR1cmUuZGVjb2RlKCJ1dGYtOCIpCiAgICAg - ICAgci5oZWFkZXJzWyJBdXRob3JpemF0aW9uIl0gPSBmIkFXUyB7c2VsZi5hY2Nlc3Nfa2V5fTp7 - c2lnbmF0dXJlfSIKICAgICAgICByZXR1cm4gcgoKICAgIGRlZiBnZXRfc2lnbmF0dXJlKHNlbGYs - IHIpOgogICAgICAgIGNhbm9uaWNhbF9zdHJpbmcgPSBzZWxmLmdldF9jYW5vbmljYWxfc3RyaW5n - KHIudXJsLCByLmhlYWRlcnMsIHIubWV0aG9kKQogICAgICAgIGtleSA9IHNlbGYuc2VjcmV0X2tl - eS5lbmNvZGUoInV0Zi04IikKICAgICAgICBtc2cgPSBjYW5vbmljYWxfc3RyaW5nLmVuY29kZSgi - dXRmLTgiKQogICAgICAgIGggPSBobWFjLm5ldyhrZXksIG1zZywgZGlnZXN0bW9kPXNoYSkKICAg - ICAgICByZXR1cm4gZW5jb2Rlc3RyaW5nKGguZGlnZXN0KCkpLnN0cmlwKCkKCiAgICBkZWYgZ2V0 - X2Nhbm9uaWNhbF9zdHJpbmcoc2VsZiwgdXJsLCBoZWFkZXJzLCBtZXRob2QpOgogICAgICAgIHBh - cnNlZHVybCA9IHVybHBhcnNlKHVybCkKICAgICAgICBvYmplY3RrZXkgPSBwYXJzZWR1cmwucGF0 - aFsxOl0KCiAgICAgICAgYnVja2V0ID0gcGFyc2VkdXJsLm5ldGxvY1s6IC1sZW4oc2VsZi5zZXJ2 - aWNlX2Jhc2VfdXJsKV0KICAgICAgICBpZiBsZW4oYnVja2V0KSA+IDE6CiAgICAgICAgICAgICMg - cmVtb3ZlIGxhc3QgZG90CiAgICAgICAgICAgIGJ1Y2tldCA9IGJ1Y2tldFs6LTFdCgogICAgICAg - IGludGVyZXN0aW5nX2hlYWRlcnMgPSB7ImNvbnRlbnQtbWQ1IjogIiIsICJjb250ZW50LXR5cGUi - OiAiIiwgImRhdGUiOiAiIn0KICAgICAgICBmb3Iga2V5IGluIGhlYWRlcnM6CiAgICAgICAgICAg - IGxrID0ga2V5Lmxvd2VyKCkKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgbGsgPSBs - ay5kZWNvZGUoInV0Zi04IikKICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgcGFz - cwogICAgICAgICAgICBpZiBoZWFkZXJzW2tleV0gYW5kICgKICAgICAgICAgICAgICAgIGxrIGlu - IGludGVyZXN0aW5nX2hlYWRlcnMua2V5cygpIG9yIGxrLnN0YXJ0c3dpdGgoIngtYW16LSIpCiAg - ICAgICAgICAgICk6CiAgICAgICAgICAgICAgICBpbnRlcmVzdGluZ19oZWFkZXJzW2xrXSA9IGhl - YWRlcnNba2V5XS5zdHJpcCgpCgogICAgICAgICMgSWYgeC1hbXotZGF0ZSBpcyB1c2VkIGl0IHN1 - cGVyc2VkZXMgdGhlIGRhdGUgaGVhZGVyLgogICAgICAgIGlmICJ4LWFtei1kYXRlIiBpbiBpbnRl - cmVzdGluZ19oZWFkZXJzOgogICAgICAgICAgICBpbnRlcmVzdGluZ19oZWFkZXJzWyJkYXRlIl0g - PSAiIgoKICAgICAgICBidWYgPSBmInttZXRob2R9XG4iCiAgICAgICAgZm9yIGtleSBpbiBzb3J0 - ZWQoaW50ZXJlc3RpbmdfaGVhZGVycy5rZXlzKCkpOgogICAgICAgICAgICB2YWwgPSBpbnRlcmVz - dGluZ19oZWFkZXJzW2tleV0KICAgICAgICAgICAgaWYga2V5LnN0YXJ0c3dpdGgoIngtYW16LSIp - OgogICAgICAgICAgICAgICAgYnVmICs9IGYie2tleX06e3ZhbH1cbiIKICAgICAgICAgICAgZWxz - ZToKICAgICAgICAgICAgICAgIGJ1ZiArPSBmInt2YWx9XG4iCgogICAgICAgICMgYXBwZW5kIHRo - ZSBidWNrZXQgaWYgaXQgZXhpc3RzCiAgICAgICAgaWYgYnVja2V0ICE9ICIiOgogICAgICAgICAg - ICBidWYgKz0gZiIve2J1Y2tldH0iCgogICAgICAgICMgYWRkIHRoZSBvYmplY3RrZXkuIGV2ZW4g - aWYgaXQgZG9lc24ndCBleGlzdCwgYWRkIHRoZSBzbGFzaAogICAgICAgIGJ1ZiArPSBmIi97b2Jq - ZWN0a2V5fSIKCiAgICAgICAgcmV0dXJuIGJ1ZgoKCmNsYXNzIFJhZG9zSlNPTjoKICAgIEVYVEVS - TkFMX1VTRVJfTkFNRSA9ICJjbGllbnQuaGVhbHRoY2hlY2tlciIKICAgIEVYVEVSTkFMX1JHV19B - RE1JTl9PUFNfVVNFUl9OQU1FID0gInJndy1hZG1pbi1vcHMtdXNlciIKICAgIEVNUFRZX09VVFBV - VF9MSVNUID0gIkVtcHR5IG91dHB1dCBsaXN0IgogICAgREVGQVVMVF9SR1dfUE9PTF9QUkVGSVgg - PSAiZGVmYXVsdCIKICAgIERFRkFVTFRfTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUID0gIjkyODMi - CgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgZ2VuX2FyZ19wYXJzZXIoY2xzLCBhcmdzX3RvX3Bh - cnNlPU5vbmUpOgogICAgICAgIGFyZ1AgPSBhcmdwYXJzZS5Bcmd1bWVudFBhcnNlcigpCgogICAg - ICAgIGNvbW1vbl9ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJjb21tb24iKQogICAg - ICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoIi0tdmVyYm9zZSIsICItdiIsIGFjdGlvbj0i - c3RvcmVfdHJ1ZSIsIGRlZmF1bHQ9RmFsc2UpCiAgICAgICAgY29tbW9uX2dyb3VwLmFkZF9hcmd1 - bWVudCgKICAgICAgICAgICAgIi0tY2VwaC1jb25mIiwgIi1jIiwgaGVscD0iUHJvdmlkZSBhIGNl - cGggY29uZiBmaWxlLiIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiCiAgICAgICAgKQogICAgICAgIGNv - bW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWtleXJpbmciLCAiLWsiLCBo - ZWxwPSJQYXRoIHRvIGNlcGgga2V5cmluZyBmaWxlLiIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiCiAg - ICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICIt - LXJ1bi1hcy11c2VyIiwKICAgICAgICAgICAgIi11IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwK - ICAgICAgICAgICAgdHlwZT1zdHIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIGEgdXNlciBu - YW1lIHRvIGNoZWNrIHRoZSBjbHVzdGVyJ3MgaGVhbHRoIHN0YXR1cywgbXVzdCBiZSBwcmVmaXhl - ZCBieSAnY2xpZW50LiciLAogICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3Vt - ZW50KAogICAgICAgICAgICAiLS1jbHVzdGVyLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIi - LAogICAgICAgICAgICBoZWxwPSJLdWJlcm5ldGVzIGNsdXN0ZXIgbmFtZShsZWdhY3kgZmxhZyks - IE5vdGU6IEVpdGhlciB1c2UgdGhpcyBvciAtLWs4cy1jbHVzdGVyLW5hbWUiLAogICAgICAgICkK - ICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1rOHMtY2x1 - c3Rlci1uYW1lIiwgZGVmYXVsdD0iIiwgaGVscD0iS3ViZXJuZXRlcyBjbHVzdGVyIG5hbWUiCiAg - ICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICIt - LW5hbWVzcGFjZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9Ik5h - bWVzcGFjZSB3aGVyZSBDZXBoQ2x1c3RlciBpcyBydW5uaW5nIiwKICAgICAgICApCiAgICAgICAg - Y29tbW9uX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXBvb2wtcHJlZml4 - IiwgZGVmYXVsdD0iIiwgaGVscD0iUkdXIFBvb2wgcHJlZml4IgogICAgICAgICkKICAgICAgICBj - b21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yZXN0cmljdGVkLWF1dGgt - cGVybWlzc2lvbiIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9 - IlJlc3RyaWN0IGNlcGhDU0lLZXlyaW5ncyBhdXRoIHBlcm1pc3Npb25zIHRvIHNwZWNpZmljIHBv - b2xzLCBjbHVzdGVyLiIKICAgICAgICAgICAgKyAiTWFuZGF0b3J5IGZsYWdzIHRoYXQgbmVlZCB0 - byBiZSBzZXQgYXJlIC0tcmJkLWRhdGEtcG9vbC1uYW1lLCBhbmQgLS1rOHMtY2x1c3Rlci1uYW1l - LiIKICAgICAgICAgICAgKyAiLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIGZsYWcgY2FuIGFsc28g - YmUgcGFzc2VkIGluIGNhc2Ugb2YgY2VwaGZzIHVzZXIgcmVzdHJpY3Rpb24sIHNvIGl0IGNhbiBy - ZXN0cmljdCB1c2VyIHRvIHBhcnRpY3VsYXIgY2VwaGZzIGZpbGVzeXN0ZW0iCiAgICAgICAgICAg - ICsgInNhbXBsZSBydW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rl - ci1yZXNvdXJjZXMucHkgLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIG15ZnMgLS1yYmQtZGF0YS1w - b29sLW5hbWUgcmVwbGljYXBvb2wgLS1rOHMtY2x1c3Rlci1uYW1lIHJvb2tzdG9yYWdlIC0tcmVz - dHJpY3RlZC1hdXRoLXBlcm1pc3Npb24gdHJ1ZWAiCiAgICAgICAgICAgICsgIk5vdGU6IFJlc3Ry - aWN0aW5nIHRoZSBjc2ktdXNlcnMgcGVyIHBvb2wsIGFuZCBwZXIgY2x1c3RlciB3aWxsIHJlcXVp - cmUgY3JlYXRpbmcgbmV3IGNzaS11c2VycyBhbmQgbmV3IHNlY3JldHMgZm9yIHRoYXQgY3NpLXVz - ZXJzLiIKICAgICAgICAgICAgKyAiU28gYXBwbHkgdGhlc2Ugc2VjcmV0cyBvbmx5IHRvIG5ldyBg - Q29uc3VtZXIgY2x1c3RlcmAgZGVwbG95bWVudCB3aGlsZSB1c2luZyB0aGUgc2FtZSBgU291cmNl - IGNsdXN0ZXJgLiIsCiAgICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQo - CiAgICAgICAgICAgICItLXYyLXBvcnQtZW5hYmxlIiwKICAgICAgICAgICAgYWN0aW9uPSJzdG9y - ZV90cnVlIiwKICAgICAgICAgICAgZGVmYXVsdD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iRW5h - YmxlIHYyIG1vbiBwb3J0KDMzMDApIGZvciBtb25zIiwKICAgICAgICApCgogICAgICAgIG91dHB1 - dF9ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJvdXRwdXQiKQogICAgICAgIG91dHB1 - dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWZvcm1hdCIsCiAgICAgICAgICAg - ICItdCIsCiAgICAgICAgICAgIGNob2ljZXM9WyJqc29uIiwgImJhc2giXSwKICAgICAgICAgICAg - ZGVmYXVsdD0ianNvbiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBvdXRwdXQgZm9y - bWF0IChqc29uIHwgYmFzaCkiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy - Z3VtZW50KAogICAgICAgICAgICAiLS1vdXRwdXQiLAogICAgICAgICAgICAiLW8iLAogICAgICAg - ICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJPdXRwdXQgd2lsbCBiZSBzdG9yZWQg - aW50byB0aGUgcHJvdmlkZWQgZmlsZSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5h - ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNlcGhmcy1maWxlc3lzdGVtLW5hbWUiLAogICAg - ICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBv - ZiB0aGUgQ2VwaCBmaWxlc3lzdGVtIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFk - ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tY2VwaGZzLW1ldGFkYXRhLXBvb2wtbmFtZSIsCiAg - ICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBuYW1l - IG9mIHRoZSBjZXBoZnMgbWV0YWRhdGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9n - cm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNlcGhmcy1kYXRhLXBvb2wtbmFtZSIs - CiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBu - YW1lIG9mIHRoZSBjZXBoZnMgZGF0YSBwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dy - b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmJkLWRhdGEtcG9vbC1uYW1lIiwKICAg - ICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAg - ICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBuYW1lIG9mIHRoZSBSQkQgZGF0YXBvb2wiLAogICAgICAg - ICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1hbGlh - cy1yYmQtZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAg - ICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iUHJvdmlkZXMgYW4gYWxpYXMgZm9y - IHRoZSAgUkJEIGRhdGEgcG9vbCBuYW1lLCBuZWNlc3NhcnkgaWYgYSBzcGVjaWFsIGNoYXJhY3Rl - ciBpcyBwcmVzZW50IGluIHRoZSBwb29sIG5hbWUgc3VjaCBhcyBhIHBlcmlvZCBvciB1bmRlcnNj - b3JlIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg - ICAgICAgIi0tcmd3LWVuZHBvaW50IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAg - ICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IlJBRE9TIEdhdGV3YXkgZW5kcG9p - bnQgKGluIGA8SVB2ND46PFBPUlQ+YCBvciBgPFtJUHY2XT46PFBPUlQ+YCBvciBgPEZRRE4+OjxQ - T1JUPmAgZm9ybWF0KSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1l - bnQoCiAgICAgICAgICAgICItLXJndy10bHMtY2VydC1wYXRoIiwKICAgICAgICAgICAgZGVmYXVs - dD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IlJBRE9T - IEdhdGV3YXkgZW5kcG9pbnQgVExTIGNlcnRpZmljYXRlIiwKICAgICAgICApCiAgICAgICAgb3V0 - cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXNraXAtdGxzIiwKICAg - ICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAg - ICAgICAgIGhlbHA9Iklnbm9yZSBUTFMgY2VydGlmaWNhdGlvbiB2YWxpZGF0aW9uIHdoZW4gYSBz - ZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZSBpcyBwcm92aWRlZCAoTk9UIFJFQ09NTUVOREVEIiwKICAg - ICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0t - bW9uaXRvcmluZy1lbmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAg - IHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJDZXBoIE1hbmFnZXIgcHJvbWV0aGV1 - cyBleHBvcnRlciBlbmRwb2ludHMgKGNvbW1hIHNlcGFyYXRlZCBsaXN0IG9mIChmb3JtYXQgYDxJ - UHY0PmAgb3IgYDxbSVB2Nl0+YCBvciBgPEZRRE4+YCkgZW50cmllcyBvZiBhY3RpdmUgYW5kIHN0 - YW5kYnkgbWdycykiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50 - KAogICAgICAgICAgICAiLS1tb25pdG9yaW5nLWVuZHBvaW50LXBvcnQiLAogICAgICAgICAgICBk - ZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0i - Q2VwaCBNYW5hZ2VyIHByb21ldGhldXMgZXhwb3J0ZXIgcG9ydCIsCiAgICAgICAgKQogICAgICAg - IG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXNraXAtbW9uaXRvcmlu - Zy1lbmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGFjdGlv - bj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGhlbHA9IkRvIG5vdCBjaGVjayBmb3IgYSBtb25p - dG9yaW5nIGVuZHBvaW50IGZvciB0aGUgQ2VwaCBjbHVzdGVyIiwKICAgICAgICApCiAgICAgICAg - b3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmJkLW1ldGFkYXRhLWVj - LXBvb2wtbmFtZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVk - PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiBlcmFzdXJlIGNv - ZGVkIFJCRCBtZXRhZGF0YSBwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFk - ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tZHJ5LXJ1biIsCiAgICAgICAgICAgIGRlZmF1bHQ9 - RmFsc2UsCiAgICAgICAgICAgIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGhlbHA9 - IkRyeSBydW4gcHJpbnRzIHRoZSBleGVjdXRlZCBjb21tYW5kcyB3aXRob3V0IHJ1bm5pbmcgdGhl - bSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAg - ICAgICItLXJhZG9zLW5hbWVzcGFjZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAg - ICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJEaXZpZGVzIGEgcG9vbCBpbnRv - IHNlcGFyYXRlIGxvZ2ljYWwgbmFtZXNwYWNlcywgdXNlZCBmb3IgY3JlYXRpbmcgUkJEIFBWQyBp - biBhIENlcGhCbG9ja1Bvb2xSYWRvc05hbWVzcGFjZSAoc2hvdWxkIGJlIGxvd2VyIGNhc2UpIiwK + aW5kZXgiLCAibWRzIiwgImFsbG93ICoiXSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tl + ciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBjYXBzIn0iIiIKICAgICAgICBd + ID0gIiIiW3siZW50aXR5IjoiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0 + NWJGUkFBVG5kTE5VU1JLcnVvenhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwg + YWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdy + IjogImFsbG93IGNvbW1hbmQgY29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHks + IGFsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3Qs + IGFsbG93IHJ3IHBvb2w9ZGVmYXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0 + LnJndy5sb2csIGFsbG93IHggcG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4IiwibWRzIjoi + YWxsb3cgKiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWyIiInsiZm9ybWF0Ijog + Impzb24iLCAicHJlZml4IjogIm1nciBzZXJ2aWNlcyJ9IiIiXSA9ICgKICAgICAgICAgICAgIiIi + eyJkYXNoYm9hcmQiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0am5sOjcw + MDAvIiwgInByb21ldGhldXMiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0 + am5sOjkyODMvIn0iIiIKICAgICAgICApCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAg + ICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCAiZm9ybWF0Ijog + Impzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0gIiIieyJkYXNoYm9h + cmQiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0am5sOjcwMDAvIiwgInBy + b21ldGhldXMiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0am5sOjkyODMv + In0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0 + eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAi + YXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuaGVhbHRoY2hl + Y2tlciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNscmRBPT0iLCJj + YXBzIjp7Im1vbiI6ICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93 + IGNvbW1hbmQgdmVyc2lvbiIsICJtZ3IiOiAiYWxsb3cgY29tbWFuZCBjb25maWciLCAib3NkIjog + InByb2ZpbGUgcmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwg + YWxsb3cgciBwb29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9s + LCBhbGxvdyByeCBwb29sPWRlZmF1bHQucmd3LmxvZywgYWxsb3cgeCBwb29sPWRlZmF1bHQucmd3 + LmJ1Y2tldHMuaW5kZXgiLCJtZHMiOiJhbGxvdyAqIn19XSIiIgogICAgICAgIHNlbGYuY21kX291 + dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLW5v + ZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBd + ID0gIiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7 + ImVudGl0eSI6ICJjbGllbnQuY3NpLXJiZC1ub2RlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZp + eCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRf + b3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtcHJv + dmlzaW9uZXIiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAg + ICAgICBdID0gIiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAg + ICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQi + OiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIiIgog + ICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNs + aWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlIiwgImZvcm1hdCI6 + ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAg + ICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xp + ZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UtbXlmcyIsICJmb3Jt + YXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIi + IgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5Ijog + ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZp + eCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2kt + Y2VwaGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExOVVNFS3J1b3p4 + aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cgciIsICJtZ3IiOiJhbGxvdyBydyIsICJv + c2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiLCJtZHMiOiJhbGxvdyAqIn19XSIi + IgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsi + bW9uIiwgImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJh + bGxvdyBydyIsICJvc2QiLCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIiwgIm1kcyIs + ICJhbGxvdyAqIl0sICJlbnRpdHkiOiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAi + Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggY2FwcyJ9IiIiCiAgICAgICAgXSA9ICIi + Ilt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmti + TmVmdDViRlJBQVRuZExOVVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cg + ciwgIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciI6ImFsbG93IHJ3IiwgIm9z + ZCI6ImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiIsIm1kcyI6ImFsbG93ICoifX1dIiIi + CiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsneyJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgi + OiAic3RhdHVzIn0nXSA9IGNlcGhfc3RhdHVzX3N0cgoKICAgIGRlZiBzaHV0ZG93bihzZWxmKToK + ICAgICAgICBwYXNzCgogICAgZGVmIGdldF9mc2lkKHNlbGYpOgogICAgICAgIHJldHVybiAiYWY0 + ZTE2NzMtMGI3Mi00MDJkLTk5MGEtMjJkMjkxOWQwZjFjIgoKICAgIGRlZiBjb25mX3JlYWRfZmls + ZShzZWxmKToKICAgICAgICBwYXNzCgogICAgZGVmIGNvbm5lY3Qoc2VsZik6CiAgICAgICAgcGFz + cwoKICAgIGRlZiBwb29sX2V4aXN0cyhzZWxmLCBwb29sX25hbWUpOgogICAgICAgIHJldHVybiBU + cnVlCgogICAgZGVmIG1vbl9jb21tYW5kKHNlbGYsIGNtZCwgb3V0KToKICAgICAgICBqc29uX2Nt + ZCA9IGpzb24ubG9hZHMoY21kKQogICAgICAgIGpzb25fY21kX3N0ciA9IGpzb24uZHVtcHMoanNv + bl9jbWQsIHNvcnRfa2V5cz1UcnVlKQogICAgICAgIGNtZF9vdXRwdXQgPSBzZWxmLmNtZF9vdXRw + dXRfbWFwW2pzb25fY21kX3N0cl0KICAgICAgICByZXR1cm4gc2VsZi5yZXR1cm5fdmFsLCBjbWRf + b3V0cHV0LCBzdHIoc2VsZi5lcnJfbWVzc2FnZS5lbmNvZGUoInV0Zi04IikpCgogICAgZGVmIF9j + b252ZXJ0X2hvc3RuYW1lX3RvX2lwKHNlbGYsIGhvc3RfbmFtZSk6CiAgICAgICAgaXBfcmVnX3gg + PSByZS5jb21waWxlKHIiXGR7MSwzfS5cZHsxLDN9LlxkezEsM30uXGR7MSwzfSIpCiAgICAgICAg + IyBpZiBwcm92aWRlZCBob3N0IGlzIGRpcmVjdGx5IGFuIElQIGFkZHJlc3MsIHJldHVybiB0aGUg + c2FtZQogICAgICAgIGlmIGlwX3JlZ194Lm1hdGNoKGhvc3RfbmFtZSk6CiAgICAgICAgICAgIHJl + dHVybiBob3N0X25hbWUKICAgICAgICBpbXBvcnQgcmFuZG9tCgogICAgICAgIGhvc3RfaXAgPSBz + ZWxmLmR1bW15X2hvc3RfaXBfbWFwLmdldChob3N0X25hbWUsICIiKQogICAgICAgIGlmIG5vdCBo + b3N0X2lwOgogICAgICAgICAgICBob3N0X2lwID0gZiIxNzIuOS57cmFuZG9tLnJhbmRpbnQoMCwg + MjU0KX0ue3JhbmRvbS5yYW5kaW50KDAsIDI1NCl9IgogICAgICAgICAgICBzZWxmLmR1bW15X2hv + c3RfaXBfbWFwW2hvc3RfbmFtZV0gPSBob3N0X2lwCiAgICAgICAgZGVsIHJhbmRvbQogICAgICAg + IHJldHVybiBob3N0X2lwCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgUmFkb3MoY29uZmZpbGU9 + Tm9uZSk6CiAgICAgICAgcmV0dXJuIER1bW15UmFkb3MoKQoKCmNsYXNzIFMzQXV0aChBdXRoQmFz + ZSk6CiAgICAiIiJBdHRhY2hlcyBBV1MgQXV0aGVudGljYXRpb24gdG8gdGhlIGdpdmVuIFJlcXVl + c3Qgb2JqZWN0LiIiIgoKICAgIHNlcnZpY2VfYmFzZV91cmwgPSAiczMuYW1hem9uYXdzLmNvbSIK + CiAgICBkZWYgX19pbml0X18oc2VsZiwgYWNjZXNzX2tleSwgc2VjcmV0X2tleSwgc2VydmljZV91 + cmw9Tm9uZSk6CiAgICAgICAgaWYgc2VydmljZV91cmw6CiAgICAgICAgICAgIHNlbGYuc2Vydmlj + ZV9iYXNlX3VybCA9IHNlcnZpY2VfdXJsCiAgICAgICAgc2VsZi5hY2Nlc3Nfa2V5ID0gc3RyKGFj + Y2Vzc19rZXkpCiAgICAgICAgc2VsZi5zZWNyZXRfa2V5ID0gc3RyKHNlY3JldF9rZXkpCgogICAg + ZGVmIF9fY2FsbF9fKHNlbGYsIHIpOgogICAgICAgICMgQ3JlYXRlIGRhdGUgaGVhZGVyIGlmIGl0 + IGlzIG5vdCBjcmVhdGVkIHlldC4KICAgICAgICBpZiAiZGF0ZSIgbm90IGluIHIuaGVhZGVycyBh + bmQgIngtYW16LWRhdGUiIG5vdCBpbiByLmhlYWRlcnM6CiAgICAgICAgICAgIHIuaGVhZGVyc1si + ZGF0ZSJdID0gZm9ybWF0ZGF0ZSh0aW1ldmFsPU5vbmUsIGxvY2FsdGltZT1GYWxzZSwgdXNlZ210 + PVRydWUpCiAgICAgICAgc2lnbmF0dXJlID0gc2VsZi5nZXRfc2lnbmF0dXJlKHIpCiAgICAgICAg + c2lnbmF0dXJlID0gc2lnbmF0dXJlLmRlY29kZSgidXRmLTgiKQogICAgICAgIHIuaGVhZGVyc1si + QXV0aG9yaXphdGlvbiJdID0gZiJBV1Mge3NlbGYuYWNjZXNzX2tleX06e3NpZ25hdHVyZX0iCiAg + ICAgICAgcmV0dXJuIHIKCiAgICBkZWYgZ2V0X3NpZ25hdHVyZShzZWxmLCByKToKICAgICAgICBj + YW5vbmljYWxfc3RyaW5nID0gc2VsZi5nZXRfY2Fub25pY2FsX3N0cmluZyhyLnVybCwgci5oZWFk + ZXJzLCByLm1ldGhvZCkKICAgICAgICBrZXkgPSBzZWxmLnNlY3JldF9rZXkuZW5jb2RlKCJ1dGYt + OCIpCiAgICAgICAgbXNnID0gY2Fub25pY2FsX3N0cmluZy5lbmNvZGUoInV0Zi04IikKICAgICAg + ICBoID0gaG1hYy5uZXcoa2V5LCBtc2csIGRpZ2VzdG1vZD1zaGEpCiAgICAgICAgcmV0dXJuIGVu + Y29kZXN0cmluZyhoLmRpZ2VzdCgpKS5zdHJpcCgpCgogICAgZGVmIGdldF9jYW5vbmljYWxfc3Ry + aW5nKHNlbGYsIHVybCwgaGVhZGVycywgbWV0aG9kKToKICAgICAgICBwYXJzZWR1cmwgPSB1cmxw + YXJzZSh1cmwpCiAgICAgICAgb2JqZWN0a2V5ID0gcGFyc2VkdXJsLnBhdGhbMTpdCgogICAgICAg + IGJ1Y2tldCA9IHBhcnNlZHVybC5uZXRsb2NbOiAtbGVuKHNlbGYuc2VydmljZV9iYXNlX3VybCld + CiAgICAgICAgaWYgbGVuKGJ1Y2tldCkgPiAxOgogICAgICAgICAgICAjIHJlbW92ZSBsYXN0IGRv + dAogICAgICAgICAgICBidWNrZXQgPSBidWNrZXRbOi0xXQoKICAgICAgICBpbnRlcmVzdGluZ19o + ZWFkZXJzID0geyJjb250ZW50LW1kNSI6ICIiLCAiY29udGVudC10eXBlIjogIiIsICJkYXRlIjog + IiJ9CiAgICAgICAgZm9yIGtleSBpbiBoZWFkZXJzOgogICAgICAgICAgICBsayA9IGtleS5sb3dl + cigpCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGxrID0gbGsuZGVjb2RlKCJ1dGYt + OCIpCiAgICAgICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgICAgIHBhc3MKICAgICAgICAgICAg + aWYgaGVhZGVyc1trZXldIGFuZCAoCiAgICAgICAgICAgICAgICBsayBpbiBpbnRlcmVzdGluZ19o + ZWFkZXJzLmtleXMoKSBvciBsay5zdGFydHN3aXRoKCJ4LWFtei0iKQogICAgICAgICAgICApOgog + ICAgICAgICAgICAgICAgaW50ZXJlc3RpbmdfaGVhZGVyc1tsa10gPSBoZWFkZXJzW2tleV0uc3Ry + aXAoKQoKICAgICAgICAjIElmIHgtYW16LWRhdGUgaXMgdXNlZCBpdCBzdXBlcnNlZGVzIHRoZSBk + YXRlIGhlYWRlci4KICAgICAgICBpZiAieC1hbXotZGF0ZSIgaW4gaW50ZXJlc3RpbmdfaGVhZGVy + czoKICAgICAgICAgICAgaW50ZXJlc3RpbmdfaGVhZGVyc1siZGF0ZSJdID0gIiIKCiAgICAgICAg + YnVmID0gZiJ7bWV0aG9kfVxuIgogICAgICAgIGZvciBrZXkgaW4gc29ydGVkKGludGVyZXN0aW5n + X2hlYWRlcnMua2V5cygpKToKICAgICAgICAgICAgdmFsID0gaW50ZXJlc3RpbmdfaGVhZGVyc1tr + ZXldCiAgICAgICAgICAgIGlmIGtleS5zdGFydHN3aXRoKCJ4LWFtei0iKToKICAgICAgICAgICAg + ICAgIGJ1ZiArPSBmIntrZXl9Ont2YWx9XG4iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg + ICAgICBidWYgKz0gZiJ7dmFsfVxuIgoKICAgICAgICAjIGFwcGVuZCB0aGUgYnVja2V0IGlmIGl0 + IGV4aXN0cwogICAgICAgIGlmIGJ1Y2tldCAhPSAiIjoKICAgICAgICAgICAgYnVmICs9IGYiL3ti + dWNrZXR9IgoKICAgICAgICAjIGFkZCB0aGUgb2JqZWN0a2V5LiBldmVuIGlmIGl0IGRvZXNuJ3Qg + ZXhpc3QsIGFkZCB0aGUgc2xhc2gKICAgICAgICBidWYgKz0gZiIve29iamVjdGtleX0iCgogICAg + ICAgIHJldHVybiBidWYKCgpjbGFzcyBSYWRvc0pTT046CiAgICBFWFRFUk5BTF9VU0VSX05BTUUg + PSAiY2xpZW50LmhlYWx0aGNoZWNrZXIiCiAgICBFWFRFUk5BTF9SR1dfQURNSU5fT1BTX1VTRVJf + TkFNRSA9ICJyZ3ctYWRtaW4tb3BzLXVzZXIiCiAgICBFTVBUWV9PVVRQVVRfTElTVCA9ICJFbXB0 + eSBvdXRwdXQgbGlzdCIKICAgIERFRkFVTFRfUkdXX1BPT0xfUFJFRklYID0gImRlZmF1bHQiCiAg + ICBERUZBVUxUX01PTklUT1JJTkdfRU5EUE9JTlRfUE9SVCA9ICI5MjgzIgoKICAgIEBjbGFzc21l + dGhvZAogICAgZGVmIGdlbl9hcmdfcGFyc2VyKGNscywgYXJnc190b19wYXJzZT1Ob25lKToKICAg + ICAgICBhcmdQID0gYXJncGFyc2UuQXJndW1lbnRQYXJzZXIoKQoKICAgICAgICBjb21tb25fZ3Jv + dXAgPSBhcmdQLmFkZF9hcmd1bWVudF9ncm91cCgiY29tbW9uIikKICAgICAgICBjb21tb25fZ3Jv + dXAuYWRkX2FyZ3VtZW50KCItLXZlcmJvc2UiLCAiLXYiLCBhY3Rpb249InN0b3JlX3RydWUiLCBk + ZWZhdWx0PUZhbHNlKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAg + ICAgICItLWNlcGgtY29uZiIsICItYyIsIGhlbHA9IlByb3ZpZGUgYSBjZXBoIGNvbmYgZmlsZS4i + LCB0eXBlPXN0ciwgZGVmYXVsdD0iIgogICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRk + X2FyZ3VtZW50KAogICAgICAgICAgICAiLS1rZXlyaW5nIiwgIi1rIiwgaGVscD0iUGF0aCB0byBj + ZXBoIGtleXJpbmcgZmlsZS4iLCB0eXBlPXN0ciwgZGVmYXVsdD0iIgogICAgICAgICkKICAgICAg + ICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1ydW4tYXMtdXNlciIs + CiAgICAgICAgICAgICItdSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHR5 + cGU9c3RyLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyBhIHVzZXIgbmFtZSB0byBjaGVjayB0 + aGUgY2x1c3RlcidzIGhlYWx0aCBzdGF0dXMsIG11c3QgYmUgcHJlZml4ZWQgYnkgJ2NsaWVudC4n + IiwKICAgICAgICApCiAgICAgICAgY29tbW9uX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAg + ICAgIi0tY2x1c3Rlci1uYW1lIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAg + aGVscD0iS3ViZXJuZXRlcyBjbHVzdGVyIG5hbWUobGVnYWN5IGZsYWcpLCBOb3RlOiBFaXRoZXIg + dXNlIHRoaXMgb3IgLS1rOHMtY2x1c3Rlci1uYW1lIiwKICAgICAgICApCiAgICAgICAgY29tbW9u + X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tazhzLWNsdXN0ZXItbmFtZSIsIGRl + ZmF1bHQ9IiIsIGhlbHA9Ikt1YmVybmV0ZXMgY2x1c3RlciBuYW1lIgogICAgICAgICkKICAgICAg + ICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1uYW1lc3BhY2UiLAog + ICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJOYW1lc3BhY2Ugd2hlcmUg + Q2VwaENsdXN0ZXIgaXMgcnVubmluZyIsCiAgICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5h + ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXJndy1wb29sLXByZWZpeCIsIGRlZmF1bHQ9IiIs + IGhlbHA9IlJHVyBQb29sIHByZWZpeCIKICAgICAgICApCiAgICAgICAgY29tbW9uX2dyb3VwLmFk + ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmVzdHJpY3RlZC1hdXRoLXBlcm1pc3Npb24iLAog + ICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJSZXN0cmljdCBjZXBo + Q1NJS2V5cmluZ3MgYXV0aCBwZXJtaXNzaW9ucyB0byBzcGVjaWZpYyBwb29scywgY2x1c3Rlci4i + CiAgICAgICAgICAgICsgIk1hbmRhdG9yeSBmbGFncyB0aGF0IG5lZWQgdG8gYmUgc2V0IGFyZSAt + LXJiZC1kYXRhLXBvb2wtbmFtZSwgYW5kIC0tazhzLWNsdXN0ZXItbmFtZS4iCiAgICAgICAgICAg + ICsgIi0tY2VwaGZzLWZpbGVzeXN0ZW0tbmFtZSBmbGFnIGNhbiBhbHNvIGJlIHBhc3NlZCBpbiBj + YXNlIG9mIGNlcGhmcyB1c2VyIHJlc3RyaWN0aW9uLCBzbyBpdCBjYW4gcmVzdHJpY3QgdXNlciB0 + byBwYXJ0aWN1bGFyIGNlcGhmcyBmaWxlc3lzdGVtIgogICAgICAgICAgICArICJzYW1wbGUgcnVu + OiBgcHl0aG9uMyAvZXRjL2NlcGgvY3JlYXRlLWV4dGVybmFsLWNsdXN0ZXItcmVzb3VyY2VzLnB5 + IC0tY2VwaGZzLWZpbGVzeXN0ZW0tbmFtZSBteWZzIC0tcmJkLWRhdGEtcG9vbC1uYW1lIHJlcGxp + Y2Fwb29sIC0tazhzLWNsdXN0ZXItbmFtZSByb29rc3RvcmFnZSAtLXJlc3RyaWN0ZWQtYXV0aC1w + ZXJtaXNzaW9uIHRydWVgIgogICAgICAgICAgICArICJOb3RlOiBSZXN0cmljdGluZyB0aGUgY3Np + LXVzZXJzIHBlciBwb29sLCBhbmQgcGVyIGNsdXN0ZXIgd2lsbCByZXF1aXJlIGNyZWF0aW5nIG5l + dyBjc2ktdXNlcnMgYW5kIG5ldyBzZWNyZXRzIGZvciB0aGF0IGNzaS11c2Vycy4iCiAgICAgICAg + ICAgICsgIlNvIGFwcGx5IHRoZXNlIHNlY3JldHMgb25seSB0byBuZXcgYENvbnN1bWVyIGNsdXN0 + ZXJgIGRlcGxveW1lbnQgd2hpbGUgdXNpbmcgdGhlIHNhbWUgYFNvdXJjZSBjbHVzdGVyYC4iLAog + ICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAi + LS12Mi1wb3J0LWVuYWJsZSIsCiAgICAgICAgICAgIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAg + ICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IkVuYWJsZSB2MiBtb24gcG9y + dCgzMzAwKSBmb3IgbW9ucyIsCiAgICAgICAgKQoKICAgICAgICBvdXRwdXRfZ3JvdXAgPSBhcmdQ + LmFkZF9hcmd1bWVudF9ncm91cCgib3V0cHV0IikKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy + Z3VtZW50KAogICAgICAgICAgICAiLS1mb3JtYXQiLAogICAgICAgICAgICAiLXQiLAogICAgICAg + ICAgICBjaG9pY2VzPVsianNvbiIsICJiYXNoIl0sCiAgICAgICAgICAgIGRlZmF1bHQ9Impzb24i + LAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgb3V0cHV0IGZvcm1hdCAoanNvbiB8IGJh + c2gpIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg + ICAgICAgIi0tb3V0cHV0IiwKICAgICAgICAgICAgIi1vIiwKICAgICAgICAgICAgZGVmYXVsdD0i + IiwKICAgICAgICAgICAgaGVscD0iT3V0cHV0IHdpbGwgYmUgc3RvcmVkIGludG8gdGhlIHByb3Zp + ZGVkIGZpbGUiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAog + ICAgICAgICAgICAiLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIiwKICAgICAgICAgICAgZGVmYXVs + dD0iIiwKICAgICAgICAgICAgaGVscD0iUHJvdmlkZXMgdGhlIG5hbWUgb2YgdGhlIENlcGggZmls + ZXN5c3RlbSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAg + ICAgICAgICAgICItLWNlcGhmcy1tZXRhZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBkZWZh + dWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgY2VwaGZz + IG1ldGFkYXRhIHBvb2wiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3Vt + ZW50KAogICAgICAgICAgICAiLS1jZXBoZnMtZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBk + ZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgY2Vw + aGZzIGRhdGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1l + bnQoCiAgICAgICAgICAgICItLXJiZC1kYXRhLXBvb2wtbmFtZSIsCiAgICAgICAgICAgIGRlZmF1 + bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJQcm92 + aWRlcyB0aGUgbmFtZSBvZiB0aGUgUkJEIGRhdGFwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0 + cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tYWxpYXMtcmJkLWRhdGEtcG9v + bC1uYW1lIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFs + c2UsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIGFuIGFsaWFzIGZvciB0aGUgIFJCRCBkYXRh + IHBvb2wgbmFtZSwgbmVjZXNzYXJ5IGlmIGEgc3BlY2lhbCBjaGFyYWN0ZXIgaXMgcHJlc2VudCBp + biB0aGUgcG9vbCBuYW1lIHN1Y2ggYXMgYSBwZXJpb2Qgb3IgdW5kZXJzY29yZSIsCiAgICAgICAg + KQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXJndy1l + bmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZh + bHNlLAogICAgICAgICAgICBoZWxwPSJSQURPUyBHYXRld2F5IGVuZHBvaW50IChpbiBgPElQdjQ+ + OjxQT1JUPmAgb3IgYDxbSVB2Nl0+OjxQT1JUPmAgb3IgYDxGUUROPjo8UE9SVD5gIGZvcm1hdCki + LAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAg + ICAiLS1yZ3ctdGxzLWNlcnQtcGF0aCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAg + ICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJSQURPUyBHYXRld2F5IGVuZHBv + aW50IFRMUyBjZXJ0aWZpY2F0ZSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRf + YXJndW1lbnQoCiAgICAgICAgICAgICItLXJndy1za2lwLXRscyIsCiAgICAgICAgICAgIHJlcXVp + cmVkPUZhbHNlLAogICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJJ + Z25vcmUgVExTIGNlcnRpZmljYXRpb24gdmFsaWRhdGlvbiB3aGVuIGEgc2VsZi1zaWduZWQgY2Vy + dGlmaWNhdGUgaXMgcHJvdmlkZWQgKE5PVCBSRUNPTU1FTkRFRCIsCiAgICAgICAgKQogICAgICAg + IG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLW1vbml0b3JpbmctZW5k + cG9pbnQiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxz + ZSwKICAgICAgICAgICAgaGVscD0iQ2VwaCBNYW5hZ2VyIHByb21ldGhldXMgZXhwb3J0ZXIgZW5k + cG9pbnRzIChjb21tYSBzZXBhcmF0ZWQgbGlzdCBvZiAoZm9ybWF0IGA8SVB2ND5gIG9yIGA8W0lQ + djZdPmAgb3IgYDxGUUROPmApIGVudHJpZXMgb2YgYWN0aXZlIGFuZCBzdGFuZGJ5IG1ncnMpIiwK ICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAg - Ii0tc3Vidm9sdW1lLWdyb3VwIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAg - cmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9InByb3ZpZGVzIHRoZSBuYW1lIG9mIHRo - ZSBzdWJ2b2x1bWUgZ3JvdXAiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy - Z3VtZW50KAogICAgICAgICAgICAiLS1yZ3ctcmVhbG0tbmFtZSIsCiAgICAgICAgICAgIGRlZmF1 - bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJwcm92 - aWRlcyB0aGUgbmFtZSBvZiB0aGUgcmd3LXJlYWxtIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0 - X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXpvbmUtbmFtZSIsCiAgICAg - ICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAg - ICBoZWxwPSJwcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgcmd3LXpvbmUiLAogICAgICAgICkKICAg - ICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yZ3ctem9uZWdy - b3VwLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1G - YWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlkZXMgdGhlIG5hbWUgb2YgdGhlIHJndy16b25l - Z3JvdXAiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAg - ICAgICAgICAiLS10b3BvbG9neS1wb29scyIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAg - ICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJjb21tYS1zZXBhcmF0ZWQg - bGlzdCBvZiB0b3BvbG9neS1jb25zdHJhaW5lZCByYmQgcG9vbHMiLAogICAgICAgICkKICAgICAg - ICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS10b3BvbG9neS1mYWls - dXJlLWRvbWFpbi1sYWJlbCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJl - cXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJrOHMgY2x1c3RlciBmYWlsdXJlIGRvbWFp - biBsYWJlbCAoZXhhbXBsZTogem9uZSwgcmFjaywgb3IgaG9zdCkgZm9yIHRoZSB0b3BvbG9neS1w - b29scyB0aGF0IG1hdGNoIHRoZSBjZXBoIGRvbWFpbiIsCiAgICAgICAgKQogICAgICAgIG91dHB1 - dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXRvcG9sb2d5LWZhaWx1cmUtZG9t - YWluLXZhbHVlcyIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVk - PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiB0aGUgazhz - IGNsdXN0ZXIgZmFpbHVyZSBkb21haW4gdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gZWFjaCBvZiB0 - aGUgcG9vbHMgaW4gdGhlIGB0b3BvbG9neS1wb29sc2AgbGlzdCIsCiAgICAgICAgKQoKICAgICAg - ICB1cGdyYWRlX2dyb3VwID0gYXJnUC5hZGRfYXJndW1lbnRfZ3JvdXAoInVwZ3JhZGUiKQogICAg - ICAgIHVwZ3JhZGVfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS11cGdyYWRlIiwK - ICAgICAgICAgICAgYWN0aW9uPSJzdG9yZV90cnVlIiwKICAgICAgICAgICAgZGVmYXVsdD1GYWxz - ZSwKICAgICAgICAgICAgaGVscD0iVXBncmFkZXMgdGhlIGNlcGhDU0lLZXlyaW5ncyhGb3IgZXhh - bXBsZTogY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIpIGFuZCBjbGllbnQuaGVhbHRoY2hl - Y2tlciBjZXBoIHVzZXJzIHdpdGggbmV3IHBlcm1pc3Npb25zIG5lZWRlZCBmb3IgdGhlIG5ldyBj - bHVzdGVyIHZlcnNpb24gYW5kIG9sZGVyIHBlcm1pc3Npb24gd2lsbCBzdGlsbCBiZSBhcHBsaWVk - LiIKICAgICAgICAgICAgKyAiU2FtcGxlIHJ1bjogYHB5dGhvbjMgL2V0Yy9jZXBoL2NyZWF0ZS1l - eHRlcm5hbC1jbHVzdGVyLXJlc291cmNlcy5weSAtLXVwZ3JhZGVgLCB0aGlzIHdpbGwgdXBncmFk - ZSBhbGwgdGhlIGRlZmF1bHQgY3NpIHVzZXJzKG5vbi1yZXN0cmljdGVkKSIKICAgICAgICAgICAg - KyAiRm9yIHJlc3RyaWN0ZWQgdXNlcnMoRm9yIGV4YW1wbGU6IGNsaWVudC5jc2ktY2VwaGZzLXBy - b3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMpLCB1c2VycyBjcmVhdGVkIHVzaW5nIC0t - cmVzdHJpY3RlZC1hdXRoLXBlcm1pc3Npb24gZmxhZyBuZWVkIHRvIHBhc3MgbWFuZGF0b3J5IGZs - YWdzIgogICAgICAgICAgICArICJtYW5kYXRvcnkgZmxhZ3M6ICctLXJiZC1kYXRhLXBvb2wtbmFt - ZSwgLS1rOHMtY2x1c3Rlci1uYW1lIGFuZCAtLXJ1bi1hcy11c2VyJyBmbGFncyB3aGlsZSB1cGdy - YWRpbmciCiAgICAgICAgICAgICsgImluIGNhc2Ugb2YgY2VwaGZzIHVzZXJzIGlmIHlvdSBoYXZl - IHBhc3NlZCAtLWNlcGhmcy1maWxlc3lzdGVtLW5hbWUgZmxhZyB3aGlsZSBjcmVhdGluZyB1c2Vy - IHRoZW4gd2hpbGUgdXBncmFkaW5nIGl0IHdpbGwgYmUgbWFuZGF0b3J5IHRvbyIKICAgICAgICAg - ICAgKyAiU2FtcGxlIHJ1bjogYHB5dGhvbjMgL2V0Yy9jZXBoL2NyZWF0ZS1leHRlcm5hbC1jbHVz - dGVyLXJlc291cmNlcy5weSAtLXVwZ3JhZGUgLS1yYmQtZGF0YS1wb29sLW5hbWUgcmVwbGljYXBv - b2wgLS1rOHMtY2x1c3Rlci1uYW1lIHJvb2tzdG9yYWdlICAtLXJ1bi1hcy11c2VyIGNsaWVudC5j - c2ktcmJkLW5vZGUtcm9va3N0b3JhZ2UtcmVwbGljYXBvb2xgIgogICAgICAgICAgICArICJQUzog - QW4gZXhpc3Rpbmcgbm9uLXJlc3RyaWN0ZWQgdXNlciBjYW5ub3QgYmUgY29udmVydGVkIHRvIGEg - cmVzdHJpY3RlZCB1c2VyIGJ5IHVwZ3JhZGluZy4iCiAgICAgICAgICAgICsgIlVwZ3JhZGUgZmxh - ZyBzaG91bGQgb25seSBiZSB1c2VkIHRvIGFwcGVuZCBuZXcgcGVybWlzc2lvbnMgdG8gdXNlcnMs - IGl0IHNob3VsZG4ndCBiZSB1c2VkIGZvciBjaGFuZ2luZyB1c2VyIGFscmVhZHkgYXBwbGllZCBw - ZXJtaXNzaW9uLCBmb3IgZXhhbXBsZSB5b3Ugc2hvdWxkbid0IGNoYW5nZSBpbiB3aGljaCBwb29s - IHVzZXIgaGFzIGFjY2VzcyIsCiAgICAgICAgKQoKICAgICAgICAjIEFkZCBjb21tYW5kLWxpbmUg - YXJndW1lbnRzCiAgICAgICAgY29uZmlnX2dyb3VwID0gYXJnUC5hZGRfYXJndW1lbnRfZ3JvdXAo - ImNvbmZpZyIpCiAgICAgICAgY29uZmlnX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAg - Ii0tY29uZmlnLWZpbGUiLAogICAgICAgICAgICB0eXBlPXN0ciwKICAgICAgICAgICAgaGVscD0i - UGF0aCB0byB0aGUgY29uZmlndXJhdGlvbiBmaWxlLCBQcmlvcml0eTogY29tbWFuZC1saW5lLWFy - Z3MgPiBjb25maWcuaW5pIGZpbGUgdmFsdWVzID4gZGVmYXVsdCB2YWx1ZXMiLAogICAgICAgICAg - ICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICApCgogICAg - ICAgIGlmIGFyZ3NfdG9fcGFyc2U6CiAgICAgICAgICAgIGFzc2VydCAoCiAgICAgICAgICAgICAg - ICB0eXBlKGFyZ3NfdG9fcGFyc2UpID09IGxpc3QKICAgICAgICAgICAgKSwgIkFyZ3VtZW50IHRv - ICdnZW5fYXJnX3BhcnNlcicgc2hvdWxkIGJlIGEgbGlzdCIKICAgICAgICBlbHNlOgogICAgICAg - ICAgICBhcmdzX3RvX3BhcnNlID0gc3lzLmFyZ3ZbMTpdCiAgICAgICAgcmV0dXJuIGFyZ1AucGFy - c2VfYXJncyhhcmdzX3RvX3BhcnNlKQoKICAgIGRlZiB2YWxpZGF0ZV9yYmRfbWV0YWRhdGFfZWNf - cG9vbF9uYW1lKHNlbGYpOgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmJkX21ldGFkYXRh - X2VjX3Bvb2xfbmFtZToKICAgICAgICAgICAgcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZSA9IHNl - bGYuX2FyZ19wYXJzZXIucmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQogICAgICAgICAgICByYmRf - cG9vbF9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5yYmRfZGF0YV9wb29sX25hbWUKCiAgICAgICAg - ICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRp - b25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJGbGFnICctLXJiZC1kYXRh - LXBvb2wtbmFtZScgc2hvdWxkIG5vdCBiZSBlbXB0eSIKICAgICAgICAgICAgICAgICkKCiAgICAg - ICAgICAgIGlmIHJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAg - ICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJG - bGFnICctLXJiZC1tZXRhZGF0YS1lYy1wb29sLW5hbWUnIHNob3VsZCBub3QgYmUgZW1wdHkiCiAg - ICAgICAgICAgICAgICApCgogICAgICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogIm9zZCBk - dW1wIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVy - cl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICBp - ZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFp - c2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBmIntjbWRf - anNvblsncHJlZml4J119IGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAgICAgICAgIGYi - RXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJ - U1R9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBtZXRhZGF0YV9wb29sX2V4aXN0LCBw - b29sX2V4aXN0ID0gRmFsc2UsIEZhbHNlCgogICAgICAgICAgICBmb3Iga2V5IGluIGpzb25fb3V0 - WyJwb29scyJdOgogICAgICAgICAgICAgICAgIyBpZiBlcmFzdXJlX2NvZGVfcHJvZmlsZSBpcyBl - bXB0eSBhbmQgcG9vbCBuYW1lIGV4aXN0cyB0aGVuIGl0IHJlcGxpY2EgcG9vbAogICAgICAgICAg - ICAgICAgaWYgKAogICAgICAgICAgICAgICAgICAgIGtleVsiZXJhc3VyZV9jb2RlX3Byb2ZpbGUi - XSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBrZXlbInBvb2xfbmFtZSJdID09IHJiZF9t - ZXRhZGF0YV9lY19wb29sX25hbWUKICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICAg - ICAgbWV0YWRhdGFfcG9vbF9leGlzdCA9IFRydWUKICAgICAgICAgICAgICAgICMgaWYgZXJhc3Vy - ZV9jb2RlX3Byb2ZpbGUgaXMgbm90IGVtcHR5IGFuZCBwb29sIG5hbWUgZXhpc3RzIHRoZW4gaXQg - aXMgZWMgcG9vbAogICAgICAgICAgICAgICAgaWYga2V5WyJlcmFzdXJlX2NvZGVfcHJvZmlsZSJd - IGFuZCBrZXlbInBvb2xfbmFtZSJdID09IHJiZF9wb29sX25hbWU6CiAgICAgICAgICAgICAgICAg - ICAgcG9vbF9leGlzdCA9IFRydWUKCiAgICAgICAgICAgIGlmIG5vdCBtZXRhZGF0YV9wb29sX2V4 - aXN0OgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAg - ICAgICAgICAgICAgICAgICAiUHJvdmlkZWQgcmJkX2VjX21ldGFkYXRhX3Bvb2wgbmFtZSwiCiAg - ICAgICAgICAgICAgICAgICAgZiIge3JiZF9tZXRhZGF0YV9lY19wb29sX25hbWV9LCBkb2VzIG5v - dCBleGlzdCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgbm90IHBvb2xfZXhpc3Q6 - CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg - ICAgICAgICAgICAgIGYiUHJvdmlkZWQgcmJkX2RhdGFfcG9vbCBuYW1lLCB7cmJkX3Bvb2xfbmFt - ZX0sIGRvZXMgbm90IGV4aXN0IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICByZXR1cm4g - cmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQoKICAgIGRlZiBkcnlfcnVuKHNlbGYsIG1zZyk6CiAg - ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICBwcmludCgiRXhl - Y3V0ZTogIiArICInIiArIG1zZyArICInIikKCiAgICBkZWYgdmFsaWRhdGVfcmd3X2VuZHBvaW50 - X3Rsc19jZXJ0KHNlbGYpOgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Rsc19jZXJ0 - X3BhdGg6CiAgICAgICAgICAgIHdpdGggb3BlbihzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2Vy - dF9wYXRoLCBlbmNvZGluZz0idXRmOCIpIGFzIGY6CiAgICAgICAgICAgICAgICBjb250ZW50cyA9 - IGYucmVhZCgpCiAgICAgICAgICAgICAgICByZXR1cm4gY29udGVudHMucnN0cmlwKCkKCiAgICBk - ZWYgX2NoZWNrX2NvbmZsaWN0aW5nX29wdGlvbnMoc2VsZik6CiAgICAgICAgaWYgbm90IHNlbGYu - X2FyZ19wYXJzZXIudXBncmFkZSBhbmQgbm90IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9v - bF9uYW1lOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAg - ICAgICAgICAgICAgIkVpdGhlciAnLS11cGdyYWRlJyBvciAnLS1yYmQtZGF0YS1wb29sLW5hbWUg - PHBvb2xfbmFtZT4nIHNob3VsZCBiZSBzcGVjaWZpZWQiCiAgICAgICAgICAgICkKCiAgICBkZWYg - X2ludmFsaWRfZW5kcG9pbnQoc2VsZiwgZW5kcG9pbnRfc3RyKToKICAgICAgICAjIGV4dHJhY3Qg - dGhlIHBvcnQgYnkgZ2V0dGluZyB0aGUgbGFzdCBzcGxpdCBvbiBgOmAgZGVsaW1pdGVyCiAgICAg - ICAgdHJ5OgogICAgICAgICAgICBlbmRwb2ludF9zdHJfaXAsIHBvcnQgPSBlbmRwb2ludF9zdHIu - cnNwbGl0KCI6IiwgMSkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgcmFp - c2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbihmIk5vdCBhIHByb3BlciBlbmRwb2ludDoge2Vu - ZHBvaW50X3N0cn0iKQoKICAgICAgICB0cnk6CiAgICAgICAgICAgIGlmIGVuZHBvaW50X3N0cl9p - cFswXSA9PSAiWyI6CiAgICAgICAgICAgICAgICBlbmRwb2ludF9zdHJfaXAgPSBlbmRwb2ludF9z - dHJfaXBbMSA6IGxlbihlbmRwb2ludF9zdHJfaXApIC0gMV0KICAgICAgICAgICAgaXBfdHlwZSA9 - ICgKICAgICAgICAgICAgICAgICJJUHY0IiBpZiB0eXBlKGlwX2FkZHJlc3MoZW5kcG9pbnRfc3Ry - X2lwKSkgaXMgSVB2NEFkZHJlc3MgZWxzZSAiSVB2NiIKICAgICAgICAgICAgKQogICAgICAgIGV4 - Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICBpcF90eXBlID0gIkZRRE4iCiAgICAgICAgaWYg - bm90IHBvcnQuaXNkaWdpdCgpOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj - ZXB0aW9uKGYiUG9ydCBub3QgdmFsaWQ6IHtwb3J0fSIpCiAgICAgICAgaW50UG9ydCA9IGludChw - b3J0KQogICAgICAgIGlmIGludFBvcnQgPCAxIG9yIGludFBvcnQgPiAyKioxNiAtIDE6CiAgICAg - ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oZiJPdXQgb2YgcmFuZ2UgcG9y - dCBudW1iZXI6IHtwb3J0fSIpCgogICAgICAgIHJldHVybiBpcF90eXBlCgogICAgZGVmIGVuZHBv - aW50X2RpYWwoc2VsZiwgZW5kcG9pbnRfc3RyLCBpcF90eXBlLCB0aW1lb3V0PTMsIGNlcnQ9Tm9u - ZSk6CiAgICAgICAgIyBpZiB0aGUgJ2NsdXN0ZXInIGluc3RhbmNlIGlzIGEgZHVtbXkgb25lLAog - ICAgICAgICMgZG9uJ3QgdHJ5IHRvIHJlYWNoIG91dCB0byB0aGUgZW5kcG9pbnQKICAgICAgICBp - ZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlSYWRvcyk6CiAgICAgICAgICAgIHJldHVy - biAiIiwgIiIsICIiCiAgICAgICAgaWYgaXBfdHlwZSA9PSAiSVB2NiI6CiAgICAgICAgICAgIHRy - eToKICAgICAgICAgICAgICAgIGVuZHBvaW50X3N0cl9pcCwgZW5kcG9pbnRfc3RyX3BvcnQgPSBl - bmRwb2ludF9zdHIucnNwbGl0KCI6IiwgMSkKICAgICAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6 - CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg - ICAgICAgICAgICAgIGYiTm90IGEgcHJvcGVyIGVuZHBvaW50OiB7ZW5kcG9pbnRfc3RyfSIKICAg - ICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgZW5kcG9pbnRfc3RyX2lwWzBdICE9ICJbIjoK - ICAgICAgICAgICAgICAgIGVuZHBvaW50X3N0cl9pcCA9ICJbIiArIGVuZHBvaW50X3N0cl9pcCAr - ICJdIgogICAgICAgICAgICBlbmRwb2ludF9zdHIgPSAiOiIuam9pbihbZW5kcG9pbnRfc3RyX2lw - LCBlbmRwb2ludF9zdHJfcG9ydF0pCgogICAgICAgIHByb3RvY29scyA9IFsiaHR0cCIsICJodHRw - cyJdCiAgICAgICAgcmVzcG9uc2VfZXJyb3IgPSBOb25lCiAgICAgICAgZm9yIHByZWZpeCBpbiBw - cm90b2NvbHM6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGVwID0gZiJ7cHJlZml4 - fTovL3tlbmRwb2ludF9zdHJ9IgogICAgICAgICAgICAgICAgdmVyaWZ5ID0gTm9uZQogICAgICAg - ICAgICAgICAgIyBJZiB2ZXJpZnkgaXMgc2V0IHRvIGEgcGF0aCB0byBhIGRpcmVjdG9yeSwKICAg - ICAgICAgICAgICAgICMgdGhlIGRpcmVjdG9yeSBtdXN0IGhhdmUgYmVlbiBwcm9jZXNzZWQgdXNp - bmcgdGhlIGNfcmVoYXNoIHV0aWxpdHkgc3VwcGxpZWQgd2l0aCBPcGVuU1NMLgogICAgICAgICAg - ICAgICAgaWYgcHJlZml4ID09ICJodHRwcyIgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3NraXBf - dGxzOgogICAgICAgICAgICAgICAgICAgIHZlcmlmeSA9IEZhbHNlCiAgICAgICAgICAgICAgICAg - ICAgciA9IHJlcXVlc3RzLmhlYWQoZXAsIHRpbWVvdXQ9dGltZW91dCwgdmVyaWZ5PUZhbHNlKQog - ICAgICAgICAgICAgICAgZWxpZiBwcmVmaXggPT0gImh0dHBzIiBhbmQgY2VydDoKICAgICAgICAg - ICAgICAgICAgICB2ZXJpZnkgPSBjZXJ0CiAgICAgICAgICAgICAgICAgICAgciA9IHJlcXVlc3Rz - LmhlYWQoZXAsIHRpbWVvdXQ9dGltZW91dCwgdmVyaWZ5PWNlcnQpCiAgICAgICAgICAgICAgICBl - bHNlOgogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0cy5oZWFkKGVwLCB0aW1lb3V0PXRp - bWVvdXQpCiAgICAgICAgICAgICAgICBpZiByLnN0YXR1c19jb2RlID09IDIwMDoKICAgICAgICAg - ICAgICAgICAgICByZXR1cm4gcHJlZml4LCB2ZXJpZnksICIiCiAgICAgICAgICAgIGV4Y2VwdCBF - eGNlcHRpb24gYXMgZXJyOgogICAgICAgICAgICAgICAgcmVzcG9uc2VfZXJyb3IgPSBlcnIKICAg - ICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgc3lzLnN0ZGVyci53cml0ZSgKICAgICAgICAg - ICAgZiJ1bmFibGUgdG8gY29ubmVjdCB0byBlbmRwb2ludDoge2VuZHBvaW50X3N0cn0sIGZhaWxl - ZCBlcnJvcjoge3Jlc3BvbnNlX2Vycm9yfSIKICAgICAgICApCiAgICAgICAgcmV0dXJuICgKICAg - ICAgICAgICAgIiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAoIi0xIiksCiAgICAgICAg - KQoKICAgIGRlZiBwYXJzZV9jb25maWdfZmlsZShzZWxmLCBjb25maWdfZmlsZSk6CiAgICAgICAg - Y29uZmlnID0gY29uZmlncGFyc2VyLkNvbmZpZ1BhcnNlcigpCiAgICAgICAgY29uZmlnLnJlYWQo - Y29uZmlnX2ZpbGUpCiAgICAgICAgZm9yIGFyZyBpbiBsaXN0KHZhcnMoc2VsZi5fYXJnX3BhcnNl - cikpOgogICAgICAgICAgICAjIHB5dGhvbiB0cmVhdHMgZmxhZy1uYW1lIGFzIGZsYWdfbmFtZSBp - bnRlcm5hbGx5LCBzbyBjb252ZXJ0aW5nIGJhY2sgdG8gZmxhZy1uYW1lLAogICAgICAgICAgICAj - IHNvIHdlIGNhbiBnZXQgdGhvc2UgdmFsdWVzIGZyb20gY29uZmlnIGZpbGUKICAgICAgICAgICAg - YXJndW1lbnQgPSBhcmcucmVwbGFjZSgiXyIsICItIikKICAgICAgICAgICAgYXJndW1lbnRWYWx1 - ZSA9IHN0cihnZXRhdHRyKHNlbGYuX2FyZ19wYXJzZXIsIGFyZykpCiAgICAgICAgICAgIGNvbmZp - Z192YWx1ZSA9IGNvbmZpZy5nZXQoIkNvbmZpZ3VyYXRpb25zIiwgYXJndW1lbnQsIGZhbGxiYWNr - PU5vbmUpCiAgICAgICAgICAgICMgZ2l2ZSBwcmlvcml0eSB0byBjb21tYW5kIGxpbmUgYXJndW1l - bnQsIGlmIGNvbW1hbmQgbGluZSBhcmd1bWVudCBpcyBub3QgcHJlc2VudCB1c2UgY29uZmlnLmlu - aSB2YWx1ZSwKICAgICAgICAgICAgaWYgKHN0cihzeXMuYXJndikuZmluZChhcmd1bWVudCkgPT0g - LTEpIGFuZCAoCiAgICAgICAgICAgICAgICAoY29uZmlnX3ZhbHVlICE9IE5vbmUpIGFuZCAoY29u - ZmlnX3ZhbHVlICE9ICIiKQogICAgICAgICAgICApOgogICAgICAgICAgICAgICAgc2VsZi5fYXJn - X3BhcnNlci5fX3NldGF0dHJfXyhhcmcsIGNvbmZpZ192YWx1ZSkKCiAgICAgICAgcmV0dXJuIGNv - bmZpZwoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhcmdfbGlzdD1Ob25lKToKICAgICAgICBzZWxm - Lm91dF9tYXAgPSB7fQogICAgICAgIHNlbGYuX2V4Y2x1ZGVkX2tleXMgPSBzZXQoKQogICAgICAg - IHNlbGYuX2FyZ19wYXJzZXIgPSBzZWxmLmdlbl9hcmdfcGFyc2VyKGFyZ3NfdG9fcGFyc2U9YXJn - X2xpc3QpCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jb25maWdfZmlsZToKICAgICAgICAg - ICAgc2VsZi5jb25maWcgPSBzZWxmLnBhcnNlX2NvbmZpZ19maWxlKHNlbGYuX2FyZ19wYXJzZXIu - Y29uZmlnX2ZpbGUpCiAgICAgICAgc2VsZi5fY2hlY2tfY29uZmxpY3Rpbmdfb3B0aW9ucygpCiAg - ICAgICAgc2VsZi5ydW5fYXNfdXNlciA9IHNlbGYuX2FyZ19wYXJzZXIucnVuX2FzX3VzZXIKICAg - ICAgICBzZWxmLm91dHB1dF9maWxlID0gc2VsZi5fYXJnX3BhcnNlci5vdXRwdXQKICAgICAgICBz - ZWxmLmNlcGhfY29uZiA9IHNlbGYuX2FyZ19wYXJzZXIuY2VwaF9jb25mCiAgICAgICAgc2VsZi5j - ZXBoX2tleXJpbmcgPSBzZWxmLl9hcmdfcGFyc2VyLmtleXJpbmcKICAgICAgICAjIGlmIHVzZXIg - bm90IHByb3ZpZGVkLCBnaXZlIGEgZGVmYXVsdCB1c2VyCiAgICAgICAgaWYgbm90IHNlbGYucnVu - X2FzX3VzZXIgYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVwZ3JhZGU6CiAgICAgICAgICAgIHNl - bGYucnVuX2FzX3VzZXIgPSBzZWxmLkVYVEVSTkFMX1VTRVJfTkFNRQogICAgICAgIGlmIG5vdCBz - ZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeCBhbmQgbm90IHNlbGYuX2FyZ19wYXJzZXIu - dXBncmFkZToKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXggPSBz - ZWxmLkRFRkFVTFRfUkdXX1BPT0xfUFJFRklYCiAgICAgICAgaWYgc2VsZi5jZXBoX2NvbmY6CiAg - ICAgICAgICAgIGt3YXJncyA9IHt9CiAgICAgICAgICAgIGlmIHNlbGYuY2VwaF9rZXlyaW5nOgog - ICAgICAgICAgICAgICAga3dhcmdzWyJjb25mIl0gPSB7ImtleXJpbmciOiBzZWxmLmNlcGhfa2V5 - cmluZ30KICAgICAgICAgICAgc2VsZi5jbHVzdGVyID0gcmFkb3MuUmFkb3MoY29uZmZpbGU9c2Vs - Zi5jZXBoX2NvbmYsICoqa3dhcmdzKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYuY2x1 - c3RlciA9IHJhZG9zLlJhZG9zKCkKICAgICAgICAgICAgc2VsZi5jbHVzdGVyLmNvbmZfcmVhZF9m - aWxlKCkKICAgICAgICBzZWxmLmNsdXN0ZXIuY29ubmVjdCgpCgogICAgZGVmIHNodXRkb3duKHNl - bGYpOgogICAgICAgIGlmIHNlbGYuY2x1c3Rlci5zdGF0ZSA9PSAiY29ubmVjdGVkIjoKICAgICAg - ICAgICAgc2VsZi5jbHVzdGVyLnNodXRkb3duKCkKCiAgICBkZWYgZ2V0X2ZzaWQoc2VsZik6CiAg - ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2Vs - Zi5kcnlfcnVuKCJjZXBoIGZzaWQiKQogICAgICAgIHJldHVybiBzdHIoc2VsZi5jbHVzdGVyLmdl - dF9mc2lkKCkpCgogICAgZGVmIF9jb21tb25fY21kX2pzb25fZ2VuKHNlbGYsIGNtZF9qc29uKToK - ICAgICAgICBjbWQgPSBqc29uLmR1bXBzKGNtZF9qc29uLCBzb3J0X2tleXM9VHJ1ZSkKICAgICAg - ICByZXRfdmFsLCBjbWRfb3V0LCBlcnJfbXNnID0gc2VsZi5jbHVzdGVyLm1vbl9jb21tYW5kKGNt - ZCwgYiIiKQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudmVyYm9zZToKICAgICAgICAgICAg - cHJpbnQoZiJDb21tYW5kIElucHV0OiB7Y21kfSIpCiAgICAgICAgICAgIHByaW50KAogICAgICAg - ICAgICAgICAgZiJSZXR1cm4gVmFsOiB7cmV0X3ZhbH1cbkNvbW1hbmQgT3V0cHV0OiB7Y21kX291 - dH1cbiIKICAgICAgICAgICAgICAgIGYiRXJyb3IgTWVzc2FnZToge2Vycl9tc2d9XG4tLS0tLS0t - LS0tXG4iCiAgICAgICAgICAgICkKICAgICAgICBqc29uX291dCA9IHt9CiAgICAgICAgIyBpZiB0 - aGVyZSBpcyBubyBlcnJvciAoaS5lOyByZXRfdmFsIGlzIFpFUk8pIGFuZCAnY21kX291dCcgaXMg - bm90IGVtcHR5CiAgICAgICAgIyB0aGVuIGNvbnZlcnQgJ2NtZF9vdXQnIHRvIGEganNvbiBvdXRw - dXQKICAgICAgICBpZiByZXRfdmFsID09IDAgYW5kIGNtZF9vdXQ6CiAgICAgICAgICAgIGpzb25f - b3V0ID0ganNvbi5sb2FkcyhjbWRfb3V0KQogICAgICAgIHJldHVybiByZXRfdmFsLCBqc29uX291 - dCwgZXJyX21zZwoKICAgIGRlZiBnZXRfY2VwaF9leHRlcm5hbF9tb25fZGF0YShzZWxmKToKICAg - ICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogInF1b3J1bV9zdGF0dXMiLCAiZm9ybWF0IjogImpz - b24ifQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0 - dXJuIHNlbGYuZHJ5X3J1bigiY2VwaCAiICsgY21kX2pzb25bInByZWZpeCJdKQogICAgICAgIHJl - dF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRf - anNvbikKICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAg - ICAgIGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJh - aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiJ3F1b3J1bV9z - dGF0dXMnIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9t - c2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAg - ICAgICkKICAgICAgICBxX2xlYWRlcl9uYW1lID0ganNvbl9vdXRbInF1b3J1bV9sZWFkZXJfbmFt - ZSJdCiAgICAgICAgcV9sZWFkZXJfZGV0YWlscyA9IHt9CiAgICAgICAgcV9sZWFkZXJfbWF0Y2hp - bmdfbGlzdCA9IFsKICAgICAgICAgICAgbCBmb3IgbCBpbiBqc29uX291dFsibW9ubWFwIl1bIm1v - bnMiXSBpZiBsWyJuYW1lIl0gPT0gcV9sZWFkZXJfbmFtZQogICAgICAgIF0KICAgICAgICBpZiBs - ZW4ocV9sZWFkZXJfbWF0Y2hpbmdfbGlzdCkgPT0gMDoKICAgICAgICAgICAgcmFpc2UgRXhlY3V0 - aW9uRmFpbHVyZUV4Y2VwdGlvbigiTm8gbWF0Y2hpbmcgJ21vbicgZGV0YWlscyBmb3VuZCIpCiAg - ICAgICAgcV9sZWFkZXJfZGV0YWlscyA9IHFfbGVhZGVyX21hdGNoaW5nX2xpc3RbMF0KICAgICAg - ICAjIGdldCB0aGUgYWRkcmVzcyB2ZWN0b3Igb2YgdGhlIHF1b3J1bS1sZWFkZXIKICAgICAgICBx - X2xlYWRlcl9hZGRydmVjID0gcV9sZWFkZXJfZGV0YWlscy5nZXQoInB1YmxpY19hZGRycyIsIHt9 - KS5nZXQoImFkZHJ2ZWMiLCBbXSkKICAgICAgICBpcF9hZGRyID0gc3RyKHFfbGVhZGVyX2RldGFp - bHNbInB1YmxpY19hZGRyIl0uc3BsaXQoIi8iKVswXSkKCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh - cnNlci52Ml9wb3J0X2VuYWJsZToKICAgICAgICAgICAgaWYgcV9sZWFkZXJfYWRkcnZlY1swXVsi - dHlwZSJdID09ICJ2MiI6CiAgICAgICAgICAgICAgICBpcF9hZGRyID0gcV9sZWFkZXJfYWRkcnZl - Y1swXVsiYWRkciJdCiAgICAgICAgICAgIGVsaWYgbGVuKHFfbGVhZGVyX2FkZHJ2ZWMpID4gMSBh - bmQgcV9sZWFkZXJfYWRkcnZlY1sxXVsidHlwZSJdID09ICJ2MiI6CiAgICAgICAgICAgICAgICBp - cF9hZGRyID0gcV9sZWFkZXJfYWRkcnZlY1sxXVsiYWRkciJdCiAgICAgICAgICAgIGVsc2U6CiAg - ICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKAogICAgICAgICAgICAgICAgICAgICIndjIn - IGFkZHJlc3MgdHlwZSBub3QgcHJlc2VudCwgYW5kICd2Mi1wb3J0LWVuYWJsZScgZmxhZyBpcyBw - cm92aWRlZCIKICAgICAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIGYie3N0cihxX2xlYWRl - cl9uYW1lKX09e2lwX2FkZHJ9IgoKICAgIGRlZiBfY29udmVydF9ob3N0bmFtZV90b19pcChzZWxm - LCBob3N0X25hbWUsIHBvcnQsIGlwX3R5cGUpOgogICAgICAgICMgaWYgJ2NsdXN0ZXInIGluc3Rh - bmNlIGlzIGEgZHVtbXkgdHlwZSwKICAgICAgICAjIGNhbGwgdGhlIGR1bW15IGluc3RhbmNlJ3Mg - ImNvbnZlcnQiIG1ldGhvZAogICAgICAgIGlmIG5vdCBob3N0X25hbWU6CiAgICAgICAgICAgIHJh - aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oIkVtcHR5IGhvc3RuYW1lIHByb3ZpZGVkIikK - ICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlSYWRvcyk6CiAgICAgICAg - ICAgIHJldHVybiBzZWxmLmNsdXN0ZXIuX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoaG9zdF9uYW1l - KQoKICAgICAgICBpZiBpcF90eXBlID09ICJGUUROIjoKICAgICAgICAgICAgIyBjaGVjayB3aGlj - aCBpcCBGUUROIHNob3VsZCBiZSBjb252ZXJ0ZWQgdG8sIElQdjQgb3IgSVB2NgogICAgICAgICAg - ICAjIGNoZWNrIHRoZSBob3N0IGlwLCB0aGUgZW5kcG9pbnQgaXAgdHlwZSB3b3VsZCBiZSBzaW1p - bGFyIHRvIGhvc3QgaXAKICAgICAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJvcmNoIGhv - c3QgbHMiLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgICAgICByZXRfdmFsLCBqc29uX291dCwg - ZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgICAg - ICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0dGVtcHQsCiAgICAgICAgICAgIGlmIHJl - dF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgICAgICByYWlzZSBF - eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICInb3JjaCBob3N0 - IGxzJyBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgICAgICBmIkVycm9yOiB7ZXJy - X21zZyBpZiByZXRfdmFsICE9IDAgZWxzZSBzZWxmLkVNUFRZX09VVFBVVF9MSVNUfSIKICAgICAg - ICAgICAgICAgICkKICAgICAgICAgICAgaG9zdF9hZGRyID0ganNvbl9vdXRbMF1bImFkZHIiXQog - ICAgICAgICAgICAjIGFkZCA6ODAgc2FtcGxlIHBvcnQgaW4gaXBfdHlwZSwgYXMgX2ludmFsaWRf - ZW5kcG9pbnQgYWxzbyB2ZXJpZnkgcG9ydAogICAgICAgICAgICBob3N0X2lwX3R5cGUgPSBzZWxm - Ll9pbnZhbGlkX2VuZHBvaW50KGhvc3RfYWRkciArICI6ODAiKQogICAgICAgICAgICBpbXBvcnQg - c29ja2V0CgogICAgICAgICAgICBpcCA9IFtdCiAgICAgICAgICAgICMgZXhhbXBsZSBvdXRwdXQg - Wyg8QWRkcmVzc0ZhbWlseS5BRl9JTkVUOiAyPiwgPFNvY2tldEtpbmQuU09DS19TVFJFQU06IDE+ - LCA2LCAnJywgKCc5My4xODQuMjE2LjM0JywgODApKSwgLi4uXQogICAgICAgICAgICAjIHdlIG5l - ZWQgdG8gZ2V0IDkzLjE4NC4yMTYuMzQgc28gaXQgd291bGQgYmUgaXBbMF1bNF1bMF0KICAgICAg - ICAgICAgaWYgaG9zdF9pcF90eXBlID09ICJJUHY2IjoKICAgICAgICAgICAgICAgIGlwID0gc29j - a2V0LmdldGFkZHJpbmZvKAogICAgICAgICAgICAgICAgICAgIGhvc3RfbmFtZSwgcG9ydCwgZmFt - aWx5PXNvY2tldC5BRl9JTkVUNiwgcHJvdG89c29ja2V0LklQUFJPVE9fVENQCiAgICAgICAgICAg - ICAgICApCiAgICAgICAgICAgIGVsaWYgaG9zdF9pcF90eXBlID09ICJJUHY0IjoKICAgICAgICAg - ICAgICAgIGlwID0gc29ja2V0LmdldGFkZHJpbmZvKAogICAgICAgICAgICAgICAgICAgIGhvc3Rf - bmFtZSwgcG9ydCwgZmFtaWx5PXNvY2tldC5BRl9JTkVULCBwcm90bz1zb2NrZXQuSVBQUk9UT19U - Q1AKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgZGVsIHNvY2tldAogICAgICAgICAgICBy - ZXR1cm4gaXBbMF1bNF1bMF0KICAgICAgICByZXR1cm4gaG9zdF9uYW1lCgogICAgZGVmIGdldF9h - Y3RpdmVfYW5kX3N0YW5kYnlfbWdycyhzZWxmKToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2Vy - LmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiAiIiwgc2VsZi5kcnlfcnVuKCJjZXBoIHN0YXR1 - cyIpCiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0ID0gc2VsZi5fYXJnX3BhcnNlci5t - b25pdG9yaW5nX2VuZHBvaW50X3BvcnQKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xp - c3QgPSBzZWxmLl9hcmdfcGFyc2VyLm1vbml0b3JpbmdfZW5kcG9pbnQKICAgICAgICBzdGFuZGJ5 - X21ncnMgPSBbXQogICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3Q6CiAg - ICAgICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAic3RhdHVzIiwgImZvcm1hdCI6ICJqc29u - In0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25f - Y21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3Vj - Y2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgICAgICBpZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25f - b3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv - bigKICAgICAgICAgICAgICAgICAgICAiJ21nciBzZXJ2aWNlcycgY29tbWFuZCBmYWlsZWQuXG4i - CiAgICAgICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVs - c2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAg - IG1vbml0b3JpbmdfZW5kcG9pbnQgPSAoCiAgICAgICAgICAgICAgICBqc29uX291dC5nZXQoIm1n - cm1hcCIsIHt9KS5nZXQoInNlcnZpY2VzIiwge30pLmdldCgicHJvbWV0aGV1cyIsICIiKQogICAg - ICAgICAgICApCiAgICAgICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2VuZHBvaW50OgogICAgICAg + Ii0tbW9uaXRvcmluZy1lbmRwb2ludC1wb3J0IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAg + ICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IkNlcGggTWFuYWdlciBw + cm9tZXRoZXVzIGV4cG9ydGVyIHBvcnQiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAu + YWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1za2lwLW1vbml0b3JpbmctZW5kcG9pbnQiLAog + ICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAgICAgICBhY3Rpb249InN0b3JlX3RydWUi + LAogICAgICAgICAgICBoZWxwPSJEbyBub3QgY2hlY2sgZm9yIGEgbW9uaXRvcmluZyBlbmRwb2lu + dCBmb3IgdGhlIENlcGggY2x1c3RlciIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5h + ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXJiZC1tZXRhZGF0YS1lYy1wb29sLW5hbWUiLAog + ICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAg + ICAgICAgaGVscD0iUHJvdmlkZXMgdGhlIG5hbWUgb2YgZXJhc3VyZSBjb2RlZCBSQkQgbWV0YWRh + dGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAg + ICAgICAgICAgICItLWRyeS1ydW4iLAogICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAg + ICAgICBhY3Rpb249InN0b3JlX3RydWUiLAogICAgICAgICAgICBoZWxwPSJEcnkgcnVuIHByaW50 + cyB0aGUgZXhlY3V0ZWQgY29tbWFuZHMgd2l0aG91dCBydW5uaW5nIHRoZW0iLAogICAgICAgICkK + ICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yYWRvcy1u + YW1lc3BhY2UiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1G + YWxzZSwKICAgICAgICAgICAgaGVscD0iRGl2aWRlcyBhIHBvb2wgaW50byBzZXBhcmF0ZSBsb2dp + Y2FsIG5hbWVzcGFjZXMsIHVzZWQgZm9yIGNyZWF0aW5nIFJCRCBQVkMgaW4gYSBDZXBoQmxvY2tQ + b29sUmFkb3NOYW1lc3BhY2UgKHNob3VsZCBiZSBsb3dlciBjYXNlKSIsCiAgICAgICAgKQogICAg + ICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXN1YnZvbHVtZS1n + cm91cCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNl + LAogICAgICAgICAgICBoZWxwPSJwcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgc3Vidm9sdW1lIGdy + b3VwIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg + ICAgICAgIi0tcmd3LXJlYWxtLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAg + ICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlkZXMgdGhlIG5hbWUg + b2YgdGhlIHJndy1yZWFsbSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJn + dW1lbnQoCiAgICAgICAgICAgICItLXJndy16b25lLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0 + PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlk + ZXMgdGhlIG5hbWUgb2YgdGhlIHJndy16b25lIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dy + b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cC1uYW1lIiwKICAg + ICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAg + ICAgIGhlbHA9InByb3ZpZGVzIHRoZSBuYW1lIG9mIHRoZSByZ3ctem9uZWdyb3VwIiwKICAgICAg + ICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tdG9w + b2xvZ3ktcG9vbHMiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJl + ZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iY29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgdG9wb2xv + Z3ktY29uc3RyYWluZWQgcmJkIHBvb2xzIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3Vw + LmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tdG9wb2xvZ3ktZmFpbHVyZS1kb21haW4tbGFi + ZWwiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwK + ICAgICAgICAgICAgaGVscD0iazhzIGNsdXN0ZXIgZmFpbHVyZSBkb21haW4gbGFiZWwgKGV4YW1w + bGU6IHpvbmUsIHJhY2ssIG9yIGhvc3QpIGZvciB0aGUgdG9wb2xvZ3ktcG9vbHMgdGhhdCBtYXRj + aCB0aGUgY2VwaCBkb21haW4iLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy + Z3VtZW50KAogICAgICAgICAgICAiLS10b3BvbG9neS1mYWlsdXJlLWRvbWFpbi12YWx1ZXMiLAog + ICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAg + ICAgICAgaGVscD0iY29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgdGhlIGs4cyBjbHVzdGVyIGZhaWx1 + cmUgZG9tYWluIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggb2YgdGhlIHBvb2xzIGluIHRo + ZSBgdG9wb2xvZ3ktcG9vbHNgIGxpc3QiLAogICAgICAgICkKCiAgICAgICAgdXBncmFkZV9ncm91 + cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJ1cGdyYWRlIikKICAgICAgICB1cGdyYWRlX2dy + b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tdXBncmFkZSIsCiAgICAgICAgICAgIGFj + dGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAg + IGhlbHA9IlVwZ3JhZGVzIHRoZSBjZXBoQ1NJS2V5cmluZ3MoRm9yIGV4YW1wbGU6IGNsaWVudC5j + c2ktY2VwaGZzLXByb3Zpc2lvbmVyKSBhbmQgY2xpZW50LmhlYWx0aGNoZWNrZXIgY2VwaCB1c2Vy + cyB3aXRoIG5ldyBwZXJtaXNzaW9ucyBuZWVkZWQgZm9yIHRoZSBuZXcgY2x1c3RlciB2ZXJzaW9u + IGFuZCBvbGRlciBwZXJtaXNzaW9uIHdpbGwgc3RpbGwgYmUgYXBwbGllZC4iCiAgICAgICAgICAg + ICsgIlNhbXBsZSBydW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rl + ci1yZXNvdXJjZXMucHkgLS11cGdyYWRlYCwgdGhpcyB3aWxsIHVwZ3JhZGUgYWxsIHRoZSBkZWZh + dWx0IGNzaSB1c2Vycyhub24tcmVzdHJpY3RlZCkiCiAgICAgICAgICAgICsgIkZvciByZXN0cmlj + dGVkIHVzZXJzKEZvciBleGFtcGxlOiBjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lci1vcGVu + c2hpZnQtc3RvcmFnZS1teWZzKSwgdXNlcnMgY3JlYXRlZCB1c2luZyAtLXJlc3RyaWN0ZWQtYXV0 + aC1wZXJtaXNzaW9uIGZsYWcgbmVlZCB0byBwYXNzIG1hbmRhdG9yeSBmbGFncyIKICAgICAgICAg + ICAgKyAibWFuZGF0b3J5IGZsYWdzOiAnLS1yYmQtZGF0YS1wb29sLW5hbWUsIC0tazhzLWNsdXN0 + ZXItbmFtZSBhbmQgLS1ydW4tYXMtdXNlcicgZmxhZ3Mgd2hpbGUgdXBncmFkaW5nIgogICAgICAg + ICAgICArICJpbiBjYXNlIG9mIGNlcGhmcyB1c2VycyBpZiB5b3UgaGF2ZSBwYXNzZWQgLS1jZXBo + ZnMtZmlsZXN5c3RlbS1uYW1lIGZsYWcgd2hpbGUgY3JlYXRpbmcgdXNlciB0aGVuIHdoaWxlIHVw + Z3JhZGluZyBpdCB3aWxsIGJlIG1hbmRhdG9yeSB0b28iCiAgICAgICAgICAgICsgIlNhbXBsZSBy + dW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rlci1yZXNvdXJjZXMu + cHkgLS11cGdyYWRlIC0tcmJkLWRhdGEtcG9vbC1uYW1lIHJlcGxpY2Fwb29sIC0tazhzLWNsdXN0 + ZXItbmFtZSByb29rc3RvcmFnZSAgLS1ydW4tYXMtdXNlciBjbGllbnQuY3NpLXJiZC1ub2RlLXJv + b2tzdG9yYWdlLXJlcGxpY2Fwb29sYCIKICAgICAgICAgICAgKyAiUFM6IEFuIGV4aXN0aW5nIG5v + bi1yZXN0cmljdGVkIHVzZXIgY2Fubm90IGJlIGNvbnZlcnRlZCB0byBhIHJlc3RyaWN0ZWQgdXNl + ciBieSB1cGdyYWRpbmcuIgogICAgICAgICAgICArICJVcGdyYWRlIGZsYWcgc2hvdWxkIG9ubHkg + YmUgdXNlZCB0byBhcHBlbmQgbmV3IHBlcm1pc3Npb25zIHRvIHVzZXJzLCBpdCBzaG91bGRuJ3Qg + YmUgdXNlZCBmb3IgY2hhbmdpbmcgdXNlciBhbHJlYWR5IGFwcGxpZWQgcGVybWlzc2lvbiwgZm9y + IGV4YW1wbGUgeW91IHNob3VsZG4ndCBjaGFuZ2UgaW4gd2hpY2ggcG9vbCB1c2VyIGhhcyBhY2Nl + c3MiLAogICAgICAgICkKCiAgICAgICAgIyBBZGQgY29tbWFuZC1saW5lIGFyZ3VtZW50cwogICAg + ICAgIGNvbmZpZ19ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJjb25maWciKQogICAg + ICAgIGNvbmZpZ19ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNvbmZpZy1maWxl + IiwKICAgICAgICAgICAgdHlwZT1zdHIsCiAgICAgICAgICAgIGhlbHA9IlBhdGggdG8gdGhlIGNv + bmZpZ3VyYXRpb24gZmlsZSwgUHJpb3JpdHk6IGNvbW1hbmQtbGluZS1hcmdzID4gY29uZmlnLmlu + aSBmaWxlIHZhbHVlcyA+IGRlZmF1bHQgdmFsdWVzIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFs + c2UsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgKQoKICAgICAgICBpZiBhcmdzX3Rv + X3BhcnNlOgogICAgICAgICAgICBhc3NlcnQgKAogICAgICAgICAgICAgICAgdHlwZShhcmdzX3Rv + X3BhcnNlKSA9PSBsaXN0CiAgICAgICAgICAgICksICJBcmd1bWVudCB0byAnZ2VuX2FyZ19wYXJz + ZXInIHNob3VsZCBiZSBhIGxpc3QiCiAgICAgICAgZWxzZToKICAgICAgICAgICAgYXJnc190b19w + YXJzZSA9IHN5cy5hcmd2WzE6XQogICAgICAgIHJldHVybiBhcmdQLnBhcnNlX2FyZ3MoYXJnc190 + b19wYXJzZSkKCiAgICBkZWYgdmFsaWRhdGVfcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZShzZWxm + KToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJiZF9tZXRhZGF0YV9lY19wb29sX25hbWU6 + CiAgICAgICAgICAgIHJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFyc2Vy + LnJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUKICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNl + bGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCgogICAgICAgICAgICBpZiByYmRfcG9v + bF9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2Vw + dGlvbigKICAgICAgICAgICAgICAgICAgICAiRmxhZyAnLS1yYmQtZGF0YS1wb29sLW5hbWUnIHNo + b3VsZCBub3QgYmUgZW1wdHkiCiAgICAgICAgICAgICAgICApCgogICAgICAgICAgICBpZiByYmRf + bWV0YWRhdGFfZWNfcG9vbF9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0 + aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiRmxhZyAnLS1yYmQtbWV0 + YWRhdGEtZWMtcG9vbC1uYW1lJyBzaG91bGQgbm90IGJlIGVtcHR5IgogICAgICAgICAgICAgICAg + KQoKICAgICAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJvc2QgZHVtcCIsICJmb3JtYXQi + OiAianNvbiJ9CiAgICAgICAgICAgIHJldF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5f + Y29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICAgICAgaWYgcmV0X3ZhbCAhPSAw + IG9yIGxlbihqc29uX291dCkgPT0gMDoKICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgZiJ7Y21kX2pzb25bJ3ByZWZpeCdd + fSBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgICAgICBmIkVycm9yOiB7ZXJyX21z + ZyBpZiByZXRfdmFsICE9IDAgZWxzZSBzZWxmLkVNUFRZX09VVFBVVF9MSVNUfSIKICAgICAgICAg + ICAgICAgICkKICAgICAgICAgICAgbWV0YWRhdGFfcG9vbF9leGlzdCwgcG9vbF9leGlzdCA9IEZh + bHNlLCBGYWxzZQoKICAgICAgICAgICAgZm9yIGtleSBpbiBqc29uX291dFsicG9vbHMiXToKICAg + ICAgICAgICAgICAgICMgaWYgZXJhc3VyZV9jb2RlX3Byb2ZpbGUgaXMgZW1wdHkgYW5kIHBvb2wg + bmFtZSBleGlzdHMgdGhlbiBpdCByZXBsaWNhIHBvb2wKICAgICAgICAgICAgICAgIGlmICgKICAg + ICAgICAgICAgICAgICAgICBrZXlbImVyYXN1cmVfY29kZV9wcm9maWxlIl0gPT0gIiIKICAgICAg + ICAgICAgICAgICAgICBhbmQga2V5WyJwb29sX25hbWUiXSA9PSByYmRfbWV0YWRhdGFfZWNfcG9v + bF9uYW1lCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhX3Bv + b2xfZXhpc3QgPSBUcnVlCiAgICAgICAgICAgICAgICAjIGlmIGVyYXN1cmVfY29kZV9wcm9maWxl + IGlzIG5vdCBlbXB0eSBhbmQgcG9vbCBuYW1lIGV4aXN0cyB0aGVuIGl0IGlzIGVjIHBvb2wKICAg + ICAgICAgICAgICAgIGlmIGtleVsiZXJhc3VyZV9jb2RlX3Byb2ZpbGUiXSBhbmQga2V5WyJwb29s + X25hbWUiXSA9PSByYmRfcG9vbF9uYW1lOgogICAgICAgICAgICAgICAgICAgIHBvb2xfZXhpc3Qg + PSBUcnVlCgogICAgICAgICAgICBpZiBub3QgbWV0YWRhdGFfcG9vbF9leGlzdDoKICAgICAgICAg + ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAg + ICAgIlByb3ZpZGVkIHJiZF9lY19tZXRhZGF0YV9wb29sIG5hbWUsIgogICAgICAgICAgICAgICAg + ICAgIGYiIHtyYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lfSwgZG9lcyBub3QgZXhpc3QiCiAgICAg + ICAgICAgICAgICApCiAgICAgICAgICAgIGlmIG5vdCBwb29sX2V4aXN0OgogICAgICAgICAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBm + IlByb3ZpZGVkIHJiZF9kYXRhX3Bvb2wgbmFtZSwge3JiZF9wb29sX25hbWV9LCBkb2VzIG5vdCBl + eGlzdCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgcmV0dXJuIHJiZF9tZXRhZGF0YV9l + Y19wb29sX25hbWUKCiAgICBkZWYgZHJ5X3J1bihzZWxmLCBtc2cpOgogICAgICAgIGlmIHNlbGYu + X2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcHJpbnQoIkV4ZWN1dGU6ICIgKyAiJyIg + KyBtc2cgKyAiJyIpCgogICAgZGVmIHZhbGlkYXRlX3Jnd19lbmRwb2ludF90bHNfY2VydChzZWxm + KToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2VydF9wYXRoOgogICAgICAg + ICAgICB3aXRoIG9wZW4oc2VsZi5fYXJnX3BhcnNlci5yZ3dfdGxzX2NlcnRfcGF0aCwgZW5jb2Rp + bmc9InV0ZjgiKSBhcyBmOgogICAgICAgICAgICAgICAgY29udGVudHMgPSBmLnJlYWQoKQogICAg + ICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnRzLnJzdHJpcCgpCgogICAgZGVmIF9jaGVja19jb25m + bGljdGluZ19vcHRpb25zKHNlbGYpOgogICAgICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVw + Z3JhZGUgYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZToKICAgICAg + ICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJF + aXRoZXIgJy0tdXBncmFkZScgb3IgJy0tcmJkLWRhdGEtcG9vbC1uYW1lIDxwb29sX25hbWU+JyBz + aG91bGQgYmUgc3BlY2lmaWVkIgogICAgICAgICAgICApCgogICAgZGVmIF9pbnZhbGlkX2VuZHBv + aW50KHNlbGYsIGVuZHBvaW50X3N0cik6CiAgICAgICAgIyBleHRyYWN0IHRoZSBwb3J0IGJ5IGdl + dHRpbmcgdGhlIGxhc3Qgc3BsaXQgb24gYDpgIGRlbGltaXRlcgogICAgICAgIHRyeToKICAgICAg + ICAgICAgZW5kcG9pbnRfc3RyX2lwLCBwb3J0ID0gZW5kcG9pbnRfc3RyLnJzcGxpdCgiOiIsIDEp + CiAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24oZiJOb3QgYSBwcm9wZXIgZW5kcG9pbnQ6IHtlbmRwb2ludF9zdHJ9IikK + CiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBlbmRwb2ludF9zdHJfaXBbMF0gPT0gIlsiOgog + ICAgICAgICAgICAgICAgZW5kcG9pbnRfc3RyX2lwID0gZW5kcG9pbnRfc3RyX2lwWzEgOiBsZW4o + ZW5kcG9pbnRfc3RyX2lwKSAtIDFdCiAgICAgICAgICAgIGlwX3R5cGUgPSAoCiAgICAgICAgICAg + ICAgICAiSVB2NCIgaWYgdHlwZShpcF9hZGRyZXNzKGVuZHBvaW50X3N0cl9pcCkpIGlzIElQdjRB + ZGRyZXNzIGVsc2UgIklQdjYiCiAgICAgICAgICAgICkKICAgICAgICBleGNlcHQgVmFsdWVFcnJv + cjoKICAgICAgICAgICAgaXBfdHlwZSA9ICJGUUROIgogICAgICAgIGlmIG5vdCBwb3J0LmlzZGln + aXQoKToKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbihmIlBvcnQg + bm90IHZhbGlkOiB7cG9ydH0iKQogICAgICAgIGludFBvcnQgPSBpbnQocG9ydCkKICAgICAgICBp + ZiBpbnRQb3J0IDwgMSBvciBpbnRQb3J0ID4gMioqMTYgLSAxOgogICAgICAgICAgICByYWlzZSBF + eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKGYiT3V0IG9mIHJhbmdlIHBvcnQgbnVtYmVyOiB7cG9y + dH0iKQoKICAgICAgICByZXR1cm4gaXBfdHlwZQoKICAgIGRlZiBlbmRwb2ludF9kaWFsKHNlbGYs + IGVuZHBvaW50X3N0ciwgaXBfdHlwZSwgdGltZW91dD0zLCBjZXJ0PU5vbmUpOgogICAgICAgICMg + aWYgdGhlICdjbHVzdGVyJyBpbnN0YW5jZSBpcyBhIGR1bW15IG9uZSwKICAgICAgICAjIGRvbid0 + IHRyeSB0byByZWFjaCBvdXQgdG8gdGhlIGVuZHBvaW50CiAgICAgICAgaWYgaXNpbnN0YW5jZShz + ZWxmLmNsdXN0ZXIsIER1bW15UmFkb3MpOgogICAgICAgICAgICByZXR1cm4gIiIsICIiLCAiIgog + ICAgICAgIGlmIGlwX3R5cGUgPT0gIklQdjYiOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAg + ICAgICBlbmRwb2ludF9zdHJfaXAsIGVuZHBvaW50X3N0cl9wb3J0ID0gZW5kcG9pbnRfc3RyLnJz + cGxpdCgiOiIsIDEpCiAgICAgICAgICAgIGV4Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBm + Ik5vdCBhIHByb3BlciBlbmRwb2ludDoge2VuZHBvaW50X3N0cn0iCiAgICAgICAgICAgICAgICAp + CiAgICAgICAgICAgIGlmIGVuZHBvaW50X3N0cl9pcFswXSAhPSAiWyI6CiAgICAgICAgICAgICAg + ICBlbmRwb2ludF9zdHJfaXAgPSAiWyIgKyBlbmRwb2ludF9zdHJfaXAgKyAiXSIKICAgICAgICAg + ICAgZW5kcG9pbnRfc3RyID0gIjoiLmpvaW4oW2VuZHBvaW50X3N0cl9pcCwgZW5kcG9pbnRfc3Ry + X3BvcnRdKQoKICAgICAgICBwcm90b2NvbHMgPSBbImh0dHAiLCAiaHR0cHMiXQogICAgICAgIHJl + c3BvbnNlX2Vycm9yID0gTm9uZQogICAgICAgIGZvciBwcmVmaXggaW4gcHJvdG9jb2xzOgogICAg + ICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBlcCA9IGYie3ByZWZpeH06Ly97ZW5kcG9pbnRf + c3RyfSIKICAgICAgICAgICAgICAgIHZlcmlmeSA9IE5vbmUKICAgICAgICAgICAgICAgICMgSWYg + dmVyaWZ5IGlzIHNldCB0byBhIHBhdGggdG8gYSBkaXJlY3RvcnksCiAgICAgICAgICAgICAgICAj + IHRoZSBkaXJlY3RvcnkgbXVzdCBoYXZlIGJlZW4gcHJvY2Vzc2VkIHVzaW5nIHRoZSBjX3JlaGFz + aCB1dGlsaXR5IHN1cHBsaWVkIHdpdGggT3BlblNTTC4KICAgICAgICAgICAgICAgIGlmIHByZWZp + eCA9PSAiaHR0cHMiIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnJnd19za2lwX3RsczoKICAgICAgICAg + ICAgICAgICAgICB2ZXJpZnkgPSBGYWxzZQogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0 + cy5oZWFkKGVwLCB0aW1lb3V0PXRpbWVvdXQsIHZlcmlmeT1GYWxzZSkKICAgICAgICAgICAgICAg + IGVsaWYgcHJlZml4ID09ICJodHRwcyIgYW5kIGNlcnQ6CiAgICAgICAgICAgICAgICAgICAgdmVy + aWZ5ID0gY2VydAogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0cy5oZWFkKGVwLCB0aW1l + b3V0PXRpbWVvdXQsIHZlcmlmeT1jZXJ0KQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAg + ICAgICAgICAgICByID0gcmVxdWVzdHMuaGVhZChlcCwgdGltZW91dD10aW1lb3V0KQogICAgICAg + ICAgICAgICAgaWYgci5zdGF0dXNfY29kZSA9PSAyMDA6CiAgICAgICAgICAgICAgICAgICAgcmV0 + dXJuIHByZWZpeCwgdmVyaWZ5LCAiIgogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGVy + cjoKICAgICAgICAgICAgICAgIHJlc3BvbnNlX2Vycm9yID0gZXJyCiAgICAgICAgICAgICAgICBj + b250aW51ZQogICAgICAgIHN5cy5zdGRlcnIud3JpdGUoCiAgICAgICAgICAgIGYidW5hYmxlIHRv + IGNvbm5lY3QgdG8gZW5kcG9pbnQ6IHtlbmRwb2ludF9zdHJ9LCBmYWlsZWQgZXJyb3I6IHtyZXNw + b25zZV9lcnJvcn0iCiAgICAgICAgKQogICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICIiLAog + ICAgICAgICAgICAiIiwKICAgICAgICAgICAgKCItMSIpLAogICAgICAgICkKCiAgICBkZWYgcGFy + c2VfY29uZmlnX2ZpbGUoc2VsZiwgY29uZmlnX2ZpbGUpOgogICAgICAgIGNvbmZpZyA9IGNvbmZp + Z3BhcnNlci5Db25maWdQYXJzZXIoKQogICAgICAgIGNvbmZpZy5yZWFkKGNvbmZpZ19maWxlKQog + ICAgICAgIGZvciBhcmcgaW4gbGlzdCh2YXJzKHNlbGYuX2FyZ19wYXJzZXIpKToKICAgICAgICAg + ICAgIyBweXRob24gdHJlYXRzIGZsYWctbmFtZSBhcyBmbGFnX25hbWUgaW50ZXJuYWxseSwgc28g + Y29udmVydGluZyBiYWNrIHRvIGZsYWctbmFtZSwKICAgICAgICAgICAgIyBzbyB3ZSBjYW4gZ2V0 + IHRob3NlIHZhbHVlcyBmcm9tIGNvbmZpZyBmaWxlCiAgICAgICAgICAgIGFyZ3VtZW50ID0gYXJn + LnJlcGxhY2UoIl8iLCAiLSIpCiAgICAgICAgICAgIGFyZ3VtZW50VmFsdWUgPSBzdHIoZ2V0YXR0 + cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpKQogICAgICAgICAgICBjb25maWdfdmFsdWUgPSBjb25m + aWcuZ2V0KCJDb25maWd1cmF0aW9ucyIsIGFyZ3VtZW50LCBmYWxsYmFjaz1Ob25lKQogICAgICAg + ICAgICAjIGdpdmUgcHJpb3JpdHkgdG8gY29tbWFuZCBsaW5lIGFyZ3VtZW50LCBpZiBjb21tYW5k + IGxpbmUgYXJndW1lbnQgaXMgbm90IHByZXNlbnQgdXNlIGNvbmZpZy5pbmkgdmFsdWUsCiAgICAg + ICAgICAgIGlmIChzdHIoc3lzLmFyZ3YpLmZpbmQoYXJndW1lbnQpID09IC0xKSBhbmQgKAogICAg + ICAgICAgICAgICAgKGNvbmZpZ192YWx1ZSAhPSBOb25lKSBhbmQgKGNvbmZpZ192YWx1ZSAhPSAi + IikKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuX19zZXRh + dHRyX18oYXJnLCBjb25maWdfdmFsdWUpCgogICAgICAgIHJldHVybiBjb25maWcKCiAgICBkZWYg + X19pbml0X18oc2VsZiwgYXJnX2xpc3Q9Tm9uZSk6CiAgICAgICAgc2VsZi5vdXRfbWFwID0ge30K + ICAgICAgICBzZWxmLl9leGNsdWRlZF9rZXlzID0gc2V0KCkKICAgICAgICBzZWxmLl9hcmdfcGFy + c2VyID0gc2VsZi5nZW5fYXJnX3BhcnNlcihhcmdzX3RvX3BhcnNlPWFyZ19saXN0KQogICAgICAg + IGlmIHNlbGYuX2FyZ19wYXJzZXIuY29uZmlnX2ZpbGU6CiAgICAgICAgICAgIHNlbGYuY29uZmln + ID0gc2VsZi5wYXJzZV9jb25maWdfZmlsZShzZWxmLl9hcmdfcGFyc2VyLmNvbmZpZ19maWxlKQog + ICAgICAgIHNlbGYuX2NoZWNrX2NvbmZsaWN0aW5nX29wdGlvbnMoKQogICAgICAgIHNlbGYucnVu + X2FzX3VzZXIgPSBzZWxmLl9hcmdfcGFyc2VyLnJ1bl9hc191c2VyCiAgICAgICAgc2VsZi5vdXRw + dXRfZmlsZSA9IHNlbGYuX2FyZ19wYXJzZXIub3V0cHV0CiAgICAgICAgc2VsZi5jZXBoX2NvbmYg + PSBzZWxmLl9hcmdfcGFyc2VyLmNlcGhfY29uZgogICAgICAgIHNlbGYuY2VwaF9rZXlyaW5nID0g + c2VsZi5fYXJnX3BhcnNlci5rZXlyaW5nCiAgICAgICAgIyBpZiB1c2VyIG5vdCBwcm92aWRlZCwg + Z2l2ZSBhIGRlZmF1bHQgdXNlcgogICAgICAgIGlmIG5vdCBzZWxmLnJ1bl9hc191c2VyIGFuZCBu + b3Qgc2VsZi5fYXJnX3BhcnNlci51cGdyYWRlOgogICAgICAgICAgICBzZWxmLnJ1bl9hc191c2Vy + ID0gc2VsZi5FWFRFUk5BTF9VU0VSX05BTUUKICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNl + ci5yZ3dfcG9vbF9wcmVmaXggYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVwZ3JhZGU6CiAgICAg + ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4ID0gc2VsZi5ERUZBVUxUX1JH + V19QT09MX1BSRUZJWAogICAgICAgIGlmIHNlbGYuY2VwaF9jb25mOgogICAgICAgICAgICBrd2Fy + Z3MgPSB7fQogICAgICAgICAgICBpZiBzZWxmLmNlcGhfa2V5cmluZzoKICAgICAgICAgICAgICAg + IGt3YXJnc1siY29uZiJdID0geyJrZXlyaW5nIjogc2VsZi5jZXBoX2tleXJpbmd9CiAgICAgICAg + ICAgIHNlbGYuY2x1c3RlciA9IHJhZG9zLlJhZG9zKGNvbmZmaWxlPXNlbGYuY2VwaF9jb25mLCAq + Kmt3YXJncykKICAgICAgICBlbHNlOgogICAgICAgICAgICBzZWxmLmNsdXN0ZXIgPSByYWRvcy5S + YWRvcygpCiAgICAgICAgICAgIHNlbGYuY2x1c3Rlci5jb25mX3JlYWRfZmlsZSgpCiAgICAgICAg + c2VsZi5jbHVzdGVyLmNvbm5lY3QoKQoKICAgIGRlZiBzaHV0ZG93bihzZWxmKToKICAgICAgICBp + ZiBzZWxmLmNsdXN0ZXIuc3RhdGUgPT0gImNvbm5lY3RlZCI6CiAgICAgICAgICAgIHNlbGYuY2x1 + c3Rlci5zaHV0ZG93bigpCgogICAgZGVmIGdldF9mc2lkKHNlbGYpOgogICAgICAgIGlmIHNlbGYu + X2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigiY2Vw + aCBmc2lkIikKICAgICAgICByZXR1cm4gc3RyKHNlbGYuY2x1c3Rlci5nZXRfZnNpZCgpKQoKICAg + IGRlZiBfY29tbW9uX2NtZF9qc29uX2dlbihzZWxmLCBjbWRfanNvbik6CiAgICAgICAgY21kID0g + anNvbi5kdW1wcyhjbWRfanNvbiwgc29ydF9rZXlzPVRydWUpCiAgICAgICAgcmV0X3ZhbCwgY21k + X291dCwgZXJyX21zZyA9IHNlbGYuY2x1c3Rlci5tb25fY29tbWFuZChjbWQsIGIiIikKICAgICAg + ICBpZiBzZWxmLl9hcmdfcGFyc2VyLnZlcmJvc2U6CiAgICAgICAgICAgIHByaW50KGYiQ29tbWFu + ZCBJbnB1dDoge2NtZH0iKQogICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgIGYiUmV0 + dXJuIFZhbDoge3JldF92YWx9XG5Db21tYW5kIE91dHB1dDoge2NtZF9vdXR9XG4iCiAgICAgICAg + ICAgICAgICBmIkVycm9yIE1lc3NhZ2U6IHtlcnJfbXNnfVxuLS0tLS0tLS0tLVxuIgogICAgICAg + ICAgICApCiAgICAgICAganNvbl9vdXQgPSB7fQogICAgICAgICMgaWYgdGhlcmUgaXMgbm8gZXJy + b3IgKGkuZTsgcmV0X3ZhbCBpcyBaRVJPKSBhbmQgJ2NtZF9vdXQnIGlzIG5vdCBlbXB0eQogICAg + ICAgICMgdGhlbiBjb252ZXJ0ICdjbWRfb3V0JyB0byBhIGpzb24gb3V0cHV0CiAgICAgICAgaWYg + cmV0X3ZhbCA9PSAwIGFuZCBjbWRfb3V0OgogICAgICAgICAgICBqc29uX291dCA9IGpzb24ubG9h + ZHMoY21kX291dCkKICAgICAgICByZXR1cm4gcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cKCiAg + ICBkZWYgZ2V0X2NlcGhfZXh0ZXJuYWxfbW9uX2RhdGEoc2VsZik6CiAgICAgICAgY21kX2pzb24g + PSB7InByZWZpeCI6ICJxdW9ydW1fc3RhdHVzIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICBp + ZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiBzZWxmLmRyeV9y + dW4oImNlcGggIiArIGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRfdmFsLCBqc29uX291 + dCwgZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAg + IyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwKICAgICAgICBpZiByZXRfdmFs + ICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25G + YWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIidxdW9ydW1fc3RhdHVzJyBjb21tYW5k + IGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgIGYiRXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwg + IT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJU1R9IgogICAgICAgICAgICApCiAgICAgICAg + cV9sZWFkZXJfbmFtZSA9IGpzb25fb3V0WyJxdW9ydW1fbGVhZGVyX25hbWUiXQogICAgICAgIHFf + bGVhZGVyX2RldGFpbHMgPSB7fQogICAgICAgIHFfbGVhZGVyX21hdGNoaW5nX2xpc3QgPSBbCiAg + ICAgICAgICAgIGwgZm9yIGwgaW4ganNvbl9vdXRbIm1vbm1hcCJdWyJtb25zIl0gaWYgbFsibmFt + ZSJdID09IHFfbGVhZGVyX25hbWUKICAgICAgICBdCiAgICAgICAgaWYgbGVuKHFfbGVhZGVyX21h + dGNoaW5nX2xpc3QpID09IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl + cHRpb24oIk5vIG1hdGNoaW5nICdtb24nIGRldGFpbHMgZm91bmQiKQogICAgICAgIHFfbGVhZGVy + X2RldGFpbHMgPSBxX2xlYWRlcl9tYXRjaGluZ19saXN0WzBdCiAgICAgICAgIyBnZXQgdGhlIGFk + ZHJlc3MgdmVjdG9yIG9mIHRoZSBxdW9ydW0tbGVhZGVyCiAgICAgICAgcV9sZWFkZXJfYWRkcnZl + YyA9IHFfbGVhZGVyX2RldGFpbHMuZ2V0KCJwdWJsaWNfYWRkcnMiLCB7fSkuZ2V0KCJhZGRydmVj + IiwgW10pCiAgICAgICAgaXBfYWRkciA9IHN0cihxX2xlYWRlcl9kZXRhaWxzWyJwdWJsaWNfYWRk + ciJdLnNwbGl0KCIvIilbMF0pCgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudjJfcG9ydF9l + bmFibGU6CiAgICAgICAgICAgIGlmIHFfbGVhZGVyX2FkZHJ2ZWNbMF1bInR5cGUiXSA9PSAidjIi + OgogICAgICAgICAgICAgICAgaXBfYWRkciA9IHFfbGVhZGVyX2FkZHJ2ZWNbMF1bImFkZHIiXQog + ICAgICAgICAgICBlbGlmIGxlbihxX2xlYWRlcl9hZGRydmVjKSA+IDEgYW5kIHFfbGVhZGVyX2Fk + ZHJ2ZWNbMV1bInR5cGUiXSA9PSAidjIiOgogICAgICAgICAgICAgICAgaXBfYWRkciA9IHFfbGVh + ZGVyX2FkZHJ2ZWNbMV1bImFkZHIiXQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAg + c3lzLnN0ZGVyci53cml0ZSgKICAgICAgICAgICAgICAgICAgICAiJ3YyJyBhZGRyZXNzIHR5cGUg + bm90IHByZXNlbnQsIGFuZCAndjItcG9ydC1lbmFibGUnIGZsYWcgaXMgcHJvdmlkZWQiCiAgICAg + ICAgICAgICAgICApCgogICAgICAgIHJldHVybiBmIntzdHIocV9sZWFkZXJfbmFtZSl9PXtpcF9h + ZGRyfSIKCiAgICBkZWYgX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoc2VsZiwgaG9zdF9uYW1lLCBw + b3J0LCBpcF90eXBlKToKICAgICAgICAjIGlmICdjbHVzdGVyJyBpbnN0YW5jZSBpcyBhIGR1bW15 + IHR5cGUsCiAgICAgICAgIyBjYWxsIHRoZSBkdW1teSBpbnN0YW5jZSdzICJjb252ZXJ0IiBtZXRo + b2QKICAgICAgICBpZiBub3QgaG9zdF9uYW1lOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25G + YWlsdXJlRXhjZXB0aW9uKCJFbXB0eSBob3N0bmFtZSBwcm92aWRlZCIpCiAgICAgICAgaWYgaXNp + bnN0YW5jZShzZWxmLmNsdXN0ZXIsIER1bW15UmFkb3MpOgogICAgICAgICAgICByZXR1cm4gc2Vs + Zi5jbHVzdGVyLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKGhvc3RfbmFtZSkKCiAgICAgICAgaWYg + aXBfdHlwZSA9PSAiRlFETiI6CiAgICAgICAgICAgICMgY2hlY2sgd2hpY2ggaXAgRlFETiBzaG91 + bGQgYmUgY29udmVydGVkIHRvLCBJUHY0IG9yIElQdjYKICAgICAgICAgICAgIyBjaGVjayB0aGUg + aG9zdCBpcCwgdGhlIGVuZHBvaW50IGlwIHR5cGUgd291bGQgYmUgc2ltaWxhciB0byBob3N0IGlw + CiAgICAgICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAib3JjaCBob3N0IGxzIiwgImZvcm1h + dCI6ICJqc29uIn0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxm + Ll9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICAjIGlmIHRoZXJlIGlz + IGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgICAgICBpZiByZXRfdmFsICE9IDAgb3Ig + bGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVy + ZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiJ29yY2ggaG9zdCBscycgY29tbWFuZCBm + YWlsZWQuXG4iCiAgICAgICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3Zh + bCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICAgICApCiAg + ICAgICAgICAgIGhvc3RfYWRkciA9IGpzb25fb3V0WzBdWyJhZGRyIl0KICAgICAgICAgICAgIyBh + ZGQgOjgwIHNhbXBsZSBwb3J0IGluIGlwX3R5cGUsIGFzIF9pbnZhbGlkX2VuZHBvaW50IGFsc28g + dmVyaWZ5IHBvcnQKICAgICAgICAgICAgaG9zdF9pcF90eXBlID0gc2VsZi5faW52YWxpZF9lbmRw + b2ludChob3N0X2FkZHIgKyAiOjgwIikKICAgICAgICAgICAgaW1wb3J0IHNvY2tldAoKICAgICAg + ICAgICAgaXAgPSBbXQogICAgICAgICAgICAjIGV4YW1wbGUgb3V0cHV0IFsoPEFkZHJlc3NGYW1p + bHkuQUZfSU5FVDogMj4sIDxTb2NrZXRLaW5kLlNPQ0tfU1RSRUFNOiAxPiwgNiwgJycsICgnOTMu + MTg0LjIxNi4zNCcsIDgwKSksIC4uLl0KICAgICAgICAgICAgIyB3ZSBuZWVkIHRvIGdldCA5My4x + ODQuMjE2LjM0IHNvIGl0IHdvdWxkIGJlIGlwWzBdWzRdWzBdCiAgICAgICAgICAgIGlmIGhvc3Rf + aXBfdHlwZSA9PSAiSVB2NiI6CiAgICAgICAgICAgICAgICBpcCA9IHNvY2tldC5nZXRhZGRyaW5m + bygKICAgICAgICAgICAgICAgICAgICBob3N0X25hbWUsIHBvcnQsIGZhbWlseT1zb2NrZXQuQUZf + SU5FVDYsIHByb3RvPXNvY2tldC5JUFBST1RPX1RDUAogICAgICAgICAgICAgICAgKQogICAgICAg + ICAgICBlbGlmIGhvc3RfaXBfdHlwZSA9PSAiSVB2NCI6CiAgICAgICAgICAgICAgICBpcCA9IHNv + Y2tldC5nZXRhZGRyaW5mbygKICAgICAgICAgICAgICAgICAgICBob3N0X25hbWUsIHBvcnQsIGZh + bWlseT1zb2NrZXQuQUZfSU5FVCwgcHJvdG89c29ja2V0LklQUFJPVE9fVENQCiAgICAgICAgICAg + ICAgICApCiAgICAgICAgICAgIGRlbCBzb2NrZXQKICAgICAgICAgICAgcmV0dXJuIGlwWzBdWzRd + WzBdCiAgICAgICAgcmV0dXJuIGhvc3RfbmFtZQoKICAgIGRlZiBnZXRfYWN0aXZlX2FuZF9zdGFu + ZGJ5X21ncnMoc2VsZik6CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAg + ICAgICAgICByZXR1cm4gIiIsIHNlbGYuZHJ5X3J1bigiY2VwaCBzdGF0dXMiKQogICAgICAgIG1v + bml0b3JpbmdfZW5kcG9pbnRfcG9ydCA9IHNlbGYuX2FyZ19wYXJzZXIubW9uaXRvcmluZ19lbmRw + b2ludF9wb3J0CiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0ID0gc2VsZi5fYXJn + X3BhcnNlci5tb25pdG9yaW5nX2VuZHBvaW50CiAgICAgICAgc3RhbmRieV9tZ3JzID0gW10KICAg + ICAgICBpZiBub3QgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0OgogICAgICAgICAgICBjbWRf + anNvbiA9IHsicHJlZml4IjogInN0YXR1cyIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgICAg + IHJldF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihj + bWRfanNvbikKICAgICAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1w + dCwKICAgICAgICAgICAgaWYgcmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAg + ICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAg + ICAgICAgICAgIidtZ3Igc2VydmljZXMnIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAg + ICAgICAgIGYiRXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlf + T1VUUFVUX0xJU1R9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBtb25pdG9yaW5nX2Vu + ZHBvaW50ID0gKAogICAgICAgICAgICAgICAganNvbl9vdXQuZ2V0KCJtZ3JtYXAiLCB7fSkuZ2V0 + KCJzZXJ2aWNlcyIsIHt9KS5nZXQoInByb21ldGhldXMiLCAiIikKICAgICAgICAgICAgKQogICAg + ICAgICAgICBpZiBub3QgbW9uaXRvcmluZ19lbmRwb2ludDoKICAgICAgICAgICAgICAgIHJhaXNl + IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgImNhbid0IGZp + bmQgbW9uaXRvcmluZ19lbmRwb2ludCwgcHJvbWV0aGV1cyBtb2R1bGUgbWlnaHQgbm90IGJlIGVu + YWJsZWQsICIKICAgICAgICAgICAgICAgICAgICAiZW5hYmxlIHRoZSBtb2R1bGUgYnkgcnVubmlu + ZyAnY2VwaCBtZ3IgbW9kdWxlIGVuYWJsZSBwcm9tZXRoZXVzJyIKICAgICAgICAgICAgICAgICkK + ICAgICAgICAgICAgIyBub3cgY2hlY2sgdGhlIHN0YW5kLWJ5IG1nci1zCiAgICAgICAgICAgIHN0 + YW5kYnlfYXJyID0ganNvbl9vdXQuZ2V0KCJtZ3JtYXAiLCB7fSkuZ2V0KCJzdGFuZGJ5cyIsIFtd + KQogICAgICAgICAgICBmb3IgZWFjaF9zdGFuZGJ5IGluIHN0YW5kYnlfYXJyOgogICAgICAgICAg + ICAgICAgaWYgIm5hbWUiIGluIGVhY2hfc3RhbmRieS5rZXlzKCk6CiAgICAgICAgICAgICAgICAg + ICAgc3RhbmRieV9tZ3JzLmFwcGVuZChlYWNoX3N0YW5kYnlbIm5hbWUiXSkKICAgICAgICAgICAg + dHJ5OgogICAgICAgICAgICAgICAgcGFyc2VkX2VuZHBvaW50ID0gdXJscGFyc2UobW9uaXRvcmlu + Z19lbmRwb2ludCkKICAgICAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgICAg + ICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgIGYi + aW52YWxpZCBlbmRwb2ludDoge21vbml0b3JpbmdfZW5kcG9pbnR9IgogICAgICAgICAgICAgICAg + KQogICAgICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3QgPSBwYXJzZWRfZW5kcG9p + bnQuaG9zdG5hbWUKICAgICAgICAgICAgaWYgbm90IG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydDoK + ICAgICAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydCA9IHN0cihwYXJzZWRfZW5k + cG9pbnQucG9ydCkKCiAgICAgICAgIyBpZiBtb25pdG9yaW5nIGVuZHBvaW50IHBvcnQgaXMgbm90 + IHNldCwgcHV0IGEgZGVmYXVsdCBtb24gcG9ydAogICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2Vu + ZHBvaW50X3BvcnQ6CiAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydCA9IHNlbGYu + REVGQVVMVF9NT05JVE9SSU5HX0VORFBPSU5UX1BPUlQKCiAgICAgICAgIyB1c2VyIGNvdWxkIGdp + dmUgY29tbWEgYW5kIHNwYWNlIHNlcGFyYXRlZCBpbnB1dHMgKGxpa2UgLS1tb25pdG9yaW5nLWVu + ZHBvaW50PSI8aXAxPiwgPGlwMj4iKQogICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlz + dCA9IG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdC5yZXBsYWNlKCIsIiwgIiAiKQogICAgICAg + IG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdF9zcGxpdCA9IG1vbml0b3JpbmdfZW5kcG9pbnRf + aXBfbGlzdC5zcGxpdCgpCiAgICAgICAgIyBpZiBtb25pdG9yaW5nLWVuZHBvaW50IGNvdWxkIG5v + dCBiZSBmb3VuZCwgcmFpc2UgYW4gZXJyb3IKICAgICAgICBpZiBsZW4obW9uaXRvcmluZ19lbmRw + b2ludF9pcF9saXN0X3NwbGl0KSA9PSAwOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls + dXJlRXhjZXB0aW9uKCJObyAnbW9uaXRvcmluZy1lbmRwb2ludCcgZm91bmQiKQogICAgICAgICMg + Zmlyc3QgaXAgaXMgdHJlYXRlZCBhcyB0aGUgbWFpbiBtb25pdG9yaW5nLWVuZHBvaW50CiAgICAg + ICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcCA9IG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdF9z + cGxpdFswXQogICAgICAgICMgcmVzdCBvZiB0aGUgaXAtcyBhcmUgYWRkZWQgdG8gdGhlICdzdGFu + ZGJ5X21ncnMnIGxpc3QKICAgICAgICBzdGFuZGJ5X21ncnMuZXh0ZW5kKG1vbml0b3JpbmdfZW5k + cG9pbnRfaXBfbGlzdF9zcGxpdFsxOl0pCiAgICAgICAgZmFpbGVkX2lwID0gbW9uaXRvcmluZ19l + bmRwb2ludF9pcAoKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50ID0gIjoiLmpvaW4oCiAgICAg + ICAgICAgIFttb25pdG9yaW5nX2VuZHBvaW50X2lwLCBtb25pdG9yaW5nX2VuZHBvaW50X3BvcnRd + CiAgICAgICAgKQogICAgICAgIGlwX3R5cGUgPSBzZWxmLl9pbnZhbGlkX2VuZHBvaW50KG1vbml0 + b3JpbmdfZW5kcG9pbnQpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBtb25pdG9yaW5nX2VuZHBv + aW50X2lwID0gc2VsZi5fY29udmVydF9ob3N0bmFtZV90b19pcCgKICAgICAgICAgICAgICAgIG1v + bml0b3JpbmdfZW5kcG9pbnRfaXAsIG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydCwgaXBfdHlwZQog + ICAgICAgICAgICApCiAgICAgICAgICAgICMgY29sbGVjdCBhbGwgdGhlICdzdGFuZC1ieScgbWdy + IGlwcwogICAgICAgICAgICBtZ3JfaXBzID0gW10KICAgICAgICAgICAgZm9yIGVhY2hfc3RhbmRi + eV9tZ3IgaW4gc3RhbmRieV9tZ3JzOgogICAgICAgICAgICAgICAgZmFpbGVkX2lwID0gZWFjaF9z + dGFuZGJ5X21ncgogICAgICAgICAgICAgICAgbWdyX2lwcy5hcHBlbmQoCiAgICAgICAgICAgICAg + ICAgICAgc2VsZi5fY29udmVydF9ob3N0bmFtZV90b19pcCgKICAgICAgICAgICAgICAgICAgICAg + ICAgZWFjaF9zdGFuZGJ5X21nciwgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0LCBpcF90eXBlCiAg + ICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKQogICAgICAgIGV4Y2VwdDoKICAg ICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAg - ICAgICAiY2FuJ3QgZmluZCBtb25pdG9yaW5nX2VuZHBvaW50LCBwcm9tZXRoZXVzIG1vZHVsZSBt - aWdodCBub3QgYmUgZW5hYmxlZCwgIgogICAgICAgICAgICAgICAgICAgICJlbmFibGUgdGhlIG1v - ZHVsZSBieSBydW5uaW5nICdjZXBoIG1nciBtb2R1bGUgZW5hYmxlIHByb21ldGhldXMnIgogICAg - ICAgICAgICAgICAgKQogICAgICAgICAgICAjIG5vdyBjaGVjayB0aGUgc3RhbmQtYnkgbWdyLXMK - ICAgICAgICAgICAgc3RhbmRieV9hcnIgPSBqc29uX291dC5nZXQoIm1ncm1hcCIsIHt9KS5nZXQo - InN0YW5kYnlzIiwgW10pCiAgICAgICAgICAgIGZvciBlYWNoX3N0YW5kYnkgaW4gc3RhbmRieV9h - cnI6CiAgICAgICAgICAgICAgICBpZiAibmFtZSIgaW4gZWFjaF9zdGFuZGJ5LmtleXMoKToKICAg - ICAgICAgICAgICAgICAgICBzdGFuZGJ5X21ncnMuYXBwZW5kKGVhY2hfc3RhbmRieVsibmFtZSJd - KQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBwYXJzZWRfZW5kcG9pbnQgPSB1cmxw - YXJzZShtb25pdG9yaW5nX2VuZHBvaW50KQogICAgICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoK - ICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAg - ICAgICAgICAgICAgZiJpbnZhbGlkIGVuZHBvaW50OiB7bW9uaXRvcmluZ19lbmRwb2ludH0iCiAg - ICAgICAgICAgICAgICApCiAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdCA9 - IHBhcnNlZF9lbmRwb2ludC5ob3N0bmFtZQogICAgICAgICAgICBpZiBub3QgbW9uaXRvcmluZ19l - bmRwb2ludF9wb3J0OgogICAgICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0ID0g - c3RyKHBhcnNlZF9lbmRwb2ludC5wb3J0KQoKICAgICAgICAjIGlmIG1vbml0b3JpbmcgZW5kcG9p - bnQgcG9ydCBpcyBub3Qgc2V0LCBwdXQgYSBkZWZhdWx0IG1vbiBwb3J0CiAgICAgICAgaWYgbm90 - IG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydDoKICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2lu - dF9wb3J0ID0gc2VsZi5ERUZBVUxUX01PTklUT1JJTkdfRU5EUE9JTlRfUE9SVAoKICAgICAgICAj - IHVzZXIgY291bGQgZ2l2ZSBjb21tYSBhbmQgc3BhY2Ugc2VwYXJhdGVkIGlucHV0cyAobGlrZSAt - LW1vbml0b3JpbmctZW5kcG9pbnQ9IjxpcDE+LCA8aXAyPiIpCiAgICAgICAgbW9uaXRvcmluZ19l - bmRwb2ludF9pcF9saXN0ID0gbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0LnJlcGxhY2UoIiwi - LCAiICIpCiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0X3NwbGl0ID0gbW9uaXRv - cmluZ19lbmRwb2ludF9pcF9saXN0LnNwbGl0KCkKICAgICAgICAjIGlmIG1vbml0b3JpbmctZW5k - cG9pbnQgY291bGQgbm90IGJlIGZvdW5kLCByYWlzZSBhbiBlcnJvcgogICAgICAgIGlmIGxlbiht - b25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3Rfc3BsaXQpID09IDA6CiAgICAgICAgICAgIHJhaXNl - IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oIk5vICdtb25pdG9yaW5nLWVuZHBvaW50JyBmb3Vu - ZCIpCiAgICAgICAgIyBmaXJzdCBpcCBpcyB0cmVhdGVkIGFzIHRoZSBtYWluIG1vbml0b3Jpbmct - ZW5kcG9pbnQKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwID0gbW9uaXRvcmluZ19lbmRw - b2ludF9pcF9saXN0X3NwbGl0WzBdCiAgICAgICAgIyByZXN0IG9mIHRoZSBpcC1zIGFyZSBhZGRl - ZCB0byB0aGUgJ3N0YW5kYnlfbWdycycgbGlzdAogICAgICAgIHN0YW5kYnlfbWdycy5leHRlbmQo - bW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0X3NwbGl0WzE6XSkKICAgICAgICBmYWlsZWRfaXAg - PSBtb25pdG9yaW5nX2VuZHBvaW50X2lwCgogICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnQgPSAi - OiIuam9pbigKICAgICAgICAgICAgW21vbml0b3JpbmdfZW5kcG9pbnRfaXAsIG1vbml0b3Jpbmdf - ZW5kcG9pbnRfcG9ydF0KICAgICAgICApCiAgICAgICAgaXBfdHlwZSA9IHNlbGYuX2ludmFsaWRf - ZW5kcG9pbnQobW9uaXRvcmluZ19lbmRwb2ludCkKICAgICAgICB0cnk6CiAgICAgICAgICAgIG1v - bml0b3JpbmdfZW5kcG9pbnRfaXAgPSBzZWxmLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKAogICAg - ICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcCwgbW9uaXRvcmluZ19lbmRwb2ludF9w - b3J0LCBpcF90eXBlCiAgICAgICAgICAgICkKICAgICAgICAgICAgIyBjb2xsZWN0IGFsbCB0aGUg - J3N0YW5kLWJ5JyBtZ3IgaXBzCiAgICAgICAgICAgIG1ncl9pcHMgPSBbXQogICAgICAgICAgICBm - b3IgZWFjaF9zdGFuZGJ5X21nciBpbiBzdGFuZGJ5X21ncnM6CiAgICAgICAgICAgICAgICBmYWls - ZWRfaXAgPSBlYWNoX3N0YW5kYnlfbWdyCiAgICAgICAgICAgICAgICBtZ3JfaXBzLmFwcGVuZCgK - ICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKAogICAgICAg - ICAgICAgICAgICAgICAgICBlYWNoX3N0YW5kYnlfbWdyLCBtb25pdG9yaW5nX2VuZHBvaW50X3Bv - cnQsIGlwX3R5cGUKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApCiAgICAg - ICAgZXhjZXB0OgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAog - ICAgICAgICAgICAgICAgZiJDb252ZXJzaW9uIG9mIGhvc3Q6IHtmYWlsZWRfaXB9IHRvIElQIGZh - aWxlZC4gIgogICAgICAgICAgICAgICAgIlBsZWFzZSBlbnRlciB0aGUgSVAgYWRkcmVzc2VzIG9m - IGFsbCB0aGUgY2VwaC1tZ3JzIHdpdGggdGhlICctLW1vbml0b3JpbmctZW5kcG9pbnQnIGZsYWci - CiAgICAgICAgICAgICkKCiAgICAgICAgXywgXywgZXJyID0gc2VsZi5lbmRwb2ludF9kaWFsKG1v - bml0b3JpbmdfZW5kcG9pbnQsIGlwX3R5cGUpCiAgICAgICAgaWYgZXJyID09ICItMSI6CiAgICAg - ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oZXJyKQogICAgICAgICMgYWRk - IHRoZSB2YWxpZGF0ZWQgYWN0aXZlIG1nciBJUCBpbnRvIHRoZSBmaXJzdCBpbmRleAogICAgICAg - IG1ncl9pcHMuaW5zZXJ0KDAsIG1vbml0b3JpbmdfZW5kcG9pbnRfaXApCiAgICAgICAgYWxsX21n - cl9pcHNfc3RyID0gIiwiLmpvaW4obWdyX2lwcykKICAgICAgICByZXR1cm4gYWxsX21ncl9pcHNf - c3RyLCBtb25pdG9yaW5nX2VuZHBvaW50X3BvcnQKCiAgICBkZWYgY2hlY2tfdXNlcl9leGlzdChz - ZWxmLCB1c2VyKToKICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogImF1dGggZ2V0IiwgImVu - dGl0eSI6IGYie3VzZXJ9IiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICByZXRfdmFsLCBqc29u - X291dCwgXyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgaWYg - cmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAgICAgICAgICAgcmV0dXJuICIi - CiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0pCgogICAgZGVmIGdldF9jZXBo - ZnNfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KHNlbGYpOgogICAgICAgIGVudGl0eSA9ICJj - bGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIKICAgICAgICBjYXBzID0gewogICAgICAgICAg + IGYiQ29udmVyc2lvbiBvZiBob3N0OiB7ZmFpbGVkX2lwfSB0byBJUCBmYWlsZWQuICIKICAgICAg + ICAgICAgICAgICJQbGVhc2UgZW50ZXIgdGhlIElQIGFkZHJlc3NlcyBvZiBhbGwgdGhlIGNlcGgt + bWdycyB3aXRoIHRoZSAnLS1tb25pdG9yaW5nLWVuZHBvaW50JyBmbGFnIgogICAgICAgICAgICAp + CgogICAgICAgIF8sIF8sIGVyciA9IHNlbGYuZW5kcG9pbnRfZGlhbChtb25pdG9yaW5nX2VuZHBv + aW50LCBpcF90eXBlKQogICAgICAgIGlmIGVyciA9PSAiLTEiOgogICAgICAgICAgICByYWlzZSBF + eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKGVycikKICAgICAgICAjIGFkZCB0aGUgdmFsaWRhdGVk + IGFjdGl2ZSBtZ3IgSVAgaW50byB0aGUgZmlyc3QgaW5kZXgKICAgICAgICBtZ3JfaXBzLmluc2Vy + dCgwLCBtb25pdG9yaW5nX2VuZHBvaW50X2lwKQogICAgICAgIGFsbF9tZ3JfaXBzX3N0ciA9ICIs + Ii5qb2luKG1ncl9pcHMpCiAgICAgICAgcmV0dXJuIGFsbF9tZ3JfaXBzX3N0ciwgbW9uaXRvcmlu + Z19lbmRwb2ludF9wb3J0CgogICAgZGVmIGNoZWNrX3VzZXJfZXhpc3Qoc2VsZiwgdXNlcik6CiAg + ICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJhdXRoIGdldCIsICJlbnRpdHkiOiBmInt1c2Vy + fSIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIF8gPSBzZWxm + Ll9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgIGlmIHJldF92YWwgIT0gMCBv + ciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJldHVybiAiIgogICAgICAgIHJldHVy + biBzdHIoanNvbl9vdXRbMF1bImtleSJdKQoKICAgIGRlZiBnZXRfY2VwaGZzX3Byb3Zpc2lvbmVy + X2NhcHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSAiY2xpZW50LmNzaS1jZXBo + ZnMtcHJvdmlzaW9uZXIiCiAgICAgICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJhbGxv + dyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJtZ3IiOiAi + YWxsb3cgcnciLAogICAgICAgICAgICAib3NkIjogImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRh + dGE9KiIsCiAgICAgICAgICAgICJtZHMiOiAiYWxsb3cgKiIsCiAgICAgICAgfQogICAgICAgIGlm + IHNlbGYuX2FyZ19wYXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb246CiAgICAgICAgICAg + IGs4c19jbHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAg + ICAgICAgICAgaWYgazhzX2NsdXN0ZXJfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNl + IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIms4c19jbHVz + dGVyX25hbWUgbm90IGZvdW5kLCBwbGVhc2Ugc2V0IHRoZSAnLS1rOHMtY2x1c3Rlci1uYW1lJyBm + bGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBjZXBoZnNfZmlsZXN5c3RlbSA9IHNl + bGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgICAgICBpZiBjZXBo + ZnNfZmlsZXN5c3RlbSA9PSAiIjoKICAgICAgICAgICAgICAgIGVudGl0eSA9IGYie2VudGl0eX0t + e2s4c19jbHVzdGVyX25hbWV9IgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZW50 + aXR5ID0gZiJ7ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFtZX0te2NlcGhmc19maWxlc3lzdGVtfSIK + ICAgICAgICAgICAgICAgIGNhcHNbIm9zZCJdID0gZiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFk + YXRhPXtjZXBoZnNfZmlsZXN5c3RlbX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAg + ICBkZWYgZ2V0X2NlcGhmc19ub2RlX2NhcHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRp + dHkgPSAiY2xpZW50LmNzaS1jZXBoZnMtbm9kZSIKICAgICAgICBjYXBzID0gewogICAgICAgICAg ICAibW9uIjogImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwKICAgICAg ICAgICAgIm1nciI6ICJhbGxvdyBydyIsCiAgICAgICAgICAgICJvc2QiOiAiYWxsb3cgcncgdGFn - IGNlcGhmcyBtZXRhZGF0YT0qIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl - ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgazhzX2NsdXN0ZXJfbmFt - ZSA9IHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZQogICAgICAgICAgICBpZiBrOHNf - Y2x1c3Rlcl9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVy - ZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiazhzX2NsdXN0ZXJfbmFtZSBub3QgZm91 - bmQsIHBsZWFzZSBzZXQgdGhlICctLWs4cy1jbHVzdGVyLW5hbWUnIGZsYWciCiAgICAgICAgICAg - ICAgICApCiAgICAgICAgICAgIGNlcGhmc19maWxlc3lzdGVtID0gc2VsZi5fYXJnX3BhcnNlci5j - ZXBoZnNfZmlsZXN5c3RlbV9uYW1lCiAgICAgICAgICAgIGlmIGNlcGhmc19maWxlc3lzdGVtID09 - ICIiOgogICAgICAgICAgICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFt - ZX0iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9 - LXtrOHNfY2x1c3Rlcl9uYW1lfS17Y2VwaGZzX2ZpbGVzeXN0ZW19IgogICAgICAgICAgICAgICAg - Y2Fwc1sib3NkIl0gPSBmImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9e2NlcGhmc19maWxl - c3lzdGVtfSIKCiAgICAgICAgcmV0dXJuIGNhcHMsIGVudGl0eQoKICAgIGRlZiBnZXRfY2VwaGZz - X25vZGVfY2Fwc19hbmRfZW50aXR5KHNlbGYpOgogICAgICAgIGVudGl0eSA9ICJjbGllbnQuY3Np - LWNlcGhmcy1ub2RlIgogICAgICAgIGNhcHMgPSB7CiAgICAgICAgICAgICJtb24iOiAiYWxsb3cg - ciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLAogICAgICAgICAgICAibWdyIjogImFs - bG93IHJ3IiwKICAgICAgICAgICAgIm9zZCI6ICJhbGxvdyBydyB0YWcgY2VwaGZzICo9KiIsCiAg - ICAgICAgICAgICJtZHMiOiAiYWxsb3cgcnciLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9h - cmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uOgogICAgICAgICAgICBrOHNfY2x1 - c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lCiAgICAgICAgICAg - IGlmIGs4c19jbHVzdGVyX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRp - b25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJrOHNfY2x1c3Rlcl9uYW1l - IG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAg - ICAgICAgICAgICAgICkKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW0gPSBzZWxmLl9hcmdf - cGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICAgICAgaWYgY2VwaGZzX2ZpbGVz - eXN0ZW0gPT0gIiI6CiAgICAgICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1 - c3Rlcl9uYW1lfSIKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGVudGl0eSA9IGYi - e2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXtjZXBoZnNfZmlsZXN5c3RlbX0iCiAgICAgICAg - ICAgICAgICBjYXBzWyJvc2QiXSA9IGYiYWxsb3cgcncgdGFnIGNlcGhmcyAqPXtjZXBoZnNfZmls - ZXN5c3RlbX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2VudGl0 - eSgKICAgICAgICBzZWxmLAogICAgICAgIGVudGl0eSwKICAgICAgICByYmRfcG9vbF9uYW1lLAog - ICAgICAgIGFsaWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgazhzX2NsdXN0ZXJfbmFtZSwKICAg - ICAgICByYWRvc19uYW1lc3BhY2UsCiAgICApOgogICAgICAgIGlmICgKICAgICAgICAgICAgcmJk - X3Bvb2xfbmFtZS5jb3VudCgiLiIpICE9IDAKICAgICAgICAgICAgb3IgcmJkX3Bvb2xfbmFtZS5j - b3VudCgiXyIpICE9IDAKICAgICAgICAgICAgb3IgYWxpYXNfcmJkX3Bvb2xfbmFtZSAhPSAiIgog - ICAgICAgICAgICAjIGNoZWNraW5nIGFsaWFzX3JiZF9wb29sX25hbWUgaXMgbm90IGVtcHR5IGFz - IHRoZXJlIG1heWJlIGEgc3BlY2lhbCBjaGFyYWN0ZXIgdXNlZCBvdGhlciB0aGFuIC4gb3IgXwog - ICAgICAgICk6CiAgICAgICAgICAgIGlmIGFsaWFzX3JiZF9wb29sX25hbWUgPT0gIiI6CiAgICAg - ICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAg - ICAgICAgICJwbGVhc2Ugc2V0IHRoZSAnLS1hbGlhcy1yYmQtZGF0YS1wb29sLW5hbWUnIGZsYWcg - YXMgdGhlIHJiZCBkYXRhIHBvb2wgbmFtZSBjb250YWlucyAnLicgb3IgJ18nIgogICAgICAgICAg - ICAgICAgKQogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICBhbGlhc19yYmRfcG9vbF9u - YW1lLmNvdW50KCIuIikgIT0gMAogICAgICAgICAgICAgICAgb3IgYWxpYXNfcmJkX3Bvb2xfbmFt - ZS5jb3VudCgiXyIpICE9IDAKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHJhaXNlIEV4 - ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIictLWFsaWFzLXJi - ZC1kYXRhLXBvb2wtbmFtZScgZmxhZyB2YWx1ZSBzaG91bGQgbm90IGNvbnRhaW4gJy4nIG9yICdf - JyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17azhz - X2NsdXN0ZXJfbmFtZX0te2FsaWFzX3JiZF9wb29sX25hbWV9IgogICAgICAgIGVsc2U6CiAgICAg - ICAgICAgIGVudGl0eSA9IGYie2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXtyYmRfcG9vbF9u - YW1lfSIKCiAgICAgICAgaWYgcmFkb3NfbmFtZXNwYWNlOgogICAgICAgICAgICBlbnRpdHkgPSBm - IntlbnRpdHl9LXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgIHJldHVybiBlbnRpdHkKCiAgICBk - ZWYgZ2V0X3JiZF9wcm92aXNpb25lcl9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50 - aXR5ID0gImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIgogICAgICAgIGNhcHMgPSB7CiAgICAg - ICAgICAgICJtb24iOiAicHJvZmlsZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3Qn - IiwKICAgICAgICAgICAgIm1nciI6ICJhbGxvdyBydyIsCiAgICAgICAgICAgICJvc2QiOiAicHJv - ZmlsZSByYmQiLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0 - ZWRfYXV0aF9wZXJtaXNzaW9uOgogICAgICAgICAgICByYmRfcG9vbF9uYW1lID0gc2VsZi5fYXJn - X3BhcnNlci5yYmRfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFt - ZSA9IHNlbGYuX2FyZ19wYXJzZXIuYWxpYXNfcmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAg - IGs4c19jbHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAg - ICAgICAgICAgcmFkb3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3Bh - Y2UKICAgICAgICAgICAgaWYgcmJkX3Bvb2xfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJh - aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRh - dG9yeSBmbGFnIG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tcmJkLWRhdGEtcG9vbC1uYW1l - JyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1l - ID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigK - ICAgICAgICAgICAgICAgICAgICAibWFuZGF0b3J5IGZsYWcgbm90IGZvdW5kLCBwbGVhc2Ugc2V0 - IHRoZSAnLS1rOHMtY2x1c3Rlci1uYW1lJyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAg - ICAgICBlbnRpdHkgPSBzZWxmLmdldF9lbnRpdHkoCiAgICAgICAgICAgICAgICBlbnRpdHksCiAg - ICAgICAgICAgICAgICByYmRfcG9vbF9uYW1lLAogICAgICAgICAgICAgICAgYWxpYXNfcmJkX3Bv - b2xfbmFtZSwKICAgICAgICAgICAgICAgIGs4c19jbHVzdGVyX25hbWUsCiAgICAgICAgICAgICAg - ICByYWRvc19uYW1lc3BhY2UsCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgcmFkb3NfbmFt - ZXNwYWNlICE9ICIiOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSAoCiAgICAgICAgICAg - ICAgICAgICAgZiJwcm9maWxlIHJiZCBwb29sPXtyYmRfcG9vbF9uYW1lfSBuYW1lc3BhY2U9e3Jh - ZG9zX25hbWVzcGFjZX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAg - ICAgICAgICAgICBjYXBzWyJvc2QiXSA9IGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFt - ZX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X3JiZF9ub2RlX2Nh - cHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSAiY2xpZW50LmNzaS1yYmQtbm9k - ZSIKICAgICAgICBjYXBzID0gewogICAgICAgICAgICAibW9uIjogInByb2ZpbGUgcmJkLCBhbGxv - dyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJvc2QiOiAicHJvZmlsZSBy - YmQiLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0 - aF9wZXJtaXNzaW9uOgogICAgICAgICAgICByYmRfcG9vbF9uYW1lID0gc2VsZi5fYXJnX3BhcnNl - ci5yYmRfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFtZSA9IHNl - bGYuX2FyZ19wYXJzZXIuYWxpYXNfcmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGs4c19j - bHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAgICAgICAg - ICAgcmFkb3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UKICAg - ICAgICAgICAgaWYgcmJkX3Bvb2xfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4 - ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBm - bGFnIG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tcmJkLWRhdGEtcG9vbC1uYW1lJyBmbGFn - IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1lID09ICIi - OgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAg - ICAgICAgICAgICAgICAibWFuZGF0b3J5IGZsYWcgbm90IGZvdW5kLCBwbGVhc2Ugc2V0IHRoZSAn - LS1rOHMtY2x1c3Rlci1uYW1lJyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBl - bnRpdHkgPSBzZWxmLmdldF9lbnRpdHkoCiAgICAgICAgICAgICAgICBlbnRpdHksCiAgICAgICAg - ICAgICAgICByYmRfcG9vbF9uYW1lLAogICAgICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFt - ZSwKICAgICAgICAgICAgICAgIGs4c19jbHVzdGVyX25hbWUsCiAgICAgICAgICAgICAgICByYWRv - c19uYW1lc3BhY2UsCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgcmFkb3NfbmFtZXNwYWNl - ICE9ICIiOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSAoCiAgICAgICAgICAgICAgICAg - ICAgZiJwcm9maWxlIHJiZCBwb29sPXtyYmRfcG9vbF9uYW1lfSBuYW1lc3BhY2U9e3JhZG9zX25h - bWVzcGFjZX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg - ICAgICBjYXBzWyJvc2QiXSA9IGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFtZX0iCgog - ICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2RlZmF1bHRVc2VyX2NhcHNf - YW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSBzZWxmLnJ1bl9hc191c2VyCiAgICAg - ICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1 - b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQgdmVyc2lvbiIsCiAgICAgICAgICAgICJtZ3IiOiAi - YWxsb3cgY29tbWFuZCBjb25maWciLAogICAgICAgICAgICAib3NkIjogZiJwcm9maWxlIHJiZC1y - ZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPXtzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZp - eH0ucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9e3NlbGYu - X2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD17 - c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5sb2csIGFsbG93IHggcG9vbD17 - c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5idWNrZXRzLmluZGV4IiwKICAg - ICAgICB9CgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2NhcHNfYW5k - X2VudGl0eShzZWxmLCB1c2VyX25hbWUpOgogICAgICAgIGlmICJjbGllbnQuY3NpLWNlcGhmcy1w - cm92aXNpb25lciIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAiY2xpZW50LmNzaS1jZXBo - ZnMtcHJvdmlzaW9uZXIiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19w - YXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAgIHJldHVy - biBzZWxmLmdldF9jZXBoZnNfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KCkKICAgICAgICBp - ZiAiY2xpZW50LmNzaS1jZXBoZnMtbm9kZSIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAi - Y2xpZW50LmNzaS1jZXBoZnMtbm9kZSIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2Vs - Zi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAg - ICAgcmV0dXJuIHNlbGYuZ2V0X2NlcGhmc19ub2RlX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAg - aWYgImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiBpbiB1c2VyX25hbWU6CiAgICAgICAgICAg - IGlmICJjbGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIgIT0gdXNlcl9uYW1lOgogICAgICAgICAg - ICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUK - ICAgICAgICAgICAgcmV0dXJuIHNlbGYuZ2V0X3JiZF9wcm92aXNpb25lcl9jYXBzX2FuZF9lbnRp - dHkoKQogICAgICAgIGlmICJjbGllbnQuY3NpLXJiZC1ub2RlIiBpbiB1c2VyX25hbWU6CiAgICAg - ICAgICAgIGlmICJjbGllbnQuY3NpLXJiZC1ub2RlIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAg - ICAgICBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQog - ICAgICAgICAgICByZXR1cm4gc2VsZi5nZXRfcmJkX25vZGVfY2Fwc19hbmRfZW50aXR5KCkKICAg - ICAgICBpZiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiIGluIHVzZXJfbmFtZToKICAgICAgICAgICAg - aWYgImNsaWVudC5oZWFsdGhjaGVja2VyIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAgICAgICBz - ZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQogICAgICAg - ICAgICByZXR1cm4gc2VsZi5nZXRfZGVmYXVsdFVzZXJfY2Fwc19hbmRfZW50aXR5KCkKCiAgICAg - ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgZiJubyB1c2Vy - IGZvdW5kIHdpdGggdXNlcl9uYW1lOiB7dXNlcl9uYW1lfSwgIgogICAgICAgICAgICAiZ2V0X2Nh - cHNfYW5kX2VudGl0eSBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICApCgogICAgZGVmIGNyZWF0 - ZV9jZXBoQ1NJS2V5cmluZ191c2VyKHNlbGYsIHVzZXIpOgogICAgICAgICIiIgogICAgICAgIGNv - bW1hbmQ6IGNlcGggYXV0aCBnZXQtb3ItY3JlYXRlIGNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv - bmVyIG1vbiAnYWxsb3cgcicgbWdyICdhbGxvdyBydycgb3NkICdhbGxvdyBydyB0YWcgY2VwaGZz - IG1ldGFkYXRhPSonCiAgICAgICAgIiIiCiAgICAgICAgY2FwcywgZW50aXR5ID0gc2VsZi5nZXRf - Y2Fwc19hbmRfZW50aXR5KHVzZXIpCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJw - cmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIiwKICAgICAgICAgICAgImVudGl0eSI6IGVudGl0 - eSwKICAgICAgICAgICAgImNhcHMiOiBbY2FwIGZvciBjYXBfbGlzdCBpbiBsaXN0KGNhcHMuaXRl - bXMoKSkgZm9yIGNhcCBpbiBjYXBfbGlzdF0sCiAgICAgICAgICAgICJmb3JtYXQiOiAianNvbiIs - CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAg - ICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICBzZWxmLmRyeV9ydW4oCiAgICAgICAgICAgICAg - ICAgICAgImNlcGggIgogICAgICAgICAgICAgICAgICAgICsgY21kX2pzb25bInByZWZpeCJdCiAg - ICAgICAgICAgICAgICAgICAgKyAiICIKICAgICAgICAgICAgICAgICAgICArIGNtZF9qc29uWyJl - bnRpdHkiXQogICAgICAgICAgICAgICAgICAgICsgIiAiCiAgICAgICAgICAgICAgICAgICAgKyAi - ICIuam9pbihjbWRfanNvblsiY2FwcyJdKQogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAg - ICAgICIiLAogICAgICAgICAgICApCiAgICAgICAgIyBjaGVjayBpZiB1c2VyIGFscmVhZHkgZXhp - c3QKICAgICAgICB1c2VyX2tleSA9IHNlbGYuY2hlY2tfdXNlcl9leGlzdChlbnRpdHkpCiAgICAg - ICAgaWYgdXNlcl9rZXkgIT0gIiI6CiAgICAgICAgICAgIHJldHVybiB1c2VyX2tleSwgZiJ7ZW50 - aXR5LnNwbGl0KCcuJywgMSlbMV19IgogICAgICAgICAgICAjIGVudGl0eS5zcGxpdCgnLicsMSlb - MV0gdG8gcmVuYW1lIGVudGl0eShjbGllbnQuY3NpLXJiZC1ub2RlKSBhcyBjc2ktcmJkLW5vZGUK - CiAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pz - b25fZ2VuKGNtZF9qc29uKQogICAgICAgICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0 - dGVtcHQsCiAgICAgICAgaWYgcmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAg - ICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAg - IGYiJ2F1dGggZ2V0LW9yLWNyZWF0ZSB7dXNlcn0nIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAg - ICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBU - WV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICkKICAgICAgICByZXR1cm4gc3RyKGpzb25fb3V0 - WzBdWyJrZXkiXSksIGYie2VudGl0eS5zcGxpdCgnLicsIDEpWzFdfSIKICAgICAgICAjIGVudGl0 - eS5zcGxpdCgnLicsMSlbMV0gdG8gcmVuYW1lIGVudGl0eShjbGllbnQuY3NpLXJiZC1ub2RlKSBh - cyBjc2ktcmJkLW5vZGUKCiAgICBkZWYgZ2V0X2NlcGhmc19kYXRhX3Bvb2xfZGV0YWlscyhzZWxm - KToKICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogImZzIGxzIiwgImZvcm1hdCI6ICJqc29u - In0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVy - biBzZWxmLmRyeV9ydW4oImNlcGggIiArIGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRf - dmFsLCBqc29uX291dCwgZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pz - b24pCiAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwgcmVwb3J0 - IGFuIGVycm9yCiAgICAgICAgaWYgcmV0X3ZhbCAhPSAwOgogICAgICAgICAgICAjIGlmIGZzIGFu - ZCBkYXRhX3Bvb2wgYXJndW1lbnRzIGFyZSBub3Qgc2V0LCBzaWxlbnRseSByZXR1cm4KICAgICAg - ICAgICAgaWYgKAogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmlsZXN5 - c3RlbV9uYW1lID09ICIiCiAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5jZXBo - ZnNfZGF0YV9wb29sX25hbWUgPT0gIiIKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHJl - dHVybgogICAgICAgICAgICAjIGlmIHVzZXIgaGFzIHByb3ZpZGVkIGFueSBvZiB0aGUKICAgICAg - ICAgICAgIyAnLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lJyBvciAnLS1jZXBoZnMtZGF0YS1wb29s - LW5hbWUnIGFyZ3VtZW50cywKICAgICAgICAgICAgIyByYWlzZSBhbiBleGNlcHRpb24gYXMgd2Ug - YXJlIHVuYWJsZSB0byB2ZXJpZnkgdGhlIGFyZ3MKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9u - RmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiJ2ZzIGxzJyBjZXBoIGNhbGwgZmFp - bGVkIHdpdGggZXJyb3I6IHtlcnJfbXNnfSIKICAgICAgICAgICAgKQoKICAgICAgICBtYXRjaGlu - Z19qc29uX291dCA9IHt9CiAgICAgICAgIyBpZiAnLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lJyBh - cmd1bWVudCBpcyBwcm92aWRlZCwKICAgICAgICAjIGNoZWNrIHdoZXRoZXIgdGhlIHByb3ZpZGVk - IGZpbGVzeXN0ZW0tbmFtZSBleGlzdHMgb3Igbm90CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl - ci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lOgogICAgICAgICAgICAjIGdldCB0aGUgbWF0Y2hpbmcg - bGlzdAogICAgICAgICAgICBtYXRjaGluZ19qc29uX291dF9saXN0ID0gWwogICAgICAgICAgICAg - ICAgbWF0Y2hlZAogICAgICAgICAgICAgICAgZm9yIG1hdGNoZWQgaW4ganNvbl9vdXQKICAgICAg - ICAgICAgICAgIGlmIHN0cihtYXRjaGVkWyJuYW1lIl0pID09IHNlbGYuX2FyZ19wYXJzZXIuY2Vw - aGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgICAgICBdCiAgICAgICAgICAgICMgdW5hYmxlIHRv - IGZpbmQgYSBtYXRjaGluZyBmcy1uYW1lLCByYWlzZSBhbiBlcnJvcgogICAgICAgICAgICBpZiBs - ZW4obWF0Y2hpbmdfanNvbl9vdXRfbGlzdCkgPT0gMDoKICAgICAgICAgICAgICAgIHJhaXNlIEV4 - ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgZiJGaWxlc3lzdGVt - IHByb3ZpZGVkLCAne3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZX0nLCAi - CiAgICAgICAgICAgICAgICAgICAgZiJpcyBub3QgZm91bmQgaW4gdGhlIGZzLWxpc3Q6IHtbc3Ry - KHhbJ25hbWUnXSkgZm9yIHggaW4ganNvbl9vdXRdfSIKICAgICAgICAgICAgICAgICkKICAgICAg - ICAgICAgbWF0Y2hpbmdfanNvbl9vdXQgPSBtYXRjaGluZ19qc29uX291dF9saXN0WzBdCiAgICAg - ICAgIyBpZiBjZXBoZnMgZmlsZXN5c3RlbSBuYW1lIGlzIG5vdCBwcm92aWRlZCwKICAgICAgICAj - IHRyeSB0byBnZXQgYSBkZWZhdWx0IGZzIG5hbWUgYnkgZG9pbmcgdGhlIGZvbGxvd2luZwogICAg - ICAgIGVsc2U6CiAgICAgICAgICAgICMgYS4gY2hlY2sgaWYgdGhlcmUgaXMgb25seSBvbmUgZmls - ZXN5c3RlbSBpcyBwcmVzZW50CiAgICAgICAgICAgIGlmIGxlbihqc29uX291dCkgPT0gMToKICAg - ICAgICAgICAgICAgIG1hdGNoaW5nX2pzb25fb3V0ID0ganNvbl9vdXRbMF0KICAgICAgICAgICAg - IyBiLiBvciBlbHNlLCBjaGVjayBpZiBkYXRhX3Bvb2wgbmFtZSBpcyBwcm92aWRlZAogICAgICAg - ICAgICBlbGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lOgogICAgICAg - ICAgICAgICAgIyBhbmQgaWYgcHJlc2VudCwgY2hlY2sgd2hldGhlciB0aGVyZSBleGlzdHMgYSBm - cyB3aGljaCBoYXMgdGhlIGRhdGFfcG9vbAogICAgICAgICAgICAgICAgZm9yIGVhY2hKIGluIGpz - b25fb3V0OgogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2Rh - dGFfcG9vbF9uYW1lIGluIGVhY2hKWyJkYXRhX3Bvb2xzIl06CiAgICAgICAgICAgICAgICAgICAg - ICAgIG1hdGNoaW5nX2pzb25fb3V0ID0gZWFjaEoKICAgICAgICAgICAgICAgICAgICAgICAgYnJl - YWsKICAgICAgICAgICAgICAgICMgaWYgdGhlcmUgaXMgbm8gbWF0Y2hpbmcgZnMgZXhpc3RzLCB0 - aGF0IG1lYW5zIHByb3ZpZGVkIGRhdGFfcG9vbCBuYW1lIGlzIGludmFsaWQKICAgICAgICAgICAg - ICAgIGlmIG5vdCBtYXRjaGluZ19qc29uX291dDoKICAgICAgICAgICAgICAgICAgICByYWlzZSBF - eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICAgICBmIlByb3Zp - ZGVkIGRhdGFfcG9vbCBuYW1lLCB7c2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25h - bWV9LCIKICAgICAgICAgICAgICAgICAgICAgICAgIiBkb2VzIG5vdCBleGlzdHMiCiAgICAgICAg - ICAgICAgICAgICAgKQogICAgICAgICAgICAjIGMuIGlmIG5vdGhpbmcgaXMgc2V0IGFuZCBjb3Vs - ZG4ndCBmaW5kIGEgZGVmYXVsdCwKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICMg - anVzdCByZXR1cm4gc2lsZW50bHkKICAgICAgICAgICAgICAgIHJldHVybgoKICAgICAgICBpZiBt - YXRjaGluZ19qc29uX291dDoKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls - ZXN5c3RlbV9uYW1lID0gc3RyKG1hdGNoaW5nX2pzb25fb3V0WyJuYW1lIl0pCiAgICAgICAgICAg - IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX21ldGFkYXRhX3Bvb2xfbmFtZSA9IHN0cigKICAgICAg - ICAgICAgICAgIG1hdGNoaW5nX2pzb25fb3V0WyJtZXRhZGF0YV9wb29sIl0KICAgICAgICAgICAg - KQoKICAgICAgICBpZiBpc2luc3RhbmNlKG1hdGNoaW5nX2pzb25fb3V0WyJkYXRhX3Bvb2xzIl0s - IGxpc3QpOgogICAgICAgICAgICAjIGlmIHRoZSB1c2VyIGhhcyBhbHJlYWR5IHByb3ZpZGVkIGRh - dGEtcG9vbC1uYW1lLAogICAgICAgICAgICAjIHRocm91Z2ggLS1jZXBoZnMtZGF0YS1wb29sLW5h - bWUKICAgICAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWU6 - CiAgICAgICAgICAgICAgICAjIGlmIHRoZSBwcm92aWRlZCBuYW1lIGlzIG5vdCBtYXRjaGluZyB3 - aXRoIHRoZSBvbmUgaW4gdGhlIGxpc3QKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAg - ICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFtZQogICAgICAgICAg - ICAgICAgICAgIG5vdCBpbiBtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdCiAgICAgICAg - ICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl - cHRpb24oCiAgICAgICAgICAgICAgICAgICAgICAgIGYiUHJvdmlkZWQgZGF0YS1wb29sLW5hbWU6 - ICd7c2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWV9JywgIgogICAgICAgICAg - ICAgICAgICAgICAgICAiZG9lc24ndCBtYXRjaCBmcm9tIHRoZSBkYXRhLXBvb2xzIGxpc3Q6ICIK - ICAgICAgICAgICAgICAgICAgICAgICAgZiJ7W3N0cih4KSBmb3IgeCBpbiBtYXRjaGluZ19qc29u - X291dFsnZGF0YV9wb29scyddXX0iCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAj - IGlmIGRhdGFfcG9vbCBuYW1lIGlzIG5vdCBwcm92aWRlZCwKICAgICAgICAgICAgIyB0aGVuIHRy - eSB0byBmaW5kIGEgZGVmYXVsdCBkYXRhIHBvb2wgbmFtZQogICAgICAgICAgICBlbHNlOgogICAg - ICAgICAgICAgICAgIyBpZiBubyBkYXRhX3Bvb2xzIGV4aXN0LCBzaWxlbnRseSByZXR1cm4KICAg - ICAgICAgICAgICAgIGlmIGxlbihtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdKSA9PSAw - OgogICAgICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3Bh - cnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWUgPSBzdHIoCiAgICAgICAgICAgICAgICAgICAgbWF0 - Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXVswXQogICAgICAgICAgICAgICAgKQogICAgICAg - ICAgICAjIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lICdkYXRhX3Bvb2xzJyBleGlzdCwKICAg - ICAgICAgICAgIyB0aGVuIHdhcm4gdGhlIHVzZXIgdGhhdCB3ZSBhcmUgdXNpbmcgdGhlIHNlbGVj - dGVkIG5hbWUKICAgICAgICAgICAgaWYgbGVuKG1hdGNoaW5nX2pzb25fb3V0WyJkYXRhX3Bvb2xz - Il0pID4gMToKICAgICAgICAgICAgICAgIHByaW50KAogICAgICAgICAgICAgICAgICAgICJXQVJO - SU5HOiBNdWx0aXBsZSBkYXRhIHBvb2xzIGRldGVjdGVkOiAiCiAgICAgICAgICAgICAgICAgICAg - ZiJ7W3N0cih4KSBmb3IgeCBpbiBtYXRjaGluZ19qc29uX291dFsnZGF0YV9wb29scyddXX1cbiIK - ICAgICAgICAgICAgICAgICAgICBmIlVzaW5nIHRoZSBkYXRhLXBvb2w6ICd7c2VsZi5fYXJnX3Bh - cnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWV9J1xuIgogICAgICAgICAgICAgICAgKQoKICAgIGRl - ZiBjcmVhdGVfY2hlY2tlcktleShzZWxmLCB1c2VyKToKICAgICAgICBjYXBzLCBlbnRpdHkgPSBz - ZWxmLmdldF9jYXBzX2FuZF9lbnRpdHkodXNlcikKICAgICAgICBjbWRfanNvbiA9IHsKICAgICAg - ICAgICAgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUiLAogICAgICAgICAgICAiZW50aXR5 - IjogZW50aXR5LAogICAgICAgICAgICAiY2FwcyI6IFtjYXAgZm9yIGNhcF9saXN0IGluIGxpc3Qo - Y2Fwcy5pdGVtcygpKSBmb3IgY2FwIGluIGNhcF9saXN0XSwKICAgICAgICAgICAgImZvcm1hdCI6 - ICJqc29uIiwKICAgICAgICB9CgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoK - ICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigKICAgICAgICAgICAgICAgICJjZXBoICIK - ICAgICAgICAgICAgICAgICsgY21kX2pzb25bInByZWZpeCJdCiAgICAgICAgICAgICAgICArICIg - IgogICAgICAgICAgICAgICAgKyBjbWRfanNvblsiZW50aXR5Il0KICAgICAgICAgICAgICAgICsg - IiAiCiAgICAgICAgICAgICAgICArICIgIi5qb2luKGNtZF9qc29uWyJjYXBzIl0pCiAgICAgICAg - ICAgICkKICAgICAgICAjIGNoZWNrIGlmIHVzZXIgYWxyZWFkeSBleGlzdAogICAgICAgIHVzZXJf - a2V5ID0gc2VsZi5jaGVja191c2VyX2V4aXN0KGVudGl0eSkKICAgICAgICBpZiB1c2VyX2tleSAh - PSAiIjoKICAgICAgICAgICAgcmV0dXJuIHVzZXJfa2V5CgogICAgICAgIHJldF92YWwsIGpzb25f - b3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAg - ICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgIGlmIHJldF92 - YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlv - bkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGdldC1vci1jcmVhdGUg - e3NlbGYucnVuX2FzX3VzZXJ9JyBjb21tYW5kIGZhaWxlZFxuIgogICAgICAgICAgICAgICAgZiJF - cnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElT - VH0iCiAgICAgICAgICAgICkKICAgICAgICByZXR1cm4gc3RyKGpzb25fb3V0WzBdWyJrZXkiXSkK - CiAgICBkZWYgZ2V0X2NlcGhfZGFzaGJvYXJkX2xpbmsoc2VsZik6CiAgICAgICAgY21kX2pzb24g - PSB7InByZWZpeCI6ICJtZ3Igc2VydmljZXMiLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgIGlm - IHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1 - bigiY2VwaCAiICsgY21kX2pzb25bInByZWZpeCJdKQogICAgICAgIHJldF92YWwsIGpzb25fb3V0 - LCBfID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICAjIGlmIHRo - ZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgIGlmIHJldF92YWwgIT0gMCBv - ciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJldHVybiBOb25lCiAgICAgICAgaWYg - ImRhc2hib2FyZCIgbm90IGluIGpzb25fb3V0OgogICAgICAgICAgICByZXR1cm4gTm9uZQogICAg - ICAgIHJldHVybiBqc29uX291dFsiZGFzaGJvYXJkIl0KCiAgICBkZWYgY3JlYXRlX3Jnd19hZG1p - bl9vcHNfdXNlcihzZWxmKToKICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICJyYWRvc2d3LWFk - bWluIiwKICAgICAgICAgICAgInVzZXIiLAogICAgICAgICAgICAiY3JlYXRlIiwKICAgICAgICAg - ICAgIi0tdWlkIiwKICAgICAgICAgICAgc2VsZi5FWFRFUk5BTF9SR1dfQURNSU5fT1BTX1VTRVJf - TkFNRSwKICAgICAgICAgICAgIi0tZGlzcGxheS1uYW1lIiwKICAgICAgICAgICAgIlJvb2sgUkdX - IEFkbWluIE9wcyB1c2VyIiwKICAgICAgICAgICAgIi0tY2FwcyIsCiAgICAgICAgICAgICJidWNr - ZXRzPSo7dXNlcnM9Kjt1c2FnZT1yZWFkO21ldGFkYXRhPXJlYWQ7em9uZT1yZWFkIiwKICAgICAg - ICAgICAgIi0tcmd3LXJlYWxtIiwKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVh - bG1fbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAgICAgICAgIHNlbGYu - X2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lLAogICAgICAgICAgICAiLS1yZ3ctem9uZSIs - CiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwKICAgICAgICBdCiAg - ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2Vs - Zi5kcnlfcnVuKCJjZXBoICIgKyAiICIuam9pbihjbWQpKQogICAgICAgIHRyeToKICAgICAgICAg - ICAgb3V0cHV0ID0gc3VicHJvY2Vzcy5jaGVja19vdXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vz - cy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBl - eGVjRXJyOgogICAgICAgICAgICAjIGlmIHRoZSB1c2VyIGFscmVhZHkgZXhpc3RzLCB3ZSBqdXN0 - IHF1ZXJ5IGl0CiAgICAgICAgICAgIGlmIGV4ZWNFcnIucmV0dXJuY29kZSA9PSBlcnJuby5FRVhJ - U1Q6CiAgICAgICAgICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICAgICAgICAgInJhZG9zZ3ct - YWRtaW4iLAogICAgICAgICAgICAgICAgICAgICJ1c2VyIiwKICAgICAgICAgICAgICAgICAgICAi - aW5mbyIsCiAgICAgICAgICAgICAgICAgICAgIi0tdWlkIiwKICAgICAgICAgICAgICAgICAgICBz - ZWxmLkVYVEVSTkFMX1JHV19BRE1JTl9PUFNfVVNFUl9OQU1FLAogICAgICAgICAgICAgICAgICAg - ICItLXJndy1yZWFsbSIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3df - cmVhbG1fbmFtZSwKICAgICAgICAgICAgICAgICAgICAiLS1yZ3ctem9uZWdyb3VwIiwKICAgICAg - ICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAg - ICAgICAgICAgICAgICAiLS1yZ3ctem9uZSIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJn - X3BhcnNlci5yZ3dfem9uZV9uYW1lLAogICAgICAgICAgICAgICAgXQogICAgICAgICAgICAgICAg - dHJ5OgogICAgICAgICAgICAgICAgICAgIG91dHB1dCA9IHN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0 - KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICAgICAgICAgIGV4Y2VwdCBzdWJw - cm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAgICAgICAgICAg - IGVycl9tc2cgPSAoCiAgICAgICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUg - Y29tbWFuZCB7Y21kfS4gT3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAg - ICAgICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5z - dGRlcnJ9IgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICBzeXMuc3Rk - ZXJyLndyaXRlKGVycl9tc2cpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE5vbmUsIE5vbmUs - IEZhbHNlLCAiLTEiCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlcnJfbXNnID0g - KAogICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUgY29tbWFuZCB7Y21kfS4g - T3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAgICAgICAgZiJDb2RlOiB7 - ZXhlY0Vyci5yZXR1cm5jb2RlfS4gRXJyb3I6IHtleGVjRXJyLnN0ZGVycn0iCiAgICAgICAgICAg - ICAgICApCiAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycl9tc2cpCiAgICAgICAg - ICAgICAgICByZXR1cm4gTm9uZSwgTm9uZSwgRmFsc2UsICItMSIKCiAgICAgICAgIyBzZXBhcmF0 - ZWx5IGFkZCBpbmZvPXJlYWQgY2FwcyBmb3Igcmd3LWVuZHBvaW50IGlwIHZhbGlkYXRpb24KICAg - ICAgICBpbmZvX2NhcF9zdXBwb3J0ZWQgPSBUcnVlCiAgICAgICAgY21kID0gWwogICAgICAgICAg - ICAicmFkb3Nndy1hZG1pbiIsCiAgICAgICAgICAgICJjYXBzIiwKICAgICAgICAgICAgImFkZCIs - CiAgICAgICAgICAgICItLXVpZCIsCiAgICAgICAgICAgIHNlbGYuRVhURVJOQUxfUkdXX0FETUlO - X09QU19VU0VSX05BTUUsCiAgICAgICAgICAgICItLWNhcHMiLAogICAgICAgICAgICAiaW5mbz1y - ZWFkIiwKICAgICAgICAgICAgIi0tcmd3LXJlYWxtIiwKICAgICAgICAgICAgc2VsZi5fYXJnX3Bh - cnNlci5yZ3dfcmVhbG1fbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAg - ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lLAogICAgICAgICAgICAi - LS1yZ3ctem9uZSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwK - ICAgICAgICBdCiAgICAgICAgdHJ5OgogICAgICAgICAgICBvdXRwdXQgPSBzdWJwcm9jZXNzLmNo - ZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhjZXB0IHN1 - YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4ZWNFcnI6CiAgICAgICAgICAgICMgaWYg - dGhlIGNlcGggdmVyc2lvbiBub3Qgc3VwcG9ydGVkIGZvciBhZGRpbmcgYGluZm89cmVhZGAgY2Fw - KHJnd192YWxpZGF0aW9uKQogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAiY291bGQg - bm90IGFkZCBjYXBzOiB1bmFibGUgdG8gYWRkIGNhcHM6IGluZm89cmVhZFxuIgogICAgICAgICAg - ICAgICAgaW4gZXhlY0Vyci5zdGRlcnIuZGVjb2RlKCJ1dGYtOCIpCiAgICAgICAgICAgICAgICBh - bmQgZXhlY0Vyci5yZXR1cm5jb2RlID09IDI0NAogICAgICAgICAgICApOgogICAgICAgICAgICAg - ICAgaW5mb19jYXBfc3VwcG9ydGVkID0gRmFsc2UKICAgICAgICAgICAgZWxzZToKICAgICAgICAg - ICAgICAgIGVycl9tc2cgPSAoCiAgICAgICAgICAgICAgICAgICAgZiJmYWlsZWQgdG8gZXhlY3V0 - ZSBjb21tYW5kIHtjbWR9LiBPdXRwdXQ6IHtleGVjRXJyLm91dHB1dH0uICIKICAgICAgICAgICAg - ICAgICAgICBmIkNvZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3Rk - ZXJyfSIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3JpdGUo - ZXJyX21zZykKICAgICAgICAgICAgICAgIHJldHVybiBOb25lLCBOb25lLCBGYWxzZSwgIi0xIgoK - ICAgICAgICBqc29ub3V0cHV0ID0ganNvbi5sb2FkcyhvdXRwdXQpCiAgICAgICAgcmV0dXJuICgK - ICAgICAgICAgICAganNvbm91dHB1dFsia2V5cyJdWzBdWyJhY2Nlc3Nfa2V5Il0sCiAgICAgICAg - ICAgIGpzb25vdXRwdXRbImtleXMiXVswXVsic2VjcmV0X2tleSJdLAogICAgICAgICAgICBpbmZv - X2NhcF9zdXBwb3J0ZWQsCiAgICAgICAgICAgICIiLAogICAgICAgICkKCiAgICBkZWYgdmFsaWRh - dGVfcmJkX3Bvb2woc2VsZiwgcG9vbF9uYW1lKToKICAgICAgICBpZiBub3Qgc2VsZi5jbHVzdGVy - LnBvb2xfZXhpc3RzKHBvb2xfbmFtZSk6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1 - cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCBwb29sLCAne3Bvb2xf - bmFtZX0nLCBkb2VzIG5vdCBleGlzdCIKICAgICAgICAgICAgKQoKICAgIGRlZiBpbml0X3JiZF9w - b29sKHNlbGYsIHJiZF9wb29sX25hbWUpOgogICAgICAgIGlmIGlzaW5zdGFuY2Uoc2VsZi5jbHVz - dGVyLCBEdW1teVJhZG9zKToKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgaW9jdHggPSBzZWxm - LmNsdXN0ZXIub3Blbl9pb2N0eChyYmRfcG9vbF9uYW1lKQogICAgICAgIHJiZF9pbnN0ID0gcmJk - LlJCRCgpCiAgICAgICAgcmJkX2luc3QucG9vbF9pbml0KGlvY3R4LCBUcnVlKQoKICAgIGRlZiB2 - YWxpZGF0ZV9yYWRvc19uYW1lc3BhY2Uoc2VsZik6CiAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNl - bGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh - cnNlci5yYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lOgogICAgICAgICAgICByYmRfcG9vbF9uYW1l - ID0gc2VsZi5fYXJnX3BhcnNlci5yYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lCiAgICAgICAgcmFk - b3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UKICAgICAgICBp - ZiByYWRvc19uYW1lc3BhY2UgPT0gIiI6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGlmIHJh - ZG9zX25hbWVzcGFjZS5pc2xvd2VyKCkgPT0gRmFsc2U6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1 - dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByYWRv - cyBOYW1lc3BhY2UsICd7cmFkb3NfbmFtZXNwYWNlfScsICIKICAgICAgICAgICAgICAgIGYiY29u - dGFpbnMgdXBwZXIgY2FzZSIKICAgICAgICAgICAgKQogICAgICAgIHJiZF9pbnN0ID0gcmJkLlJC - RCgpCiAgICAgICAgaW9jdHggPSBzZWxmLmNsdXN0ZXIub3Blbl9pb2N0eChyYmRfcG9vbF9uYW1l - KQogICAgICAgIGlmIHJiZF9pbnN0Lm5hbWVzcGFjZV9leGlzdHMoaW9jdHgsIHJhZG9zX25hbWVz - cGFjZSkgaXMgRmFsc2U6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRp - b24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByYWRvcyBOYW1lc3BhY2UsICd7cmFk - b3NfbmFtZXNwYWNlfScsICIKICAgICAgICAgICAgICAgIGYiaXMgbm90IGZvdW5kIGluIHRoZSBw - b29sICd7cmJkX3Bvb2xfbmFtZX0nIgogICAgICAgICAgICApCgogICAgZGVmIGdldF9vcl9jcmVh - dGVfc3Vidm9sdW1lX2dyb3VwKHNlbGYsIHN1YnZvbHVtZV9ncm91cCwgY2VwaGZzX2ZpbGVzeXN0 - ZW1fbmFtZSk6CiAgICAgICAgY21kID0gWwogICAgICAgICAgICAiY2VwaCIsCiAgICAgICAgICAg - ICJmcyIsCiAgICAgICAgICAgICJzdWJ2b2x1bWVncm91cCIsCiAgICAgICAgICAgICJnZXRwYXRo - IiwKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgc3Vidm9s - dW1lX2dyb3VwLAogICAgICAgIF0KICAgICAgICB0cnk6CiAgICAgICAgICAgIF8gPSBzdWJwcm9j - ZXNzLmNoZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhj - ZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICBjbWQgPSBbCiAg - ICAgICAgICAgICAgICAiY2VwaCIsCiAgICAgICAgICAgICAgICAiZnMiLAogICAgICAgICAgICAg - ICAgInN1YnZvbHVtZWdyb3VwIiwKICAgICAgICAgICAgICAgICJjcmVhdGUiLAogICAgICAgICAg - ICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgICAgIHN1YnZvbHVtZV9n - cm91cCwKICAgICAgICAgICAgXQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBfID0g - c3VicHJvY2Vzcy5jaGVja19vdXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAg - ICAgICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgICAg - ICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAg - IGYic3Vidm9sdW1lIGdyb3VwIHtzdWJ2b2x1bWVfZ3JvdXB9IGlzIG5vdCBhYmxlIHRvIGdldCBj - cmVhdGVkIgogICAgICAgICAgICAgICAgKQoKICAgIGRlZiBwaW5fc3Vidm9sdW1lKAogICAgICAg - IHNlbGYsIHN1YnZvbHVtZV9ncm91cCwgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwgcGluX3R5cGUs - IHBpbl9zZXR0aW5nCiAgICApOgogICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgImNlcGgiLAog - ICAgICAgICAgICAiZnMiLAogICAgICAgICAgICAic3Vidm9sdW1lZ3JvdXAiLAogICAgICAgICAg - ICAicGluIiwKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAg - c3Vidm9sdW1lX2dyb3VwLAogICAgICAgICAgICBwaW5fdHlwZSwKICAgICAgICAgICAgcGluX3Nl - dHRpbmcsCiAgICAgICAgXQogICAgICAgIHRyeToKICAgICAgICAgICAgXyA9IHN1YnByb2Nlc3Mu - Y2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICBleGNlcHQg - c3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlv - bkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmInN1YnZvbHVtZSBncm91cCB7c3Vi - dm9sdW1lX2dyb3VwfSBpcyBub3QgYWJsZSB0byBnZXQgcGlubmVkIgogICAgICAgICAgICApCgog - ICAgZGVmIGdldF9yZ3dfZnNpZChzZWxmLCBiYXNlX3VybCwgdmVyaWZ5KToKICAgICAgICBhY2Nl - c3Nfa2V5ID0gc2VsZi5vdXRfbWFwWyJSR1dfQURNSU5fT1BTX1VTRVJfQUNDRVNTX0tFWSJdCiAg - ICAgICAgc2VjcmV0X2tleSA9IHNlbGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JF - VF9LRVkiXQogICAgICAgIHJnd19lbmRwb2ludCA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBv - aW50CiAgICAgICAgYmFzZV91cmwgPSBiYXNlX3VybCArICI6Ly8iICsgcmd3X2VuZHBvaW50ICsg - Ii9hZG1pbi9pbmZvPyIKICAgICAgICBwYXJhbXMgPSB7ImZvcm1hdCI6ICJqc29uIn0KICAgICAg - ICByZXF1ZXN0X3VybCA9IGJhc2VfdXJsICsgdXJsZW5jb2RlKHBhcmFtcykKCiAgICAgICAgdHJ5 - OgogICAgICAgICAgICByID0gcmVxdWVzdHMuZ2V0KAogICAgICAgICAgICAgICAgcmVxdWVzdF91 - cmwsCiAgICAgICAgICAgICAgICBhdXRoPVMzQXV0aChhY2Nlc3Nfa2V5LCBzZWNyZXRfa2V5LCBy - Z3dfZW5kcG9pbnQpLAogICAgICAgICAgICAgICAgdmVyaWZ5PXZlcmlmeSwKICAgICAgICAgICAg - KQogICAgICAgIGV4Y2VwdCByZXF1ZXN0cy5leGNlcHRpb25zLlRpbWVvdXQ6CiAgICAgICAgICAg - IHN5cy5zdGRlcnIud3JpdGUoCiAgICAgICAgICAgICAgICBmImludmFsaWQgZW5kcG9pbnQ6LCBu - b3QgYWJsZSB0byBjYWxsIGFkbWluLW9wcyBhcGl7cmd3X2VuZHBvaW50fSIKICAgICAgICAgICAg - KQogICAgICAgICAgICByZXR1cm4gIiIsICItMSIKICAgICAgICByMSA9IHIuanNvbigpCiAgICAg - ICAgaWYgcjEgaXMgTm9uZSBvciByMS5nZXQoImluZm8iKSBpcyBOb25lOgogICAgICAgICAgICBz - eXMuc3RkZXJyLndyaXRlKAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmd3IEVuZHBv - aW50LCAne3NlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50fScsIGlzIGludmFsaWQuIgogICAg - ICAgICAgICApCiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAiIiwKICAgICAg - ICAgICAgICAgICItMSIsCiAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIHIxWyJpbmZvIl1b - InN0b3JhZ2VfYmFja2VuZHMiXVswXVsiY2x1c3Rlcl9pZCJdLCAiIgoKICAgIGRlZiB2YWxpZGF0 - ZV9yZ3dfZW5kcG9pbnQoc2VsZiwgaW5mb19jYXBfc3VwcG9ydGVkKToKICAgICAgICAjIGlmIHRo - ZSAnY2x1c3RlcicgaW5zdGFuY2UgaXMgYSBkdW1teSBvbmUsCiAgICAgICAgIyBkb24ndCB0cnkg - dG8gcmVhY2ggb3V0IHRvIHRoZSBlbmRwb2ludAogICAgICAgIGlmIGlzaW5zdGFuY2Uoc2VsZi5j - bHVzdGVyLCBEdW1teVJhZG9zKToKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgIHJnd19lbmRw - b2ludCA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50CgogICAgICAgICMgdmFsaWRhdGUg - cmd3IGVuZHBvaW50IG9ubHkgaWYgaXAgYWRkcmVzcyBpcyBwYXNzZWQKICAgICAgICBpcF90eXBl - ID0gc2VsZi5faW52YWxpZF9lbmRwb2ludChyZ3dfZW5kcG9pbnQpCgogICAgICAgICMgY2hlY2sg - aWYgdGhlIHJndyBlbmRwb2ludCBpcyByZWFjaGFibGUKICAgICAgICBjZXJ0ID0gTm9uZQogICAg - ICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnJnd19za2lwX3RscyBhbmQgc2VsZi52YWxpZGF0 - ZV9yZ3dfZW5kcG9pbnRfdGxzX2NlcnQoKToKICAgICAgICAgICAgY2VydCA9IHNlbGYuX2FyZ19w - YXJzZXIucmd3X3Rsc19jZXJ0X3BhdGgKICAgICAgICBiYXNlX3VybCwgdmVyaWZ5LCBlcnIgPSBz - ZWxmLmVuZHBvaW50X2RpYWwocmd3X2VuZHBvaW50LCBpcF90eXBlLCBjZXJ0PWNlcnQpCiAgICAg - ICAgaWYgZXJyICE9ICIiOgogICAgICAgICAgICByZXR1cm4gIi0xIgoKICAgICAgICAjIGNoZWNr - IGlmIHRoZSByZ3cgZW5kcG9pbnQgYmVsb25ncyB0byB0aGUgc2FtZSBjbHVzdGVyCiAgICAgICAg - IyBvbmx5IGNoZWNrIGlmIGBpbmZvYCBjYXAgaXMgc3VwcG9ydGVkCiAgICAgICAgaWYgaW5mb19j - YXBfc3VwcG9ydGVkOgogICAgICAgICAgICBmc2lkID0gc2VsZi5nZXRfZnNpZCgpCiAgICAgICAg - ICAgIHJnd19mc2lkLCBlcnIgPSBzZWxmLmdldF9yZ3dfZnNpZChiYXNlX3VybCwgdmVyaWZ5KQog - ICAgICAgICAgICBpZiBlcnIgPT0gIi0xIjoKICAgICAgICAgICAgICAgIHJldHVybiAiLTEiCiAg - ICAgICAgICAgIGlmIGZzaWQgIT0gcmd3X2ZzaWQ6CiAgICAgICAgICAgICAgICBzeXMuc3RkZXJy - LndyaXRlKAogICAgICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHJndyBFbmRwb2ludCwg - J3tzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludH0nLCBpcyBpbnZhbGlkLiBXZSBhcmUgdmFs - aWRhdGluZyBieSBjYWxsaW5nIHRoZSBhZG1pbm9wcyBhcGkgdGhyb3VnaCByZ3ctZW5kcG9pbnQg - YW5kIHZhbGlkYXRpbmcgdGhlIGNsdXN0ZXJfaWQgJ3tyZ3dfZnNpZH0nIGlzIGVxdWFsIHRvIHRo - ZSBjZXBoIGNsdXN0ZXIgZnNpZCAne2ZzaWR9JyIKICAgICAgICAgICAgICAgICkKICAgICAgICAg - ICAgICAgIHJldHVybiAiLTEiCgogICAgICAgICMgY2hlY2sgaWYgdGhlIHJndyBlbmRwb2ludCBw - b29sIGV4aXN0CiAgICAgICAgIyBvbmx5IHZhbGlkYXRlIGlmIHJnd19wb29sX3ByZWZpeCBpcyBw - YXNzZWQgZWxzZSBpdCB3aWxsIHRha2UgZGVmYXVsdCB2YWx1ZSBhbmQgd2UgZG9uJ3QgY3JlYXRl - IHRoZXNlIGRlZmF1bHQgcG9vbHMKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29s - X3ByZWZpeCAhPSAiZGVmYXVsdCI6CiAgICAgICAgICAgIHJnd19wb29sc190b192YWxpZGF0ZSA9 - IFsKICAgICAgICAgICAgICAgIGYie3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5y - Z3cubWV0YSIsCiAgICAgICAgICAgICAgICAiLnJndy5yb290IiwKICAgICAgICAgICAgICAgIGYi - e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuY29udHJvbCIsCiAgICAgICAg - ICAgICAgICBmIntzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmxvZyIsCiAg - ICAgICAgICAgIF0KICAgICAgICAgICAgZm9yIF9yZ3dfcG9vbF90b192YWxpZGF0ZSBpbiByZ3df - cG9vbHNfdG9fdmFsaWRhdGU6CiAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5jbHVzdGVyLnBv - b2xfZXhpc3RzKF9yZ3dfcG9vbF90b192YWxpZGF0ZSk6CiAgICAgICAgICAgICAgICAgICAgc3lz - LnN0ZGVyci53cml0ZSgKICAgICAgICAgICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcG9v - bCwgJ3tfcmd3X3Bvb2xfdG9fdmFsaWRhdGV9JywgZG9lcyBub3QgZXhpc3QiCiAgICAgICAgICAg - ICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgIHJldHVybiAiLTEiCgogICAgICAgIHJldHVy - biAiIgoKICAgIGRlZiB2YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKHNlbGYsIHJnd19tdWx0aXNpdGVf - Y29uZmlnX25hbWUsIHJnd19tdWx0aXNpdGVfY29uZmlnKToKICAgICAgICBpZiByZ3dfbXVsdGlz - aXRlX2NvbmZpZyAhPSAiIjoKICAgICAgICAgICAgY21kID0gWwogICAgICAgICAgICAgICAgInJh - ZG9zZ3ctYWRtaW4iLAogICAgICAgICAgICAgICAgcmd3X211bHRpc2l0ZV9jb25maWcsCiAgICAg - ICAgICAgICAgICAiZ2V0IiwKICAgICAgICAgICAgICAgICItLXJndy0iICsgcmd3X211bHRpc2l0 - ZV9jb25maWcsCiAgICAgICAgICAgICAgICByZ3dfbXVsdGlzaXRlX2NvbmZpZ19uYW1lLAogICAg - ICAgICAgICBdCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIF8gPSBzdWJwcm9jZXNz - LmNoZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgICAgIGV4 - Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAg - ICAgICAgZXJyX21zZyA9ICgKICAgICAgICAgICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRl - IGNvbW1hbmQge2NtZH0uIE91dHB1dDoge2V4ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAg - ICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5zdGRl - cnJ9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShl - cnJfbXNnKQogICAgICAgICAgICAgICAgcmV0dXJuICItMSIKICAgICAgICByZXR1cm4gIiIKCiAg - ICBkZWYgY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoc2VsZiwgdmFsdWUpOgogICAg - ICAgIHJldHVybiB2YWx1ZS5zcGxpdCgiLCIpCgogICAgZGVmIHJhaXNlX2V4Y2VwdGlvbl9pZl9h - bnlfdG9wb2xvZ3lfZmxhZ19pc19taXNzaW5nKHNlbGYpOgogICAgICAgIGlmICgKICAgICAgICAg - ICAgKAogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9wb29scyAhPSAi - IgogICAgICAgICAgICAgICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFy - c2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsID09ICIiCiAgICAgICAgICAgICAgICAg - ICAgb3Igc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMgPT0g - IiIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgKQogICAgICAgICAgICBvciAoCiAgICAg - ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVs - ICE9ICIiCiAgICAgICAgICAgICAgICBhbmQgKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2Fy - Z19wYXJzZXIudG9wb2xvZ3lfcG9vbHMgPT0gIiIKICAgICAgICAgICAgICAgICAgICBvciBzZWxm - Ll9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX3ZhbHVlcyA9PSAiIgogICAgICAg - ICAgICAgICAgKQogICAgICAgICAgICApCiAgICAgICAgICAgIG9yICgKICAgICAgICAgICAgICAg - IHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFpbHVyZV9kb21haW5fdmFsdWVzICE9ICIiCiAg - ICAgICAgICAgICAgICBhbmQgKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIu - dG9wb2xvZ3lfcG9vbHMgPT0gIiIKICAgICAgICAgICAgICAgICAgICBvciBzZWxmLl9hcmdfcGFy - c2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsID09ICIiCiAgICAgICAgICAgICAgICAp - CiAgICAgICAgICAgICkKICAgICAgICApOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls - dXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgInByb3ZpZGUgYWxsIHRoZSB0b3BvbG9neSBm - bGFncyAtLXRvcG9sb2d5LXBvb2xzLCAtLXRvcG9sb2d5LWZhaWx1cmUtZG9tYWluLWxhYmVsLCAt - LXRvcG9sb2d5LWZhaWx1cmUtZG9tYWluLXZhbHVlcyIKICAgICAgICAgICAgKQoKICAgIGRlZiB2 - YWxpZGF0ZV90b3BvbG9neV92YWx1ZXMoc2VsZiwgdG9wb2xvZ3lfcG9vbHMsIHRvcG9sb2d5X2Zk - KToKICAgICAgICBpZiBsZW4odG9wb2xvZ3lfcG9vbHMpICE9IGxlbih0b3BvbG9neV9mZCk6CiAg - ICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAg - ICBmIlRoZSBwcm92aWRlZCB0b3BvbG9neSBwb29scywgJ3t0b3BvbG9neV9wb29sc30nLCBhbmQg - IgogICAgICAgICAgICAgICAgZiJ0b3BvbG9neSBmYWlsdXJlIGRvbWFpbiwgJ3t0b3BvbG9neV9m - ZH0nLCIKICAgICAgICAgICAgICAgIGYiYXJlIG9mIGRpZmZlcmVudCBsZW5ndGgsICd7bGVuKHRv - cG9sb2d5X3Bvb2xzKX0nIGFuZCAne2xlbih0b3BvbG9neV9mZCl9JyByZXNwY3RpdmVseSIKICAg - ICAgICAgICAgKQogICAgICAgIHJldHVybgoKICAgIGRlZiB2YWxpZGF0ZV90b3BvbG9neV9yYmRf - cG9vbHMoc2VsZiwgdG9wb2xvZ3lfcmJkX3Bvb2xzKToKICAgICAgICBmb3IgcG9vbCBpbiB0b3Bv - bG9neV9yYmRfcG9vbHM6CiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfcmJkX3Bvb2wocG9vbCkK - CiAgICBkZWYgaW5pdF90b3BvbG9neV9yYmRfcG9vbHMoc2VsZiwgdG9wb2xvZ3lfcmJkX3Bvb2xz - KToKICAgICAgICBmb3IgcG9vbCBpbiB0b3BvbG9neV9yYmRfcG9vbHM6CiAgICAgICAgICAgIHNl - bGYuaW5pdF9yYmRfcG9vbChwb29sKQoKICAgICMgdGhpcyB3aWxsIHJldHVybiB0aGUgZmluYWwg - YXJncyB0aGF0IHNjcmlwdCB1c2VzIHRvIHByb2Nlc3MKICAgICMgdGhlIHByaW9yaXR5IHRvIHNl - dCBhIHBhcnRpY3VsYXIgdmFsdWUgaXMsCiAgICAjIGNvbW1hbmQtbGluZS1hcmdzID4gY29uZmln - LmluaSBmaWxlIHZhbHVlcyA+IGRlZmF1bHQgdmFsdWVzCiAgICBkZWYgZ2V0RmluYWxVc2VkQXJn - cyhzZWxmKToKICAgICAgICBhcmd1bWVudCA9IGYiW0NvbmZpZ3VyYXRpb25zXVxuIgogICAgICAg - IGZvciBhcmcgaW4gdmFycyhzZWxmLl9hcmdfcGFyc2VyKToKICAgICAgICAgICAgaWYgc3RyKGdl - dGF0dHIoc2VsZi5fYXJnX3BhcnNlciwgYXJnKSk6CiAgICAgICAgICAgICAgICAjIHB5dGhvbiB0 - cmVhdHMgZmxhZy1uYW1lIGFzIGZsYWdfbmFtZSBpbnRlcm5hbGx5LCBzbyBjb252ZXJ0aW5nIGJh - Y2sgdG8gZmxhZy1uYW1lLAogICAgICAgICAgICAgICAgIyBzbyB3ZSBjYW4gZ2V0IHRob3NlIHZh - bHVlcyBmcm9tIGNvbmZpZyBmaWxlCiAgICAgICAgICAgICAgICBhcmdWYWx1ZSA9IGFyZy5yZXBs - YWNlKCJfIiwgIi0iKQogICAgICAgICAgICAgICAgIyBkbyBub3QgYWRkIHRoZSBjb25maWctZmls - ZSBmbGFnIGFuZCBhbHNvIG5vdCBhZGQgdGhlIGJvb2xlYW4gZmxhZ3Mgd2hpY2ggYXJlIHNldCB0 - byBGYWxzZQogICAgICAgICAgICAgICAgIyBiZWNhdXNlIGNvbmZpZy5pbmkgZmlsZSB0cmVhdHMg - Ym9vbGVhbiBmbGFncyBhcyBUcnVlIGFsd2F5cwogICAgICAgICAgICAgICAgaWYgKAogICAgICAg - ICAgICAgICAgICAgIGFyZ1ZhbHVlICE9ICJjb25maWctZmlsZSIKICAgICAgICAgICAgICAgICAg - ICBhbmQgZ2V0YXR0cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpICE9IEZhbHNlCiAgICAgICAgICAg - ICAgICApOgogICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50ICs9IGYie2FyZ1ZhbHVlfSA9IHtz - dHIoZ2V0YXR0cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpKX1cbiIKICAgICAgICByZXR1cm4gYXJn - dW1lbnQKCiAgICBkZWYgX2dlbl9vdXRwdXRfbWFwKHNlbGYpOgogICAgICAgIGlmIHNlbGYub3V0 - X21hcDoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgIyBzdXBwb3J0IGxlZ2FjeSBmbGFnIHdp - dGggdXBncmFkZXMKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmNsdXN0ZXJfbmFtZToKICAg - ICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3Bh - cnNlci5jbHVzdGVyX25hbWUKICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25h - bWUgPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZS5sb3dl - cigpCiAgICAgICAgKSAgIyBhbHdheXMgY29udmVydCBjbHVzdGVyIG5hbWUgdG8gbG93ZXJjYXNl - IGNoYXJhY3RlcnMKICAgICAgICBzZWxmLnZhbGlkYXRlX3JiZF9wb29sKHNlbGYuX2FyZ19wYXJz - ZXIucmJkX2RhdGFfcG9vbF9uYW1lKQogICAgICAgIHNlbGYuaW5pdF9yYmRfcG9vbChzZWxmLl9h - cmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZSkKICAgICAgICBzZWxmLnZhbGlkYXRlX3JhZG9z - X25hbWVzcGFjZSgpCiAgICAgICAgc2VsZi5fZXhjbHVkZWRfa2V5cy5hZGQoIks4U19DTFVTVEVS - X05BTUUiKQogICAgICAgIHNlbGYuZ2V0X2NlcGhmc19kYXRhX3Bvb2xfZGV0YWlscygpCiAgICAg - ICAgIyBkb3VibGUgc3RyaW5nIG5lZWRlZCBmb3IgdXBzdHJlYW0gZXhwb3J0cyBvZiBmbGFncwog - ICAgICAgIHNlbGYub3V0X21hcFsiQVJHUyJdID0gZicie3NlbGYuZ2V0RmluYWxVc2VkQXJncygp - fSInCiAgICAgICAgc2VsZi5vdXRfbWFwWyJOQU1FU1BBQ0UiXSA9IHNlbGYuX2FyZ19wYXJzZXIu - bmFtZXNwYWNlCiAgICAgICAgc2VsZi5vdXRfbWFwWyJLOFNfQ0xVU1RFUl9OQU1FIl0gPSBzZWxm - Ll9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tf - RVhURVJOQUxfRlNJRCJdID0gc2VsZi5nZXRfZnNpZCgpCiAgICAgICAgc2VsZi5vdXRfbWFwWyJS - T09LX0VYVEVSTkFMX1VTRVJOQU1FIl0gPSBzZWxmLnJ1bl9hc191c2VyCiAgICAgICAgc2VsZi5v - dXRfbWFwWyJST09LX0VYVEVSTkFMX0NFUEhfTU9OX0RBVEEiXSA9IHNlbGYuZ2V0X2NlcGhfZXh0 - ZXJuYWxfbW9uX2RhdGEoKQogICAgICAgIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5BTF9VU0VS - X1NFQ1JFVCJdID0gc2VsZi5jcmVhdGVfY2hlY2tlcktleSgKICAgICAgICAgICAgImNsaWVudC5o - ZWFsdGhjaGVja2VyIgogICAgICAgICkKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJO - QUxfREFTSEJPQVJEX0xJTksiXSA9IHNlbGYuZ2V0X2NlcGhfZGFzaGJvYXJkX2xpbmsoKQogICAg - ICAgICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX05PREVfU0VDUkVUIl0sCiAg - ICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FIl0sCiAgICAg - ICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNsaWVudC5jc2ktcmJkLW5v - ZGUiKQogICAgICAgICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lP - TkVSX1NFQ1JFVCJdLAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9SQkRfUFJPVklTSU9O - RVJfU0VDUkVUX05BTUUiXSwKICAgICAgICApID0gc2VsZi5jcmVhdGVfY2VwaENTSUtleXJpbmdf - dXNlcigiY2xpZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiKQogICAgICAgIHNlbGYub3V0X21hcFsi - Q0VQSEZTX1BPT0xfTkFNRSJdID0gc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25h - bWUKICAgICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19NRVRBREFUQV9QT09MX05BTUUiXSA9ICgK - ICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfbWV0YWRhdGFfcG9vbF9uYW1lCiAg - ICAgICAgKQogICAgICAgIHNlbGYub3V0X21hcFsiQ0VQSEZTX0ZTX05BTUUiXSA9IHNlbGYuX2Fy - Z19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgIHNlbGYub3V0X21hcFsiUkVT - VFJJQ1RFRF9BVVRIX1BFUk1JU1NJT04iXSA9ICgKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl - ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbgogICAgICAgICkKICAgICAgICBzZWxmLm91dF9t - YXBbIlJBRE9TX05BTUVTUEFDRSJdID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UK - ICAgICAgICBzZWxmLm91dF9tYXBbIlNVQlZPTFVNRV9HUk9VUCJdID0gc2VsZi5fYXJnX3BhcnNl - ci5zdWJ2b2x1bWVfZ3JvdXAKICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9T - RUNSRVQiXSA9ICIiCiAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVS - X1NFQ1JFVCJdID0gIiIKICAgICAgICAjIGNyZWF0ZSBDZXBoRlMgbm9kZSBhbmQgcHJvdmlzaW9u - ZXIga2V5cmluZyBvbmx5IHdoZW4gTURTIGV4aXN0cwogICAgICAgIGlmIHNlbGYub3V0X21hcFsi - Q0VQSEZTX0ZTX05BTUUiXSBhbmQgc2VsZi5vdXRfbWFwWyJDRVBIRlNfUE9PTF9OQU1FIl06CiAg - ICAgICAgICAgICgKICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RF - X1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVf - U0VDUkVUX05BTUUiXSwKICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5n - X3VzZXIoImNsaWVudC5jc2ktY2VwaGZzLW5vZGUiKQogICAgICAgICAgICAoCiAgICAgICAgICAg - ICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUIl0sCiAgICAg - ICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05B - TUUiXSwKICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNs - aWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIikKICAgICAgICAgICAgIyBjcmVhdGUgdGhlIGRl - ZmF1bHQgImNzaSIgc3Vidm9sdW1lZ3JvdXAKICAgICAgICAgICAgc2VsZi5nZXRfb3JfY3JlYXRl - X3N1YnZvbHVtZV9ncm91cCgKICAgICAgICAgICAgICAgICJjc2kiLCBzZWxmLl9hcmdfcGFyc2Vy - LmNlcGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICAgICAgKQogICAgICAgICAgICAjIHBpbiB0 - aGUgZGVmYXVsdCAiY3NpIiBzdWJ2b2x1bWVncm91cAogICAgICAgICAgICBzZWxmLnBpbl9zdWJ2 - b2x1bWUoCiAgICAgICAgICAgICAgICAiY3NpIiwgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls - ZXN5c3RlbV9uYW1lLCAiZGlzdHJpYnV0ZWQiLCAiMSIKICAgICAgICAgICAgKQogICAgICAgICAg - ICBpZiBzZWxmLm91dF9tYXBbIlNVQlZPTFVNRV9HUk9VUCJdOgogICAgICAgICAgICAgICAgc2Vs - Zi5nZXRfb3JfY3JlYXRlX3N1YnZvbHVtZV9ncm91cCgKICAgICAgICAgICAgICAgICAgICBzZWxm - Ll9hcmdfcGFyc2VyLnN1YnZvbHVtZV9ncm91cCwKICAgICAgICAgICAgICAgICAgICBzZWxmLl9h - cmdfcGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgICAgICApCiAgICAg - ICAgICAgICAgICBzZWxmLnBpbl9zdWJ2b2x1bWUoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5f - YXJnX3BhcnNlci5zdWJ2b2x1bWVfZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJn - X3BhcnNlci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lLAogICAgICAgICAgICAgICAgICAgICJkaXN0 - cmlidXRlZCIsCiAgICAgICAgICAgICAgICAgICAgIjEiLAogICAgICAgICAgICAgICAgKQogICAg - ICAgIHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl0gPSAiIgogICAgICAgIHNlbGYub3V0X21h - cFsiTU9OSVRPUklOR19FTkRQT0lOVCJdID0gIiIKICAgICAgICBzZWxmLm91dF9tYXBbIk1PTklU - T1JJTkdfRU5EUE9JTlRfUE9SVCJdID0gIiIKICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNl - ci5za2lwX21vbml0b3JpbmdfZW5kcG9pbnQ6CiAgICAgICAgICAgICgKICAgICAgICAgICAgICAg - IHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVCJdLAogICAgICAgICAgICAgICAgc2Vs - Zi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UX1BPUlQiXSwKICAgICAgICAgICAgKSA9IHNl - bGYuZ2V0X2FjdGl2ZV9hbmRfc3RhbmRieV9tZ3JzKCkKICAgICAgICBzZWxmLm91dF9tYXBbIlJC - RF9QT09MX05BTUUiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAg - ICAgc2VsZi5vdXRfbWFwWyJSQkRfTUVUQURBVEFfRUNfUE9PTF9OQU1FIl0gPSAoCiAgICAgICAg - ICAgIHNlbGYudmFsaWRhdGVfcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZSgpCiAgICAgICAgKQog - ICAgICAgIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfUE9PTFMiXSA9IHNlbGYuX2FyZ19wYXJzZXIu - dG9wb2xvZ3lfcG9vbHMKICAgICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9N - QUlOX0xBQkVMIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFp - bHVyZV9kb21haW5fbGFiZWwKICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9H - WV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXSA9ICgKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl - ci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMKICAgICAgICApCiAgICAgICAgaWYgKAog - ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bvb2xzICE9ICIiCiAgICAgICAg - ICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsICE9 - ICIiCiAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9t - YWluX3ZhbHVlcyAhPSAiIgogICAgICAgICk6CiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfdG9w - b2xvZ3lfdmFsdWVzKAogICAgICAgICAgICAgICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFyYXRl - ZF90b19hcnJheShzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0pLAogICAgICAgICAgICAg - ICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFyYXRlZF90b19hcnJheSgKICAgICAgICAgICAgICAg - ICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlOX1ZBTFVFUyJdCiAgICAg - ICAgICAgICAgICApLAogICAgICAgICAgICApCiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfdG9w - b2xvZ3lfcmJkX3Bvb2xzKAogICAgICAgICAgICAgICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFy - YXRlZF90b19hcnJheShzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0pCiAgICAgICAgICAg - ICkKICAgICAgICAgICAgc2VsZi5pbml0X3RvcG9sb2d5X3JiZF9wb29scygKICAgICAgICAgICAg - ICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoc2VsZi5vdXRfbWFwWyJU - T1BPTE9HWV9QT09MUyJdKQogICAgICAgICAgICApCiAgICAgICAgZWxzZToKICAgICAgICAgICAg - c2VsZi5yYWlzZV9leGNlcHRpb25faWZfYW55X3RvcG9sb2d5X2ZsYWdfaXNfbWlzc2luZygpCgog - ICAgICAgIHNlbGYub3V0X21hcFsiUkdXX1BPT0xfUFJFRklYIl0gPSBzZWxmLl9hcmdfcGFyc2Vy - LnJnd19wb29sX3ByZWZpeAogICAgICAgIHNlbGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl0gPSAi - IgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50OgogICAgICAgICAgICBp - ZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgICAgICBzZWxmLmNyZWF0ZV9y - Z3dfYWRtaW5fb3BzX3VzZXIoKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgaWYg + IGNlcGhmcyAqPSoiLAogICAgICAgICAgICAibWRzIjogImFsbG93IHJ3IiwKICAgICAgICB9CiAg + ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAg + ICAgICAgICAgazhzX2NsdXN0ZXJfbmFtZSA9IHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJf + bmFtZQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1lID09ICIiOgogICAgICAgICAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAi + azhzX2NsdXN0ZXJfbmFtZSBub3QgZm91bmQsIHBsZWFzZSBzZXQgdGhlICctLWs4cy1jbHVzdGVy + LW5hbWUnIGZsYWciCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGNlcGhmc19maWxlc3lz + dGVtID0gc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lCiAgICAgICAgICAg + IGlmIGNlcGhmc19maWxlc3lzdGVtID09ICIiOgogICAgICAgICAgICAgICAgZW50aXR5ID0gZiJ7 + ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFtZX0iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg + ICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1c3Rlcl9uYW1lfS17Y2VwaGZzX2ZpbGVz + eXN0ZW19IgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSBmImFsbG93IHJ3IHRhZyBjZXBo + ZnMgKj17Y2VwaGZzX2ZpbGVzeXN0ZW19IgoKICAgICAgICByZXR1cm4gY2FwcywgZW50aXR5Cgog + ICAgZGVmIGdldF9lbnRpdHkoCiAgICAgICAgc2VsZiwKICAgICAgICBlbnRpdHksCiAgICAgICAg + cmJkX3Bvb2xfbmFtZSwKICAgICAgICBhbGlhc19yYmRfcG9vbF9uYW1lLAogICAgICAgIGs4c19j + bHVzdGVyX25hbWUsCiAgICAgICAgcmFkb3NfbmFtZXNwYWNlLAogICAgKToKICAgICAgICBpZiAo + CiAgICAgICAgICAgIHJiZF9wb29sX25hbWUuY291bnQoIi4iKSAhPSAwCiAgICAgICAgICAgIG9y + IHJiZF9wb29sX25hbWUuY291bnQoIl8iKSAhPSAwCiAgICAgICAgICAgIG9yIGFsaWFzX3JiZF9w + b29sX25hbWUgIT0gIiIKICAgICAgICAgICAgIyBjaGVja2luZyBhbGlhc19yYmRfcG9vbF9uYW1l + IGlzIG5vdCBlbXB0eSBhcyB0aGVyZSBtYXliZSBhIHNwZWNpYWwgY2hhcmFjdGVyIHVzZWQgb3Ro + ZXIgdGhhbiAuIG9yIF8KICAgICAgICApOgogICAgICAgICAgICBpZiBhbGlhc19yYmRfcG9vbF9u + YW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv + bigKICAgICAgICAgICAgICAgICAgICAicGxlYXNlIHNldCB0aGUgJy0tYWxpYXMtcmJkLWRhdGEt + cG9vbC1uYW1lJyBmbGFnIGFzIHRoZSByYmQgZGF0YSBwb29sIG5hbWUgY29udGFpbnMgJy4nIG9y + ICdfJyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAg + YWxpYXNfcmJkX3Bvb2xfbmFtZS5jb3VudCgiLiIpICE9IDAKICAgICAgICAgICAgICAgIG9yIGFs + aWFzX3JiZF9wb29sX25hbWUuY291bnQoIl8iKSAhPSAwCiAgICAgICAgICAgICk6CiAgICAgICAg + ICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAg + ICAgICInLS1hbGlhcy1yYmQtZGF0YS1wb29sLW5hbWUnIGZsYWcgdmFsdWUgc2hvdWxkIG5vdCBj + b250YWluICcuJyBvciAnXyciCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVudGl0eSA9 + IGYie2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXthbGlhc19yYmRfcG9vbF9uYW1lfSIKICAg + ICAgICBlbHNlOgogICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1c3Rlcl9u + YW1lfS17cmJkX3Bvb2xfbmFtZX0iCgogICAgICAgIGlmIHJhZG9zX25hbWVzcGFjZToKICAgICAg + ICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17cmFkb3NfbmFtZXNwYWNlfSIKICAgICAgICByZXR1 + cm4gZW50aXR5CgogICAgZGVmIGdldF9yYmRfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KHNl + bGYpOgogICAgICAgIGVudGl0eSA9ICJjbGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIKICAgICAg + ICBjYXBzID0gewogICAgICAgICAgICAibW9uIjogInByb2ZpbGUgcmJkLCBhbGxvdyBjb21tYW5k + ICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJtZ3IiOiAiYWxsb3cgcnciLAogICAgICAg + ICAgICAib3NkIjogInByb2ZpbGUgcmJkIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJn + X3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgcmJkX3Bvb2xf + bmFtZSA9IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGFs + aWFzX3JiZF9wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLmFsaWFzX3JiZF9kYXRhX3Bvb2xf + bmFtZQogICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNf + Y2x1c3Rlcl9uYW1lCiAgICAgICAgICAgIHJhZG9zX25hbWVzcGFjZSA9IHNlbGYuX2FyZ19wYXJz + ZXIucmFkb3NfbmFtZXNwYWNlCiAgICAgICAgICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAg + ICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAg + ICAgICAgICAgICJtYW5kYXRvcnkgZmxhZyBub3QgZm91bmQsIHBsZWFzZSBzZXQgdGhlICctLXJi + ZC1kYXRhLXBvb2wtbmFtZScgZmxhZyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYg + azhzX2NsdXN0ZXJfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBmbGFnIG5vdCBm + b3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAgICAgICAg + ICAgICAgICkKICAgICAgICAgICAgZW50aXR5ID0gc2VsZi5nZXRfZW50aXR5KAogICAgICAgICAg + ICAgICAgZW50aXR5LAogICAgICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSwKICAgICAgICAgICAg + ICAgIGFsaWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1l + LAogICAgICAgICAgICAgICAgcmFkb3NfbmFtZXNwYWNlLAogICAgICAgICAgICApCiAgICAgICAg + ICAgIGlmIHJhZG9zX25hbWVzcGFjZSAhPSAiIjoKICAgICAgICAgICAgICAgIGNhcHNbIm9zZCJd + ID0gKAogICAgICAgICAgICAgICAgICAgIGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFt + ZX0gbmFtZXNwYWNlPXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgICAgICAgICAgKQogICAgICAg + ICAgICBlbHNlOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSBmInByb2ZpbGUgcmJkIHBv + b2w9e3JiZF9wb29sX25hbWV9IgoKICAgICAgICByZXR1cm4gY2FwcywgZW50aXR5CgogICAgZGVm + IGdldF9yYmRfbm9kZV9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50aXR5ID0gImNs + aWVudC5jc2ktcmJkLW5vZGUiCiAgICAgICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJw + cm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLAogICAgICAgICAgICAi + b3NkIjogInByb2ZpbGUgcmJkIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl + ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSA9 + IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGFsaWFzX3Ji + ZF9wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLmFsaWFzX3JiZF9kYXRhX3Bvb2xfbmFtZQog + ICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rl + cl9uYW1lCiAgICAgICAgICAgIHJhZG9zX25hbWVzcGFjZSA9IHNlbGYuX2FyZ19wYXJzZXIucmFk + b3NfbmFtZXNwYWNlCiAgICAgICAgICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAgICAgICAg + ICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAg + ICAgICJtYW5kYXRvcnkgZmxhZyBub3QgZm91bmQsIHBsZWFzZSBzZXQgdGhlICctLXJiZC1kYXRh + LXBvb2wtbmFtZScgZmxhZyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgazhzX2Ns + dXN0ZXJfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVF + eGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBmbGFnIG5vdCBmb3VuZCwg + cGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAgICAgICAgICAgICAg + ICkKICAgICAgICAgICAgZW50aXR5ID0gc2VsZi5nZXRfZW50aXR5KAogICAgICAgICAgICAgICAg + ZW50aXR5LAogICAgICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSwKICAgICAgICAgICAgICAgIGFs + aWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1lLAogICAg + ICAgICAgICAgICAgcmFkb3NfbmFtZXNwYWNlLAogICAgICAgICAgICApCiAgICAgICAgICAgIGlm + IHJhZG9zX25hbWVzcGFjZSAhPSAiIjoKICAgICAgICAgICAgICAgIGNhcHNbIm9zZCJdID0gKAog + ICAgICAgICAgICAgICAgICAgIGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFtZX0gbmFt + ZXNwYWNlPXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBl + bHNlOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSBmInByb2ZpbGUgcmJkIHBvb2w9e3Ji + ZF9wb29sX25hbWV9IgoKICAgICAgICByZXR1cm4gY2FwcywgZW50aXR5CgogICAgZGVmIGdldF9k + ZWZhdWx0VXNlcl9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50aXR5ID0gc2VsZi5y + dW5fYXNfdXNlcgogICAgICAgIGNhcHMgPSB7CiAgICAgICAgICAgICJtb24iOiAiYWxsb3cgciwg + YWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLAogICAg + ICAgICAgICAibWdyIjogImFsbG93IGNvbW1hbmQgY29uZmlnIiwKICAgICAgICAgICAgIm9zZCI6 + IGYicHJvZmlsZSByYmQtcmVhZC1vbmx5LCBhbGxvdyByd3ggcG9vbD17c2VsZi5fYXJnX3BhcnNl + ci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290LCBhbGxv + dyBydyBwb29sPXtzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmNvbnRyb2ws + IGFsbG93IHJ4IHBvb2w9e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cubG9n + LCBhbGxvdyB4IHBvb2w9e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuYnVj + a2V0cy5pbmRleCIsCiAgICAgICAgICAgICJtZHMiOiAiYWxsb3cgKiIsCiAgICAgICAgfQoKICAg + ICAgICByZXR1cm4gY2FwcywgZW50aXR5CgogICAgZGVmIGdldF9jYXBzX2FuZF9lbnRpdHkoc2Vs + ZiwgdXNlcl9uYW1lKToKICAgICAgICBpZiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIi + IGluIHVzZXJfbmFtZToKICAgICAgICAgICAgaWYgImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv + bmVyIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJlc3Ry + aWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQogICAgICAgICAgICByZXR1cm4gc2VsZi5nZXRf + Y2VwaGZzX3Byb3Zpc2lvbmVyX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAgaWYgImNsaWVudC5j + c2ktY2VwaGZzLW5vZGUiIGluIHVzZXJfbmFtZToKICAgICAgICAgICAgaWYgImNsaWVudC5jc2kt + Y2VwaGZzLW5vZGUiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJz + ZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAgIHJldHVybiBz + ZWxmLmdldF9jZXBoZnNfbm9kZV9jYXBzX2FuZF9lbnRpdHkoKQogICAgICAgIGlmICJjbGllbnQu + Y3NpLXJiZC1wcm92aXNpb25lciIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAiY2xpZW50 + LmNzaS1yYmQtcHJvdmlzaW9uZXIiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYu + X2FyZ19wYXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAg + IHJldHVybiBzZWxmLmdldF9yYmRfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KCkKICAgICAg + ICBpZiAiY2xpZW50LmNzaS1yYmQtbm9kZSIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAi + Y2xpZW50LmNzaS1yYmQtbm9kZSIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2VsZi5f + YXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAgICAg + cmV0dXJuIHNlbGYuZ2V0X3JiZF9ub2RlX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAgaWYgImNs + aWVudC5oZWFsdGhjaGVja2VyIiBpbiB1c2VyX25hbWU6CiAgICAgICAgICAgIGlmICJjbGllbnQu + aGVhbHRoY2hlY2tlciIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3Bh + cnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAgICAgcmV0dXJu + IHNlbGYuZ2V0X2RlZmF1bHRVc2VyX2NhcHNfYW5kX2VudGl0eSgpCgogICAgICAgIHJhaXNlIEV4 + ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgIGYibm8gdXNlciBmb3VuZCB3aXRo + IHVzZXJfbmFtZToge3VzZXJfbmFtZX0sICIKICAgICAgICAgICAgImdldF9jYXBzX2FuZF9lbnRp + dHkgY29tbWFuZCBmYWlsZWQuXG4iCiAgICAgICAgKQoKICAgIGRlZiBjcmVhdGVfY2VwaENTSUtl + eXJpbmdfdXNlcihzZWxmLCB1c2VyKToKICAgICAgICAiIiIKICAgICAgICBjb21tYW5kOiBjZXBo + IGF1dGggZ2V0LW9yLWNyZWF0ZSBjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciBtb24gJ2Fs + bG93IHInIG1nciAnYWxsb3cgcncnIG9zZCAnYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0q + JwogICAgICAgICIiIgogICAgICAgIGNhcHMsIGVudGl0eSA9IHNlbGYuZ2V0X2NhcHNfYW5kX2Vu + dGl0eSh1c2VyKQogICAgICAgIGNtZF9qc29uID0gewogICAgICAgICAgICAicHJlZml4IjogImF1 + dGggZ2V0LW9yLWNyZWF0ZSIsCiAgICAgICAgICAgICJlbnRpdHkiOiBlbnRpdHksCiAgICAgICAg + ICAgICJjYXBzIjogW2NhcCBmb3IgY2FwX2xpc3QgaW4gbGlzdChjYXBzLml0ZW1zKCkpIGZvciBj + YXAgaW4gY2FwX2xpc3RdLAogICAgICAgICAgICAiZm9ybWF0IjogImpzb24iLAogICAgICAgIH0K + CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4g + KAogICAgICAgICAgICAgICAgc2VsZi5kcnlfcnVuKAogICAgICAgICAgICAgICAgICAgICJjZXBo + ICIKICAgICAgICAgICAgICAgICAgICArIGNtZF9qc29uWyJwcmVmaXgiXQogICAgICAgICAgICAg + ICAgICAgICsgIiAiCiAgICAgICAgICAgICAgICAgICAgKyBjbWRfanNvblsiZW50aXR5Il0KICAg + ICAgICAgICAgICAgICAgICArICIgIgogICAgICAgICAgICAgICAgICAgICsgIiAiLmpvaW4oY21k + X2pzb25bImNhcHMiXSkKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAiIiwKICAg + ICAgICAgICAgKQogICAgICAgICMgY2hlY2sgaWYgdXNlciBhbHJlYWR5IGV4aXN0CiAgICAgICAg + dXNlcl9rZXkgPSBzZWxmLmNoZWNrX3VzZXJfZXhpc3QoZW50aXR5KQogICAgICAgIGlmIHVzZXJf + a2V5ICE9ICIiOgogICAgICAgICAgICByZXR1cm4gdXNlcl9rZXksIGYie2VudGl0eS5zcGxpdCgn + LicsIDEpWzFdfSIKICAgICAgICAgICAgIyBlbnRpdHkuc3BsaXQoJy4nLDEpWzFdIHRvIHJlbmFt + ZSBlbnRpdHkoY2xpZW50LmNzaS1yYmQtbm9kZSkgYXMgY3NpLXJiZC1ub2RlCgogICAgICAgIHJl + dF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRf + anNvbikKICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAg + ICAgIGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJh + aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGdl + dC1vci1jcmVhdGUge3VzZXJ9JyBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgIGYi + RXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJ + U1R9IgogICAgICAgICAgICApCiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0p + LCBmIntlbnRpdHkuc3BsaXQoJy4nLCAxKVsxXX0iCiAgICAgICAgIyBlbnRpdHkuc3BsaXQoJy4n + LDEpWzFdIHRvIHJlbmFtZSBlbnRpdHkoY2xpZW50LmNzaS1yYmQtbm9kZSkgYXMgY3NpLXJiZC1u + b2RlCgogICAgZGVmIGdldF9jZXBoZnNfZGF0YV9wb29sX2RldGFpbHMoc2VsZik6CiAgICAgICAg + Y21kX2pzb24gPSB7InByZWZpeCI6ICJmcyBscyIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAg + aWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2VsZi5kcnlf + cnVuKCJjZXBoICIgKyBjbWRfanNvblsicHJlZml4Il0pCiAgICAgICAgcmV0X3ZhbCwganNvbl9v + dXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAg + ICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0dGVtcHQsIHJlcG9ydCBhbiBlcnJvcgog + ICAgICAgIGlmIHJldF92YWwgIT0gMDoKICAgICAgICAgICAgIyBpZiBmcyBhbmQgZGF0YV9wb29s + IGFyZ3VtZW50cyBhcmUgbm90IHNldCwgc2lsZW50bHkgcmV0dXJuCiAgICAgICAgICAgIGlmICgK + ICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSA9 + PSAiIgogICAgICAgICAgICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9v + bF9uYW1lID09ICIiCiAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICByZXR1cm4KICAgICAg + ICAgICAgIyBpZiB1c2VyIGhhcyBwcm92aWRlZCBhbnkgb2YgdGhlCiAgICAgICAgICAgICMgJy0t + Y2VwaGZzLWZpbGVzeXN0ZW0tbmFtZScgb3IgJy0tY2VwaGZzLWRhdGEtcG9vbC1uYW1lJyBhcmd1 + bWVudHMsCiAgICAgICAgICAgICMgcmFpc2UgYW4gZXhjZXB0aW9uIGFzIHdlIGFyZSB1bmFibGUg + dG8gdmVyaWZ5IHRoZSBhcmdzCiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl + cHRpb24oCiAgICAgICAgICAgICAgICBmIidmcyBscycgY2VwaCBjYWxsIGZhaWxlZCB3aXRoIGVy + cm9yOiB7ZXJyX21zZ30iCiAgICAgICAgICAgICkKCiAgICAgICAgbWF0Y2hpbmdfanNvbl9vdXQg + PSB7fQogICAgICAgICMgaWYgJy0tY2VwaGZzLWZpbGVzeXN0ZW0tbmFtZScgYXJndW1lbnQgaXMg + cHJvdmlkZWQsCiAgICAgICAgIyBjaGVjayB3aGV0aGVyIHRoZSBwcm92aWRlZCBmaWxlc3lzdGVt + LW5hbWUgZXhpc3RzIG9yIG5vdAogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2Zp + bGVzeXN0ZW1fbmFtZToKICAgICAgICAgICAgIyBnZXQgdGhlIG1hdGNoaW5nIGxpc3QKICAgICAg + ICAgICAgbWF0Y2hpbmdfanNvbl9vdXRfbGlzdCA9IFsKICAgICAgICAgICAgICAgIG1hdGNoZWQK + ICAgICAgICAgICAgICAgIGZvciBtYXRjaGVkIGluIGpzb25fb3V0CiAgICAgICAgICAgICAgICBp + ZiBzdHIobWF0Y2hlZFsibmFtZSJdKSA9PSBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19maWxlc3lz + dGVtX25hbWUKICAgICAgICAgICAgXQogICAgICAgICAgICAjIHVuYWJsZSB0byBmaW5kIGEgbWF0 + Y2hpbmcgZnMtbmFtZSwgcmFpc2UgYW4gZXJyb3IKICAgICAgICAgICAgaWYgbGVuKG1hdGNoaW5n + X2pzb25fb3V0X2xpc3QpID09IDA6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls + dXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgIGYiRmlsZXN5c3RlbSBwcm92aWRlZCwg + J3tzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWV9JywgIgogICAgICAgICAg + ICAgICAgICAgIGYiaXMgbm90IGZvdW5kIGluIHRoZSBmcy1saXN0OiB7W3N0cih4WyduYW1lJ10p + IGZvciB4IGluIGpzb25fb3V0XX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIG1hdGNo + aW5nX2pzb25fb3V0ID0gbWF0Y2hpbmdfanNvbl9vdXRfbGlzdFswXQogICAgICAgICMgaWYgY2Vw + aGZzIGZpbGVzeXN0ZW0gbmFtZSBpcyBub3QgcHJvdmlkZWQsCiAgICAgICAgIyB0cnkgdG8gZ2V0 + IGEgZGVmYXVsdCBmcyBuYW1lIGJ5IGRvaW5nIHRoZSBmb2xsb3dpbmcKICAgICAgICBlbHNlOgog + ICAgICAgICAgICAjIGEuIGNoZWNrIGlmIHRoZXJlIGlzIG9ubHkgb25lIGZpbGVzeXN0ZW0gaXMg + cHJlc2VudAogICAgICAgICAgICBpZiBsZW4oanNvbl9vdXQpID09IDE6CiAgICAgICAgICAgICAg + ICBtYXRjaGluZ19qc29uX291dCA9IGpzb25fb3V0WzBdCiAgICAgICAgICAgICMgYi4gb3IgZWxz + ZSwgY2hlY2sgaWYgZGF0YV9wb29sIG5hbWUgaXMgcHJvdmlkZWQKICAgICAgICAgICAgZWxpZiBz + ZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFtZToKICAgICAgICAgICAgICAgICMg + YW5kIGlmIHByZXNlbnQsIGNoZWNrIHdoZXRoZXIgdGhlcmUgZXhpc3RzIGEgZnMgd2hpY2ggaGFz + IHRoZSBkYXRhX3Bvb2wKICAgICAgICAgICAgICAgIGZvciBlYWNoSiBpbiBqc29uX291dDoKICAg + ICAgICAgICAgICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFt + ZSBpbiBlYWNoSlsiZGF0YV9wb29scyJdOgogICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGlu + Z19qc29uX291dCA9IGVhY2hKCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAg + ICAgICAgICAjIGlmIHRoZXJlIGlzIG5vIG1hdGNoaW5nIGZzIGV4aXN0cywgdGhhdCBtZWFucyBw + cm92aWRlZCBkYXRhX3Bvb2wgbmFtZSBpcyBpbnZhbGlkCiAgICAgICAgICAgICAgICBpZiBub3Qg + bWF0Y2hpbmdfanNvbl9vdXQ6CiAgICAgICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFp + bHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAgICAgZiJQcm92aWRlZCBkYXRhX3Bv + b2wgbmFtZSwge3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lfSwiCiAgICAg + ICAgICAgICAgICAgICAgICAgICIgZG9lcyBub3QgZXhpc3RzIgogICAgICAgICAgICAgICAgICAg + ICkKICAgICAgICAgICAgIyBjLiBpZiBub3RoaW5nIGlzIHNldCBhbmQgY291bGRuJ3QgZmluZCBh + IGRlZmF1bHQsCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAjIGp1c3QgcmV0dXJu + IHNpbGVudGx5CiAgICAgICAgICAgICAgICByZXR1cm4KCiAgICAgICAgaWYgbWF0Y2hpbmdfanNv + bl9vdXQ6CiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFt + ZSA9IHN0cihtYXRjaGluZ19qc29uX291dFsibmFtZSJdKQogICAgICAgICAgICBzZWxmLl9hcmdf + cGFyc2VyLmNlcGhmc19tZXRhZGF0YV9wb29sX25hbWUgPSBzdHIoCiAgICAgICAgICAgICAgICBt + YXRjaGluZ19qc29uX291dFsibWV0YWRhdGFfcG9vbCJdCiAgICAgICAgICAgICkKCiAgICAgICAg + aWYgaXNpbnN0YW5jZShtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdLCBsaXN0KToKICAg + ICAgICAgICAgIyBpZiB0aGUgdXNlciBoYXMgYWxyZWFkeSBwcm92aWRlZCBkYXRhLXBvb2wtbmFt + ZSwKICAgICAgICAgICAgIyB0aHJvdWdoIC0tY2VwaGZzLWRhdGEtcG9vbC1uYW1lCiAgICAgICAg + ICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lOgogICAgICAgICAg + ICAgICAgIyBpZiB0aGUgcHJvdmlkZWQgbmFtZSBpcyBub3QgbWF0Y2hpbmcgd2l0aCB0aGUgb25l + IGluIHRoZSBsaXN0CiAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICAgc2Vs + Zi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgICAgICAgICBu + b3QgaW4gbWF0Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXQogICAgICAgICAgICAgICAgKToK + ICAgICAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAg + ICAgICAgICAgICAgICAgICAgICBmIlByb3ZpZGVkIGRhdGEtcG9vbC1uYW1lOiAne3NlbGYuX2Fy + Z19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lfScsICIKICAgICAgICAgICAgICAgICAgICAg + ICAgImRvZXNuJ3QgbWF0Y2ggZnJvbSB0aGUgZGF0YS1wb29scyBsaXN0OiAiCiAgICAgICAgICAg + ICAgICAgICAgICAgIGYie1tzdHIoeCkgZm9yIHggaW4gbWF0Y2hpbmdfanNvbl9vdXRbJ2RhdGFf + cG9vbHMnXV19IgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIyBpZiBkYXRhX3Bv + b2wgbmFtZSBpcyBub3QgcHJvdmlkZWQsCiAgICAgICAgICAgICMgdGhlbiB0cnkgdG8gZmluZCBh + IGRlZmF1bHQgZGF0YSBwb29sIG5hbWUKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAg + ICMgaWYgbm8gZGF0YV9wb29scyBleGlzdCwgc2lsZW50bHkgcmV0dXJuCiAgICAgICAgICAgICAg + ICBpZiBsZW4obWF0Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXSkgPT0gMDoKICAgICAgICAg + ICAgICAgICAgICByZXR1cm4KICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZz + X2RhdGFfcG9vbF9uYW1lID0gc3RyKAogICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nX2pzb25f + b3V0WyJkYXRhX3Bvb2xzIl1bMF0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIyBpZiB0 + aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSAnZGF0YV9wb29scycgZXhpc3QsCiAgICAgICAgICAgICMg + dGhlbiB3YXJuIHRoZSB1c2VyIHRoYXQgd2UgYXJlIHVzaW5nIHRoZSBzZWxlY3RlZCBuYW1lCiAg + ICAgICAgICAgIGlmIGxlbihtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdKSA+IDE6CiAg + ICAgICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgICAgICAiV0FSTklORzogTXVsdGlw + bGUgZGF0YSBwb29scyBkZXRlY3RlZDogIgogICAgICAgICAgICAgICAgICAgIGYie1tzdHIoeCkg + Zm9yIHggaW4gbWF0Y2hpbmdfanNvbl9vdXRbJ2RhdGFfcG9vbHMnXV19XG4iCiAgICAgICAgICAg + ICAgICAgICAgZiJVc2luZyB0aGUgZGF0YS1wb29sOiAne3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZz + X2RhdGFfcG9vbF9uYW1lfSdcbiIKICAgICAgICAgICAgICAgICkKCiAgICBkZWYgY3JlYXRlX2No + ZWNrZXJLZXkoc2VsZiwgdXNlcik6CiAgICAgICAgY2FwcywgZW50aXR5ID0gc2VsZi5nZXRfY2Fw + c19hbmRfZW50aXR5KHVzZXIpCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJwcmVm + aXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIiwKICAgICAgICAgICAgImVudGl0eSI6IGVudGl0eSwK + ICAgICAgICAgICAgImNhcHMiOiBbY2FwIGZvciBjYXBfbGlzdCBpbiBsaXN0KGNhcHMuaXRlbXMo + KSkgZm9yIGNhcCBpbiBjYXBfbGlzdF0sCiAgICAgICAgICAgICJmb3JtYXQiOiAianNvbiIsCiAg + ICAgICAgfQoKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAg + IHJldHVybiBzZWxmLmRyeV9ydW4oCiAgICAgICAgICAgICAgICAiY2VwaCAiCiAgICAgICAgICAg + ICAgICArIGNtZF9qc29uWyJwcmVmaXgiXQogICAgICAgICAgICAgICAgKyAiICIKICAgICAgICAg + ICAgICAgICsgY21kX2pzb25bImVudGl0eSJdCiAgICAgICAgICAgICAgICArICIgIgogICAgICAg + ICAgICAgICAgKyAiICIuam9pbihjbWRfanNvblsiY2FwcyJdKQogICAgICAgICAgICApCiAgICAg + ICAgIyBjaGVjayBpZiB1c2VyIGFscmVhZHkgZXhpc3QKICAgICAgICB1c2VyX2tleSA9IHNlbGYu + Y2hlY2tfdXNlcl9leGlzdChlbnRpdHkpCiAgICAgICAgaWYgdXNlcl9rZXkgIT0gIiI6CiAgICAg + ICAgICAgIHJldHVybiB1c2VyX2tleQoKICAgICAgICByZXRfdmFsLCBqc29uX291dCwgZXJyX21z + ZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgIyBpZiB0aGVy + ZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwKICAgICAgICBpZiByZXRfdmFsICE9IDAgb3Ig + bGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj + ZXB0aW9uKAogICAgICAgICAgICAgICAgZiInYXV0aCBnZXQtb3ItY3JlYXRlIHtzZWxmLnJ1bl9h + c191c2VyfScgY29tbWFuZCBmYWlsZWRcbiIKICAgICAgICAgICAgICAgIGYiRXJyb3I6IHtlcnJf + bXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJU1R9IgogICAgICAg + ICAgICApCiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0pCgogICAgZGVmIGdl + dF9jZXBoX2Rhc2hib2FyZF9saW5rKHNlbGYpOgogICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgi + OiAibWdyIHNlcnZpY2VzIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICBpZiBzZWxmLl9hcmdf + cGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiBzZWxmLmRyeV9ydW4oImNlcGggIiAr + IGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRfdmFsLCBqc29uX291dCwgXyA9IHNlbGYu + X2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1 + bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwKICAgICAgICBpZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25f + b3V0KSA9PSAwOgogICAgICAgICAgICByZXR1cm4gTm9uZQogICAgICAgIGlmICJkYXNoYm9hcmQi + IG5vdCBpbiBqc29uX291dDoKICAgICAgICAgICAgcmV0dXJuIE5vbmUKICAgICAgICByZXR1cm4g + anNvbl9vdXRbImRhc2hib2FyZCJdCgogICAgZGVmIGNyZWF0ZV9yZ3dfYWRtaW5fb3BzX3VzZXIo + c2VsZik6CiAgICAgICAgY21kID0gWwogICAgICAgICAgICAicmFkb3Nndy1hZG1pbiIsCiAgICAg + ICAgICAgICJ1c2VyIiwKICAgICAgICAgICAgImNyZWF0ZSIsCiAgICAgICAgICAgICItLXVpZCIs + CiAgICAgICAgICAgIHNlbGYuRVhURVJOQUxfUkdXX0FETUlOX09QU19VU0VSX05BTUUsCiAgICAg + ICAgICAgICItLWRpc3BsYXktbmFtZSIsCiAgICAgICAgICAgICJSb29rIFJHVyBBZG1pbiBPcHMg + dXNlciIsCiAgICAgICAgICAgICItLWNhcHMiLAogICAgICAgICAgICAiYnVja2V0cz0qO3VzZXJz + PSo7dXNhZ2U9cmVhZDttZXRhZGF0YT1yZWFkO3pvbmU9cmVhZCIsCiAgICAgICAgICAgICItLXJn + dy1yZWFsbSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUsCiAg + ICAgICAgICAgICItLXJndy16b25lZ3JvdXAiLAogICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2Vy + LnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmUiLAogICAgICAgICAg + ICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lX25hbWUsCiAgICAgICAgXQogICAgICAgIGlmIHNl + bGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigi + Y2VwaCAiICsgIiAiLmpvaW4oY21kKSkKICAgICAgICB0cnk6CiAgICAgICAgICAgIG91dHB1dCA9 + IHN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAg + ICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhlY0VycjoKICAg + ICAgICAgICAgIyBpZiB0aGUgdXNlciBhbHJlYWR5IGV4aXN0cywgd2UganVzdCBxdWVyeSBpdAog + ICAgICAgICAgICBpZiBleGVjRXJyLnJldHVybmNvZGUgPT0gZXJybm8uRUVYSVNUOgogICAgICAg + ICAgICAgICAgY21kID0gWwogICAgICAgICAgICAgICAgICAgICJyYWRvc2d3LWFkbWluIiwKICAg + ICAgICAgICAgICAgICAgICAidXNlciIsCiAgICAgICAgICAgICAgICAgICAgImluZm8iLAogICAg + ICAgICAgICAgICAgICAgICItLXVpZCIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5FWFRFUk5B + TF9SR1dfQURNSU5fT1BTX1VTRVJfTkFNRSwKICAgICAgICAgICAgICAgICAgICAiLS1yZ3ctcmVh + bG0iLAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUs + CiAgICAgICAgICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAgICAgICAgICAgICAg + ICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfem9uZWdyb3VwX25hbWUsCiAgICAgICAgICAgICAgICAg + ICAgIi0tcmd3LXpvbmUiLAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3 + X3pvbmVfbmFtZSwKICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICAgIHRyeToKICAgICAg + ICAgICAgICAgICAgICBvdXRwdXQgPSBzdWJwcm9jZXNzLmNoZWNrX291dHB1dChjbWQsIHN0ZGVy + cj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgICAgICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxs + ZWRQcm9jZXNzRXJyb3IgYXMgZXhlY0VycjoKICAgICAgICAgICAgICAgICAgICBlcnJfbXNnID0g + KAogICAgICAgICAgICAgICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRlIGNvbW1hbmQge2Nt + ZH0uIE91dHB1dDoge2V4ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAgICAgICAgICAgICBm + IkNvZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3RkZXJyfSIKICAg + ICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShl + cnJfbXNnKQogICAgICAgICAgICAgICAgICAgIHJldHVybiBOb25lLCBOb25lLCBGYWxzZSwgIi0x + IgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZXJyX21zZyA9ICgKICAgICAgICAg + ICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRlIGNvbW1hbmQge2NtZH0uIE91dHB1dDoge2V4 + ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAgICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0 + dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5zdGRlcnJ9IgogICAgICAgICAgICAgICAgKQogICAg + ICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShlcnJfbXNnKQogICAgICAgICAgICAgICAgcmV0 + dXJuIE5vbmUsIE5vbmUsIEZhbHNlLCAiLTEiCgogICAgICAgICMgc2VwYXJhdGVseSBhZGQgaW5m + bz1yZWFkIGNhcHMgZm9yIHJndy1lbmRwb2ludCBpcCB2YWxpZGF0aW9uCiAgICAgICAgaW5mb19j + YXBfc3VwcG9ydGVkID0gVHJ1ZQogICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgInJhZG9zZ3ct + YWRtaW4iLAogICAgICAgICAgICAiY2FwcyIsCiAgICAgICAgICAgICJhZGQiLAogICAgICAgICAg + ICAiLS11aWQiLAogICAgICAgICAgICBzZWxmLkVYVEVSTkFMX1JHV19BRE1JTl9PUFNfVVNFUl9O + QU1FLAogICAgICAgICAgICAiLS1jYXBzIiwKICAgICAgICAgICAgImluZm89cmVhZCIsCiAgICAg + ICAgICAgICItLXJndy1yZWFsbSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Jl + YWxtX25hbWUsCiAgICAgICAgICAgICItLXJndy16b25lZ3JvdXAiLAogICAgICAgICAgICBzZWxm + Ll9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmUi + LAogICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lX25hbWUsCiAgICAgICAgXQog + ICAgICAgIHRyeToKICAgICAgICAgICAgb3V0cHV0ID0gc3VicHJvY2Vzcy5jaGVja19vdXRwdXQo + Y21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9jZXNzLkNh + bGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAgICAjIGlmIHRoZSBjZXBoIHZl + cnNpb24gbm90IHN1cHBvcnRlZCBmb3IgYWRkaW5nIGBpbmZvPXJlYWRgIGNhcChyZ3dfdmFsaWRh + dGlvbikKICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAgImNvdWxkIG5vdCBhZGQgY2Fw + czogdW5hYmxlIHRvIGFkZCBjYXBzOiBpbmZvPXJlYWRcbiIKICAgICAgICAgICAgICAgIGluIGV4 + ZWNFcnIuc3RkZXJyLmRlY29kZSgidXRmLTgiKQogICAgICAgICAgICAgICAgYW5kIGV4ZWNFcnIu + cmV0dXJuY29kZSA9PSAyNDQKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIGluZm9fY2Fw + X3N1cHBvcnRlZCA9IEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlcnJf + bXNnID0gKAogICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUgY29tbWFuZCB7 + Y21kfS4gT3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAgICAgICAgZiJD + b2RlOiB7ZXhlY0Vyci5yZXR1cm5jb2RlfS4gRXJyb3I6IHtleGVjRXJyLnN0ZGVycn0iCiAgICAg + ICAgICAgICAgICApCiAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycl9tc2cpCiAg + ICAgICAgICAgICAgICByZXR1cm4gTm9uZSwgTm9uZSwgRmFsc2UsICItMSIKCiAgICAgICAganNv + bm91dHB1dCA9IGpzb24ubG9hZHMob3V0cHV0KQogICAgICAgIHJldHVybiAoCiAgICAgICAgICAg + IGpzb25vdXRwdXRbImtleXMiXVswXVsiYWNjZXNzX2tleSJdLAogICAgICAgICAgICBqc29ub3V0 + cHV0WyJrZXlzIl1bMF1bInNlY3JldF9rZXkiXSwKICAgICAgICAgICAgaW5mb19jYXBfc3VwcG9y + dGVkLAogICAgICAgICAgICAiIiwKICAgICAgICApCgogICAgZGVmIHZhbGlkYXRlX3JiZF9wb29s + KHNlbGYsIHBvb2xfbmFtZSk6CiAgICAgICAgaWYgbm90IHNlbGYuY2x1c3Rlci5wb29sX2V4aXN0 + cyhwb29sX25hbWUpOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9u + KAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcG9vbCwgJ3twb29sX25hbWV9JywgZG9l + cyBub3QgZXhpc3QiCiAgICAgICAgICAgICkKCiAgICBkZWYgaW5pdF9yYmRfcG9vbChzZWxmLCBy + YmRfcG9vbF9uYW1lKToKICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlS + YWRvcyk6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGlvY3R4ID0gc2VsZi5jbHVzdGVyLm9w + ZW5faW9jdHgocmJkX3Bvb2xfbmFtZSkKICAgICAgICByYmRfaW5zdCA9IHJiZC5SQkQoKQogICAg + ICAgIHJiZF9pbnN0LnBvb2xfaW5pdChpb2N0eCwgVHJ1ZSkKCiAgICBkZWYgdmFsaWRhdGVfcmFk + b3NfbmFtZXNwYWNlKHNlbGYpOgogICAgICAgIHJiZF9wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFy + c2VyLnJiZF9kYXRhX3Bvb2xfbmFtZQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmJkX21l + dGFkYXRhX2VjX3Bvb2xfbmFtZToKICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNlbGYuX2Fy + Z19wYXJzZXIucmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQogICAgICAgIHJhZG9zX25hbWVzcGFj + ZSA9IHNlbGYuX2FyZ19wYXJzZXIucmFkb3NfbmFtZXNwYWNlCiAgICAgICAgaWYgcmFkb3NfbmFt + ZXNwYWNlID09ICIiOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiByYWRvc19uYW1lc3Bh + Y2UuaXNsb3dlcigpID09IEZhbHNlOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJl + RXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmFkb3MgTmFtZXNwYWNl + LCAne3JhZG9zX25hbWVzcGFjZX0nLCAiCiAgICAgICAgICAgICAgICBmImNvbnRhaW5zIHVwcGVy + IGNhc2UiCiAgICAgICAgICAgICkKICAgICAgICByYmRfaW5zdCA9IHJiZC5SQkQoKQogICAgICAg + IGlvY3R4ID0gc2VsZi5jbHVzdGVyLm9wZW5faW9jdHgocmJkX3Bvb2xfbmFtZSkKICAgICAgICBp + ZiByYmRfaW5zdC5uYW1lc3BhY2VfZXhpc3RzKGlvY3R4LCByYWRvc19uYW1lc3BhY2UpIGlzIEZh + bHNlOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg + ICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmFkb3MgTmFtZXNwYWNlLCAne3JhZG9zX25hbWVzcGFj + ZX0nLCAiCiAgICAgICAgICAgICAgICBmImlzIG5vdCBmb3VuZCBpbiB0aGUgcG9vbCAne3JiZF9w + b29sX25hbWV9JyIKICAgICAgICAgICAgKQoKICAgIGRlZiBnZXRfb3JfY3JlYXRlX3N1YnZvbHVt + ZV9ncm91cChzZWxmLCBzdWJ2b2x1bWVfZ3JvdXAsIGNlcGhmc19maWxlc3lzdGVtX25hbWUpOgog + ICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgImNlcGgiLAogICAgICAgICAgICAiZnMiLAogICAg + ICAgICAgICAic3Vidm9sdW1lZ3JvdXAiLAogICAgICAgICAgICAiZ2V0cGF0aCIsCiAgICAgICAg + ICAgIGNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgIHN1YnZvbHVtZV9ncm91cCwK + ICAgICAgICBdCiAgICAgICAgdHJ5OgogICAgICAgICAgICBfID0gc3VicHJvY2Vzcy5jaGVja19v + dXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9j + ZXNzLkNhbGxlZFByb2Nlc3NFcnJvcjoKICAgICAgICAgICAgY21kID0gWwogICAgICAgICAgICAg + ICAgImNlcGgiLAogICAgICAgICAgICAgICAgImZzIiwKICAgICAgICAgICAgICAgICJzdWJ2b2x1 + bWVncm91cCIsCiAgICAgICAgICAgICAgICAiY3JlYXRlIiwKICAgICAgICAgICAgICAgIGNlcGhm + c19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgICAgICBzdWJ2b2x1bWVfZ3JvdXAsCiAgICAg + ICAgICAgIF0KICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgXyA9IHN1YnByb2Nlc3Mu + Y2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICAgICAgZXhj + ZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICAgICAgcmFpc2Ug + RXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBmInN1YnZvbHVt + ZSBncm91cCB7c3Vidm9sdW1lX2dyb3VwfSBpcyBub3QgYWJsZSB0byBnZXQgY3JlYXRlZCIKICAg + ICAgICAgICAgICAgICkKCiAgICBkZWYgcGluX3N1YnZvbHVtZSgKICAgICAgICBzZWxmLCBzdWJ2 + b2x1bWVfZ3JvdXAsIGNlcGhmc19maWxlc3lzdGVtX25hbWUsIHBpbl90eXBlLCBwaW5fc2V0dGlu + ZwogICAgKToKICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICJjZXBoIiwKICAgICAgICAgICAg + ImZzIiwKICAgICAgICAgICAgInN1YnZvbHVtZWdyb3VwIiwKICAgICAgICAgICAgInBpbiIsCiAg + ICAgICAgICAgIGNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgIHN1YnZvbHVtZV9n + cm91cCwKICAgICAgICAgICAgcGluX3R5cGUsCiAgICAgICAgICAgIHBpbl9zZXR0aW5nLAogICAg + ICAgIF0KICAgICAgICB0cnk6CiAgICAgICAgICAgIF8gPSBzdWJwcm9jZXNzLmNoZWNrX291dHB1 + dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhjZXB0IHN1YnByb2Nlc3Mu + Q2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj + ZXB0aW9uKAogICAgICAgICAgICAgICAgZiJzdWJ2b2x1bWUgZ3JvdXAge3N1YnZvbHVtZV9ncm91 + cH0gaXMgbm90IGFibGUgdG8gZ2V0IHBpbm5lZCIKICAgICAgICAgICAgKQoKICAgIGRlZiBnZXRf + cmd3X2ZzaWQoc2VsZiwgYmFzZV91cmwsIHZlcmlmeSk6CiAgICAgICAgYWNjZXNzX2tleSA9IHNl + bGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX0FDQ0VTU19LRVkiXQogICAgICAgIHNlY3Jl + dF9rZXkgPSBzZWxmLm91dF9tYXBbIlJHV19BRE1JTl9PUFNfVVNFUl9TRUNSRVRfS0VZIl0KICAg + ICAgICByZ3dfZW5kcG9pbnQgPSBzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludAogICAgICAg + IGJhc2VfdXJsID0gYmFzZV91cmwgKyAiOi8vIiArIHJnd19lbmRwb2ludCArICIvYWRtaW4vaW5m + bz8iCiAgICAgICAgcGFyYW1zID0geyJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmVxdWVzdF91 + cmwgPSBiYXNlX3VybCArIHVybGVuY29kZShwYXJhbXMpCgogICAgICAgIHRyeToKICAgICAgICAg + ICAgciA9IHJlcXVlc3RzLmdldCgKICAgICAgICAgICAgICAgIHJlcXVlc3RfdXJsLAogICAgICAg + ICAgICAgICAgYXV0aD1TM0F1dGgoYWNjZXNzX2tleSwgc2VjcmV0X2tleSwgcmd3X2VuZHBvaW50 + KSwKICAgICAgICAgICAgICAgIHZlcmlmeT12ZXJpZnksCiAgICAgICAgICAgICkKICAgICAgICBl + eGNlcHQgcmVxdWVzdHMuZXhjZXB0aW9ucy5UaW1lb3V0OgogICAgICAgICAgICBzeXMuc3RkZXJy + LndyaXRlKAogICAgICAgICAgICAgICAgZiJpbnZhbGlkIGVuZHBvaW50Oiwgbm90IGFibGUgdG8g + Y2FsbCBhZG1pbi1vcHMgYXBpe3Jnd19lbmRwb2ludH0iCiAgICAgICAgICAgICkKICAgICAgICAg + ICAgcmV0dXJuICIiLCAiLTEiCiAgICAgICAgcjEgPSByLmpzb24oKQogICAgICAgIGlmIHIxIGlz + IE5vbmUgb3IgcjEuZ2V0KCJpbmZvIikgaXMgTm9uZToKICAgICAgICAgICAgc3lzLnN0ZGVyci53 + cml0ZSgKICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHJndyBFbmRwb2ludCwgJ3tzZWxm + Ll9hcmdfcGFyc2VyLnJnd19lbmRwb2ludH0nLCBpcyBpbnZhbGlkLiIKICAgICAgICAgICAgKQog + ICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAi + LTEiLAogICAgICAgICAgICApCgogICAgICAgIHJldHVybiByMVsiaW5mbyJdWyJzdG9yYWdlX2Jh + Y2tlbmRzIl1bMF1bImNsdXN0ZXJfaWQiXSwgIiIKCiAgICBkZWYgdmFsaWRhdGVfcmd3X2VuZHBv + aW50KHNlbGYsIGluZm9fY2FwX3N1cHBvcnRlZCk6CiAgICAgICAgIyBpZiB0aGUgJ2NsdXN0ZXIn + IGluc3RhbmNlIGlzIGEgZHVtbXkgb25lLAogICAgICAgICMgZG9uJ3QgdHJ5IHRvIHJlYWNoIG91 + dCB0byB0aGUgZW5kcG9pbnQKICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVt + bXlSYWRvcyk6CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICByZ3dfZW5kcG9pbnQgPSBzZWxm + Ll9hcmdfcGFyc2VyLnJnd19lbmRwb2ludAoKICAgICAgICAjIHZhbGlkYXRlIHJndyBlbmRwb2lu + dCBvbmx5IGlmIGlwIGFkZHJlc3MgaXMgcGFzc2VkCiAgICAgICAgaXBfdHlwZSA9IHNlbGYuX2lu + dmFsaWRfZW5kcG9pbnQocmd3X2VuZHBvaW50KQoKICAgICAgICAjIGNoZWNrIGlmIHRoZSByZ3cg + ZW5kcG9pbnQgaXMgcmVhY2hhYmxlCiAgICAgICAgY2VydCA9IE5vbmUKICAgICAgICBpZiBub3Qg + c2VsZi5fYXJnX3BhcnNlci5yZ3dfc2tpcF90bHMgYW5kIHNlbGYudmFsaWRhdGVfcmd3X2VuZHBv + aW50X3Rsc19jZXJ0KCk6CiAgICAgICAgICAgIGNlcnQgPSBzZWxmLl9hcmdfcGFyc2VyLnJnd190 + bHNfY2VydF9wYXRoCiAgICAgICAgYmFzZV91cmwsIHZlcmlmeSwgZXJyID0gc2VsZi5lbmRwb2lu + dF9kaWFsKHJnd19lbmRwb2ludCwgaXBfdHlwZSwgY2VydD1jZXJ0KQogICAgICAgIGlmIGVyciAh + PSAiIjoKICAgICAgICAgICAgcmV0dXJuICItMSIKCiAgICAgICAgIyBjaGVjayBpZiB0aGUgcmd3 + IGVuZHBvaW50IGJlbG9uZ3MgdG8gdGhlIHNhbWUgY2x1c3RlcgogICAgICAgICMgb25seSBjaGVj + ayBpZiBgaW5mb2AgY2FwIGlzIHN1cHBvcnRlZAogICAgICAgIGlmIGluZm9fY2FwX3N1cHBvcnRl + ZDoKICAgICAgICAgICAgZnNpZCA9IHNlbGYuZ2V0X2ZzaWQoKQogICAgICAgICAgICByZ3dfZnNp + ZCwgZXJyID0gc2VsZi5nZXRfcmd3X2ZzaWQoYmFzZV91cmwsIHZlcmlmeSkKICAgICAgICAgICAg + aWYgZXJyID09ICItMSI6CiAgICAgICAgICAgICAgICByZXR1cm4gIi0xIgogICAgICAgICAgICBp + ZiBmc2lkICE9IHJnd19mc2lkOgogICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZSgKICAg + ICAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByZ3cgRW5kcG9pbnQsICd7c2VsZi5fYXJn + X3BhcnNlci5yZ3dfZW5kcG9pbnR9JywgaXMgaW52YWxpZC4gV2UgYXJlIHZhbGlkYXRpbmcgYnkg + Y2FsbGluZyB0aGUgYWRtaW5vcHMgYXBpIHRocm91Z2ggcmd3LWVuZHBvaW50IGFuZCB2YWxpZGF0 + aW5nIHRoZSBjbHVzdGVyX2lkICd7cmd3X2ZzaWR9JyBpcyBlcXVhbCB0byB0aGUgY2VwaCBjbHVz + dGVyIGZzaWQgJ3tmc2lkfSciCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICByZXR1 + cm4gIi0xIgoKICAgICAgICAjIGNoZWNrIGlmIHRoZSByZ3cgZW5kcG9pbnQgcG9vbCBleGlzdAog + ICAgICAgICMgb25seSB2YWxpZGF0ZSBpZiByZ3dfcG9vbF9wcmVmaXggaXMgcGFzc2VkIGVsc2Ug + aXQgd2lsbCB0YWtlIGRlZmF1bHQgdmFsdWUgYW5kIHdlIGRvbid0IGNyZWF0ZSB0aGVzZSBkZWZh + dWx0IHBvb2xzCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXggIT0g + ImRlZmF1bHQiOgogICAgICAgICAgICByZ3dfcG9vbHNfdG9fdmFsaWRhdGUgPSBbCiAgICAgICAg + ICAgICAgICBmIntzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3Lm1ldGEiLAog + ICAgICAgICAgICAgICAgIi5yZ3cucm9vdCIsCiAgICAgICAgICAgICAgICBmIntzZWxmLl9hcmdf + cGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmNvbnRyb2wiLAogICAgICAgICAgICAgICAgZiJ7 + c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5sb2ciLAogICAgICAgICAgICBd + CiAgICAgICAgICAgIGZvciBfcmd3X3Bvb2xfdG9fdmFsaWRhdGUgaW4gcmd3X3Bvb2xzX3RvX3Zh + bGlkYXRlOgogICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuY2x1c3Rlci5wb29sX2V4aXN0cyhf + cmd3X3Bvb2xfdG9fdmFsaWRhdGUpOgogICAgICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3Jp + dGUoCiAgICAgICAgICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHBvb2wsICd7X3Jnd19w + b29sX3RvX3ZhbGlkYXRlfScsIGRvZXMgbm90IGV4aXN0IgogICAgICAgICAgICAgICAgICAgICkK + ICAgICAgICAgICAgICAgICAgICByZXR1cm4gIi0xIgoKICAgICAgICByZXR1cm4gIiIKCiAgICBk + ZWYgdmFsaWRhdGVfcmd3X211bHRpc2l0ZShzZWxmLCByZ3dfbXVsdGlzaXRlX2NvbmZpZ19uYW1l + LCByZ3dfbXVsdGlzaXRlX2NvbmZpZyk6CiAgICAgICAgaWYgcmd3X211bHRpc2l0ZV9jb25maWcg + IT0gIiI6CiAgICAgICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgICAgICJyYWRvc2d3LWFkbWlu + IiwKICAgICAgICAgICAgICAgIHJnd19tdWx0aXNpdGVfY29uZmlnLAogICAgICAgICAgICAgICAg + ImdldCIsCiAgICAgICAgICAgICAgICAiLS1yZ3ctIiArIHJnd19tdWx0aXNpdGVfY29uZmlnLAog + ICAgICAgICAgICAgICAgcmd3X211bHRpc2l0ZV9jb25maWdfbmFtZSwKICAgICAgICAgICAgXQog + ICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBfID0gc3VicHJvY2Vzcy5jaGVja19vdXRw + dXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAgICAgICAgICBleGNlcHQgc3VicHJv + Y2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhlY0VycjoKICAgICAgICAgICAgICAgIGVycl9t + c2cgPSAoCiAgICAgICAgICAgICAgICAgICAgZiJmYWlsZWQgdG8gZXhlY3V0ZSBjb21tYW5kIHtj + bWR9LiBPdXRwdXQ6IHtleGVjRXJyLm91dHB1dH0uICIKICAgICAgICAgICAgICAgICAgICBmIkNv + ZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3RkZXJyfSIKICAgICAg + ICAgICAgICAgICkKICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3JpdGUoZXJyX21zZykKICAg + ICAgICAgICAgICAgIHJldHVybiAiLTEiCiAgICAgICAgcmV0dXJuICIiCgogICAgZGVmIGNvbnZl + cnRfY29tbWFfc2VwYXJhdGVkX3RvX2FycmF5KHNlbGYsIHZhbHVlKToKICAgICAgICByZXR1cm4g + dmFsdWUuc3BsaXQoIiwiKQoKICAgIGRlZiByYWlzZV9leGNlcHRpb25faWZfYW55X3RvcG9sb2d5 + X2ZsYWdfaXNfbWlzc2luZyhzZWxmKToKICAgICAgICBpZiAoCiAgICAgICAgICAgICgKICAgICAg + ICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfcG9vbHMgIT0gIiIKICAgICAgICAg + ICAgICAgIGFuZCAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9n + eV9mYWlsdXJlX2RvbWFpbl9sYWJlbCA9PSAiIgogICAgICAgICAgICAgICAgICAgIG9yIHNlbGYu + X2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFpbHVyZV9kb21haW5fdmFsdWVzID09ICIiCiAgICAgICAg + ICAgICAgICApCiAgICAgICAgICAgICkKICAgICAgICAgICAgb3IgKAogICAgICAgICAgICAgICAg + c2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl9sYWJlbCAhPSAiIgogICAg + ICAgICAgICAgICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRv + cG9sb2d5X3Bvb2xzID09ICIiCiAgICAgICAgICAgICAgICAgICAgb3Igc2VsZi5fYXJnX3BhcnNl + ci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMgPT0gIiIKICAgICAgICAgICAgICAgICkK + ICAgICAgICAgICAgKQogICAgICAgICAgICBvciAoCiAgICAgICAgICAgICAgICBzZWxmLl9hcmdf + cGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX3ZhbHVlcyAhPSAiIgogICAgICAgICAgICAg + ICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bv + b2xzID09ICIiCiAgICAgICAgICAgICAgICAgICAgb3Igc2VsZi5fYXJnX3BhcnNlci50b3BvbG9n + eV9mYWlsdXJlX2RvbWFpbl9sYWJlbCA9PSAiIgogICAgICAgICAgICAgICAgKQogICAgICAgICAg + ICApCiAgICAgICAgKToKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv + bigKICAgICAgICAgICAgICAgICJwcm92aWRlIGFsbCB0aGUgdG9wb2xvZ3kgZmxhZ3MgLS10b3Bv + bG9neS1wb29scywgLS10b3BvbG9neS1mYWlsdXJlLWRvbWFpbi1sYWJlbCwgLS10b3BvbG9neS1m + YWlsdXJlLWRvbWFpbi12YWx1ZXMiCiAgICAgICAgICAgICkKCiAgICBkZWYgdmFsaWRhdGVfdG9w + b2xvZ3lfdmFsdWVzKHNlbGYsIHRvcG9sb2d5X3Bvb2xzLCB0b3BvbG9neV9mZCk6CiAgICAgICAg + aWYgbGVuKHRvcG9sb2d5X3Bvb2xzKSAhPSBsZW4odG9wb2xvZ3lfZmQpOgogICAgICAgICAgICBy + YWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJUaGUgcHJv + dmlkZWQgdG9wb2xvZ3kgcG9vbHMsICd7dG9wb2xvZ3lfcG9vbHN9JywgYW5kICIKICAgICAgICAg + ICAgICAgIGYidG9wb2xvZ3kgZmFpbHVyZSBkb21haW4sICd7dG9wb2xvZ3lfZmR9JywiCiAgICAg + ICAgICAgICAgICBmImFyZSBvZiBkaWZmZXJlbnQgbGVuZ3RoLCAne2xlbih0b3BvbG9neV9wb29s + cyl9JyBhbmQgJ3tsZW4odG9wb2xvZ3lfZmQpfScgcmVzcGN0aXZlbHkiCiAgICAgICAgICAgICkK + ICAgICAgICByZXR1cm4KCiAgICBkZWYgdmFsaWRhdGVfdG9wb2xvZ3lfcmJkX3Bvb2xzKHNlbGYs + IHRvcG9sb2d5X3JiZF9wb29scyk6CiAgICAgICAgZm9yIHBvb2wgaW4gdG9wb2xvZ3lfcmJkX3Bv + b2xzOgogICAgICAgICAgICBzZWxmLnZhbGlkYXRlX3JiZF9wb29sKHBvb2wpCgogICAgZGVmIGlu + aXRfdG9wb2xvZ3lfcmJkX3Bvb2xzKHNlbGYsIHRvcG9sb2d5X3JiZF9wb29scyk6CiAgICAgICAg + Zm9yIHBvb2wgaW4gdG9wb2xvZ3lfcmJkX3Bvb2xzOgogICAgICAgICAgICBzZWxmLmluaXRfcmJk + X3Bvb2wocG9vbCkKCiAgICAjIHRoaXMgd2lsbCByZXR1cm4gdGhlIGZpbmFsIGFyZ3MgdGhhdCBz + Y3JpcHQgdXNlcyB0byBwcm9jZXNzCiAgICAjIHRoZSBwcmlvcml0eSB0byBzZXQgYSBwYXJ0aWN1 + bGFyIHZhbHVlIGlzLAogICAgIyBjb21tYW5kLWxpbmUtYXJncyA+IGNvbmZpZy5pbmkgZmlsZSB2 + YWx1ZXMgPiBkZWZhdWx0IHZhbHVlcwogICAgZGVmIGdldEZpbmFsVXNlZEFyZ3Moc2VsZik6CiAg + ICAgICAgYXJndW1lbnQgPSBmIltDb25maWd1cmF0aW9uc11cbiIKICAgICAgICBmb3IgYXJnIGlu + IHZhcnMoc2VsZi5fYXJnX3BhcnNlcik6CiAgICAgICAgICAgIGlmIHN0cihnZXRhdHRyKHNlbGYu + X2FyZ19wYXJzZXIsIGFyZykpOgogICAgICAgICAgICAgICAgIyBweXRob24gdHJlYXRzIGZsYWct + bmFtZSBhcyBmbGFnX25hbWUgaW50ZXJuYWxseSwgc28gY29udmVydGluZyBiYWNrIHRvIGZsYWct + bmFtZSwKICAgICAgICAgICAgICAgICMgc28gd2UgY2FuIGdldCB0aG9zZSB2YWx1ZXMgZnJvbSBj + b25maWcgZmlsZQogICAgICAgICAgICAgICAgYXJnVmFsdWUgPSBhcmcucmVwbGFjZSgiXyIsICIt + IikKICAgICAgICAgICAgICAgICMgZG8gbm90IGFkZCB0aGUgY29uZmlnLWZpbGUgZmxhZyBhbmQg + YWxzbyBub3QgYWRkIHRoZSBib29sZWFuIGZsYWdzIHdoaWNoIGFyZSBzZXQgdG8gRmFsc2UKICAg + ICAgICAgICAgICAgICMgYmVjYXVzZSBjb25maWcuaW5pIGZpbGUgdHJlYXRzIGJvb2xlYW4gZmxh + Z3MgYXMgVHJ1ZSBhbHdheXMKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAg + ICBhcmdWYWx1ZSAhPSAiY29uZmlnLWZpbGUiCiAgICAgICAgICAgICAgICAgICAgYW5kIGdldGF0 + dHIoc2VsZi5fYXJnX3BhcnNlciwgYXJnKSAhPSBGYWxzZQogICAgICAgICAgICAgICAgKToKICAg + ICAgICAgICAgICAgICAgICBhcmd1bWVudCArPSBmInthcmdWYWx1ZX0gPSB7c3RyKGdldGF0dHIo + c2VsZi5fYXJnX3BhcnNlciwgYXJnKSl9XG4iCiAgICAgICAgcmV0dXJuIGFyZ3VtZW50CgogICAg + ZGVmIF9nZW5fb3V0cHV0X21hcChzZWxmKToKICAgICAgICBpZiBzZWxmLm91dF9tYXA6CiAgICAg + ICAgICAgIHJldHVybgogICAgICAgICMgc3VwcG9ydCBsZWdhY3kgZmxhZyB3aXRoIHVwZ3JhZGVz + CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jbHVzdGVyX25hbWU6CiAgICAgICAgICAgIHNl + bGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZSA9IHNlbGYuX2FyZ19wYXJzZXIuY2x1c3Rl + cl9uYW1lCiAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lID0gKAogICAg + ICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUubG93ZXIoKQogICAgICAg + ICkgICMgYWx3YXlzIGNvbnZlcnQgY2x1c3RlciBuYW1lIHRvIGxvd2VyY2FzZSBjaGFyYWN0ZXJz + CiAgICAgICAgc2VsZi52YWxpZGF0ZV9yYmRfcG9vbChzZWxmLl9hcmdfcGFyc2VyLnJiZF9kYXRh + X3Bvb2xfbmFtZSkKICAgICAgICBzZWxmLmluaXRfcmJkX3Bvb2woc2VsZi5fYXJnX3BhcnNlci5y + YmRfZGF0YV9wb29sX25hbWUpCiAgICAgICAgc2VsZi52YWxpZGF0ZV9yYWRvc19uYW1lc3BhY2Uo + KQogICAgICAgIHNlbGYuX2V4Y2x1ZGVkX2tleXMuYWRkKCJLOFNfQ0xVU1RFUl9OQU1FIikKICAg + ICAgICBzZWxmLmdldF9jZXBoZnNfZGF0YV9wb29sX2RldGFpbHMoKQogICAgICAgICMgZG91Ymxl + IHN0cmluZyBuZWVkZWQgZm9yIHVwc3RyZWFtIGV4cG9ydHMgb2YgZmxhZ3MKICAgICAgICBzZWxm + Lm91dF9tYXBbIkFSR1MiXSA9IGYnIntzZWxmLmdldEZpbmFsVXNlZEFyZ3MoKX0iJwogICAgICAg + IHNlbGYub3V0X21hcFsiTkFNRVNQQUNFIl0gPSBzZWxmLl9hcmdfcGFyc2VyLm5hbWVzcGFjZQog + ICAgICAgIHNlbGYub3V0X21hcFsiSzhTX0NMVVNURVJfTkFNRSJdID0gc2VsZi5fYXJnX3BhcnNl + ci5rOHNfY2x1c3Rlcl9uYW1lCiAgICAgICAgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0ZT + SUQiXSA9IHNlbGYuZ2V0X2ZzaWQoKQogICAgICAgIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5B + TF9VU0VSTkFNRSJdID0gc2VsZi5ydW5fYXNfdXNlcgogICAgICAgIHNlbGYub3V0X21hcFsiUk9P + S19FWFRFUk5BTF9DRVBIX01PTl9EQVRBIl0gPSBzZWxmLmdldF9jZXBoX2V4dGVybmFsX21vbl9k + YXRhKCkKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfVVNFUl9TRUNSRVQiXSA9 + IHNlbGYuY3JlYXRlX2NoZWNrZXJLZXkoCiAgICAgICAgICAgICJjbGllbnQuaGVhbHRoY2hlY2tl + ciIKICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0RBU0hCT0FS + RF9MSU5LIl0gPSBzZWxmLmdldF9jZXBoX2Rhc2hib2FyZF9saW5rKCkKICAgICAgICAoCiAgICAg + ICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVCJdLAogICAgICAgICAgICBz + ZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSJdLAogICAgICAgICkgPSBzZWxm + LmNyZWF0ZV9jZXBoQ1NJS2V5cmluZ191c2VyKCJjbGllbnQuY3NpLXJiZC1ub2RlIikKICAgICAg + ICAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVQi + XSwKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9O + QU1FIl0sCiAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNsaWVu + dC5jc2ktcmJkLXByb3Zpc2lvbmVyIikKICAgICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19QT09M + X05BTUUiXSA9IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lCiAgICAgICAg + c2VsZi5vdXRfbWFwWyJDRVBIRlNfTUVUQURBVEFfUE9PTF9OQU1FIl0gPSAoCiAgICAgICAgICAg + IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX21ldGFkYXRhX3Bvb2xfbmFtZQogICAgICAgICkKICAg + ICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl0gPSBzZWxmLl9hcmdfcGFyc2VyLmNl + cGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICBzZWxmLm91dF9tYXBbIlJFU1RSSUNURURfQVVU + SF9QRVJNSVNTSU9OIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmVzdHJpY3Rl + ZF9hdXRoX3Blcm1pc3Npb24KICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJSQURPU19O + QU1FU1BBQ0UiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmFkb3NfbmFtZXNwYWNlCiAgICAgICAgc2Vs + Zi5vdXRfbWFwWyJTVUJWT0xVTUVfR1JPVVAiXSA9IHNlbGYuX2FyZ19wYXJzZXIuc3Vidm9sdW1l + X2dyb3VwCiAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVfU0VDUkVUIl0gPSAi + IgogICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVQiXSA9 + ICIiCiAgICAgICAgIyBjcmVhdGUgQ2VwaEZTIG5vZGUgYW5kIHByb3Zpc2lvbmVyIGtleXJpbmcg + b25seSB3aGVuIE1EUyBleGlzdHMKICAgICAgICBpZiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19O + QU1FIl0gYW5kIHNlbGYub3V0X21hcFsiQ0VQSEZTX1BPT0xfTkFNRSJdOgogICAgICAgICAgICAo + CiAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9TRUNSRVQiXSwK + ICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1F + Il0sCiAgICAgICAgICAgICkgPSBzZWxmLmNyZWF0ZV9jZXBoQ1NJS2V5cmluZ191c2VyKCJjbGll + bnQuY3NpLWNlcGhmcy1ub2RlIikKICAgICAgICAgICAgKAogICAgICAgICAgICAgICAgc2VsZi5v + dXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAg + c2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FIl0sCiAgICAg + ICAgICAgICkgPSBzZWxmLmNyZWF0ZV9jZXBoQ1NJS2V5cmluZ191c2VyKCJjbGllbnQuY3NpLWNl + cGhmcy1wcm92aXNpb25lciIpCiAgICAgICAgICAgICMgY3JlYXRlIHRoZSBkZWZhdWx0ICJjc2ki + IHN1YnZvbHVtZWdyb3VwCiAgICAgICAgICAgIHNlbGYuZ2V0X29yX2NyZWF0ZV9zdWJ2b2x1bWVf + Z3JvdXAoCiAgICAgICAgICAgICAgICAiY3NpIiwgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls + ZXN5c3RlbV9uYW1lCiAgICAgICAgICAgICkKICAgICAgICAgICAgIyBwaW4gdGhlIGRlZmF1bHQg + ImNzaSIgc3Vidm9sdW1lZ3JvdXAKICAgICAgICAgICAgc2VsZi5waW5fc3Vidm9sdW1lKAogICAg + ICAgICAgICAgICAgImNzaSIsIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFt + ZSwgImRpc3RyaWJ1dGVkIiwgIjEiCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgc2VsZi5v + dXRfbWFwWyJTVUJWT0xVTUVfR1JPVVAiXToKICAgICAgICAgICAgICAgIHNlbGYuZ2V0X29yX2Ny + ZWF0ZV9zdWJ2b2x1bWVfZ3JvdXAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl + ci5zdWJ2b2x1bWVfZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5j + ZXBoZnNfZmlsZXN5c3RlbV9uYW1lLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAg + c2VsZi5waW5fc3Vidm9sdW1lKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIu + c3Vidm9sdW1lX2dyb3VwLAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2Vw + aGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgICAgICAgICAiZGlzdHJpYnV0ZWQiLAog + ICAgICAgICAgICAgICAgICAgICIxIiwKICAgICAgICAgICAgICAgICkKICAgICAgICBzZWxmLm91 + dF9tYXBbIlJHV19UTFNfQ0VSVCJdID0gIiIKICAgICAgICBzZWxmLm91dF9tYXBbIk1PTklUT1JJ + TkdfRU5EUE9JTlQiXSA9ICIiCiAgICAgICAgc2VsZi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBP + SU5UX1BPUlQiXSA9ICIiCiAgICAgICAgaWYgbm90IHNlbGYuX2FyZ19wYXJzZXIuc2tpcF9tb25p + dG9yaW5nX2VuZHBvaW50OgogICAgICAgICAgICAoCiAgICAgICAgICAgICAgICBzZWxmLm91dF9t + YXBbIk1PTklUT1JJTkdfRU5EUE9JTlQiXSwKICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsi + TU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0sCiAgICAgICAgICAgICkgPSBzZWxmLmdldF9hY3Rp + dmVfYW5kX3N0YW5kYnlfbWdycygpCiAgICAgICAgc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1F + Il0gPSBzZWxmLl9hcmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZQogICAgICAgIHNlbGYub3V0 + X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xfTkFNRSJdID0gKAogICAgICAgICAgICBzZWxmLnZh + bGlkYXRlX3JiZF9tZXRhZGF0YV9lY19wb29sX25hbWUoKQogICAgICAgICkKICAgICAgICBzZWxm + Lm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0gPSBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bv + b2xzCiAgICAgICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9MQUJFTCJd + ID0gKAogICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWlu + X2xhYmVsCiAgICAgICAgKQogICAgICAgIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9E + T01BSU5fVkFMVUVTIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lf + ZmFpbHVyZV9kb21haW5fdmFsdWVzCiAgICAgICAgKQogICAgICAgIGlmICgKICAgICAgICAgICAg + c2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9wb29scyAhPSAiIgogICAgICAgICAgICBhbmQgc2Vs + Zi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl9sYWJlbCAhPSAiIgogICAgICAg + ICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMg + IT0gIiIKICAgICAgICApOgogICAgICAgICAgICBzZWxmLnZhbGlkYXRlX3RvcG9sb2d5X3ZhbHVl + cygKICAgICAgICAgICAgICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXko + c2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdKSwKICAgICAgICAgICAgICAgIHNlbGYuY29u + dmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5v + dXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXQogICAgICAgICAgICAgICAg + KSwKICAgICAgICAgICAgKQogICAgICAgICAgICBzZWxmLnZhbGlkYXRlX3RvcG9sb2d5X3JiZF9w + b29scygKICAgICAgICAgICAgICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJy + YXkoc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdKQogICAgICAgICAgICApCiAgICAgICAg + ICAgIHNlbGYuaW5pdF90b3BvbG9neV9yYmRfcG9vbHMoCiAgICAgICAgICAgICAgICBzZWxmLmNv + bnZlcnRfY29tbWFfc2VwYXJhdGVkX3RvX2FycmF5KHNlbGYub3V0X21hcFsiVE9QT0xPR1lfUE9P + TFMiXSkKICAgICAgICAgICAgKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYucmFpc2Vf + ZXhjZXB0aW9uX2lmX2FueV90b3BvbG9neV9mbGFnX2lzX21pc3NpbmcoKQoKICAgICAgICBzZWxm + Lm91dF9tYXBbIlJHV19QT09MX1BSRUZJWCJdID0gc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9w + cmVmaXgKICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdID0gIiIKICAgICAgICBp + ZiBzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludDoKICAgICAgICAgICAgaWYgc2VsZi5fYXJn + X3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICAgICAgc2VsZi5jcmVhdGVfcmd3X2FkbWluX29w + c191c2VyKCkKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAg + ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd19yZWFsbV9uYW1lICE9ICIiCiAgICAgICAg + ICAgICAgICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lICE9ICIi + CiAgICAgICAgICAgICAgICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSAh + PSAiIgogICAgICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgICAgICBlcnIgPSBzZWxmLnZh + bGlkYXRlX3Jnd19tdWx0aXNpdGUoCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19w + YXJzZXIucmd3X3JlYWxtX25hbWUsICJyZWFsbSIKICAgICAgICAgICAgICAgICAgICApCiAgICAg + ICAgICAgICAgICAgICAgZXJyID0gc2VsZi52YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKAogICAgICAg + ICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwgInpv + bmVncm91cCIKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgZXJyID0g + c2VsZi52YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKAogICAgICAgICAgICAgICAgICAgICAgICBzZWxm + Ll9hcmdfcGFyc2VyLnJnd196b25lX25hbWUsICJ6b25lIgogICAgICAgICAgICAgICAgICAgICkK + CiAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl + ci5yZ3dfcmVhbG1fbmFtZSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdf + cGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBz + ZWxmLl9hcmdfcGFyc2VyLnJnd196b25lX25hbWUgPT0gIiIKICAgICAgICAgICAgICAgICkgb3Ig KAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUgIT0g IiIKICAgICAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5yZ3dfem9uZWdyb3Vw X25hbWUgIT0gIiIKICAgICAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5yZ3df - em9uZV9uYW1lICE9ICIiCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIGVy - ciA9IHNlbGYudmFsaWRhdGVfcmd3X211bHRpc2l0ZSgKICAgICAgICAgICAgICAgICAgICAgICAg - c2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVhbG1fbmFtZSwgInJlYWxtIgogICAgICAgICAgICAgICAg - ICAgICkKICAgICAgICAgICAgICAgICAgICBlcnIgPSBzZWxmLnZhbGlkYXRlX3Jnd19tdWx0aXNp - dGUoCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91 - cF9uYW1lLCAiem9uZWdyb3VwIgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAg - ICAgICBlcnIgPSBzZWxmLnZhbGlkYXRlX3Jnd19tdWx0aXNpdGUoCiAgICAgICAgICAgICAgICAg - ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwgInpvbmUiCiAgICAgICAgICAg - ICAgICAgICAgKQoKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAgICBzZWxm - Ll9hcmdfcGFyc2VyLnJnd19yZWFsbV9uYW1lID09ICIiCiAgICAgICAgICAgICAgICAgICAgYW5k - IHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lID09ICIiCiAgICAgICAgICAgICAg - ICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSA9PSAiIgogICAgICAgICAg - ICAgICAgKSBvciAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVh - bG1fbmFtZSAhPSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnJn - d196b25lZ3JvdXBfbmFtZSAhPSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdf - cGFyc2VyLnJnd196b25lX25hbWUgIT0gIiIKICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAg - ICAgICAgICAgKAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19BRE1J - Tl9PUFNfVVNFUl9BQ0NFU1NfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYub3V0 - X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JFVF9LRVkiXSwKICAgICAgICAgICAgICAgICAg - ICAgICAgaW5mb19jYXBfc3VwcG9ydGVkLAogICAgICAgICAgICAgICAgICAgICAgICBlcnIsCiAg - ICAgICAgICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX3Jnd19hZG1pbl9vcHNfdXNlcigpCiAg - ICAgICAgICAgICAgICAgICAgZXJyID0gc2VsZi52YWxpZGF0ZV9yZ3dfZW5kcG9pbnQoaW5mb19j - YXBfc3VwcG9ydGVkKQogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3 - X3Rsc19jZXJ0X3BhdGg6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiUkdX - X1RMU19DRVJUIl0gPSAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnZhbGlkYXRl - X3Jnd19lbmRwb2ludF90bHNfY2VydCgpCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAg - ICAgICAgICAgICAgICAjIGlmIHRoZXJlIGlzIG5vIGVycm9yLCBzZXQgdGhlIFJHV19FTkRQT0lO - VAogICAgICAgICAgICAgICAgICAgIGlmIGVyciAhPSAiLTEiOgogICAgICAgICAgICAgICAgICAg - ICAgICBzZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdID0gc2VsZi5fYXJnX3BhcnNlci5yZ3df - ZW5kcG9pbnQKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgZXJyID0g - IlBsZWFzZSBwcm92aWRlIGFsbCB0aGUgUkdXIG11bHRpc2l0ZSBwYXJhbWV0ZXJzIG9yIG5vbmUg - b2YgdGhlbSIKICAgICAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycikKCiAgICBk - ZWYgZ2VuX3NoZWxsX291dChzZWxmKToKICAgICAgICBzZWxmLl9nZW5fb3V0cHV0X21hcCgpCiAg - ICAgICAgc2hPdXRJTyA9IFN0cmluZ0lPKCkKICAgICAgICBmb3IgaywgdiBpbiBzZWxmLm91dF9t - YXAuaXRlbXMoKToKICAgICAgICAgICAgaWYgdiBhbmQgayBub3QgaW4gc2VsZi5fZXhjbHVkZWRf - a2V5czoKICAgICAgICAgICAgICAgIHNoT3V0SU8ud3JpdGUoZiJleHBvcnQge2t9PXt2fXtMSU5F - U0VQfSIpCiAgICAgICAgc2hPdXQgPSBzaE91dElPLmdldHZhbHVlKCkKICAgICAgICBzaE91dElP - LmNsb3NlKCkKICAgICAgICByZXR1cm4gc2hPdXQKCiAgICBkZWYgZ2VuX2pzb25fb3V0KHNlbGYp - OgogICAgICAgIHNlbGYuX2dlbl9vdXRwdXRfbWFwKCkKICAgICAgICBpZiBzZWxmLl9hcmdfcGFy - c2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiAiIgogICAgICAgIGpzb25fb3V0ID0gWwog - ICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJleHRlcm5hbC1jbHVzdGVyLXVz - ZXItY29tbWFuZCIsCiAgICAgICAgICAgICAgICAia2luZCI6ICJDb25maWdNYXAiLAogICAgICAg - ICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgImFyZ3MiOiBzZWxmLm91dF9t - YXBbIkFSR1MiXSwKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAg - IHsKICAgICAgICAgICAgICAgICJuYW1lIjogInJvb2stY2VwaC1tb24tZW5kcG9pbnRzIiwKICAg - ICAgICAgICAgICAgICJraW5kIjogIkNvbmZpZ01hcCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6 - IHsKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5B - TF9DRVBIX01PTl9EQVRBIl0sCiAgICAgICAgICAgICAgICAgICAgIm1heE1vbklkIjogIjAiLAog - ICAgICAgICAgICAgICAgICAgICJtYXBwaW5nIjogInt9IiwKICAgICAgICAgICAgICAgIH0sCiAg - ICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogInJvb2st - Y2VwaC1tb24iLAogICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAg - ICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICJhZG1pbi1zZWNyZXQiOiAiYWRtaW4t - c2VjcmV0IiwKICAgICAgICAgICAgICAgICAgICAiZnNpZCI6IHNlbGYub3V0X21hcFsiUk9PS19F - WFRFUk5BTF9GU0lEIl0sCiAgICAgICAgICAgICAgICAgICAgIm1vbi1zZWNyZXQiOiAibW9uLXNl - Y3JldCIsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAg - ICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtb3BlcmF0b3ItY3JlZHMiLAogICAgICAg - ICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAgICJkYXRhIjogewogICAg - ICAgICAgICAgICAgICAgICJ1c2VySUQiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfVVNF - Uk5BTUUiXSwKICAgICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiUk9P - S19FWFRFUk5BTF9VU0VSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAg - fSwKICAgICAgICBdCgogICAgICAgICMgaWYgJ01PTklUT1JJTkdfRU5EUE9JTlQnIGV4aXN0cywg - dGhlbiBvbmx5IGFkZCAnbW9uaXRvcmluZy1lbmRwb2ludCcgdG8gQ2x1c3RlcgogICAgICAgIGlm - ICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UIl0KICAgICAg - ICAgICAgYW5kIHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0KICAgICAg - ICApOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAg - ICAgICAgICAgICAgICAgIm5hbWUiOiAibW9uaXRvcmluZy1lbmRwb2ludCIsCiAgICAgICAgICAg - ICAgICAgICAgImtpbmQiOiAiQ2VwaENsdXN0ZXIiLAogICAgICAgICAgICAgICAgICAgICJkYXRh - IjogewogICAgICAgICAgICAgICAgICAgICAgICAiTW9uaXRvcmluZ0VuZHBvaW50Ijogc2VsZi5v - dXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJN - b25pdG9yaW5nUG9ydCI6IHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0s - CiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQoK - ICAgICAgICAjIGlmICdDU0lfUkJEX05PREVfU0VDUkVUJyBleGlzdHMsIHRoZW4gb25seSBhZGQg - J3Jvb2stY3NpLXJiZC1wcm92aXNpb25lcicgU2VjcmV0CiAgICAgICAgaWYgKAogICAgICAgICAg - ICBzZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2Vs - Zi5vdXRfbWFwWyJDU0lfUkJEX05PREVfU0VDUkVUX05BTUUiXQogICAgICAgICk6CiAgICAgICAg - ICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAg - ICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUn - XX0iLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAg - ICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VySUQiOiBzZWxmLm91 - dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAg - ICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVCJdLAogICAgICAg - ICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAj - IGlmICdDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdy - b29rLWNzaS1yYmQtcHJvdmlzaW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAg - c2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCJdCiAgICAgICAgICAgIGFu - ZCBzZWxmLm91dF9tYXBbIkNTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXQogICAgICAg - ICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAg - ICAgICAgICAgICAgICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BST1ZJ - U0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTZWNy - ZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAg - ICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1F - Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VyS2V5Ijogc2VsZi5vdXRfbWFwWyJDU0lf - UkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAg - ICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdDU0lfQ0VQSEZTX1BST1ZJU0lP - TkVSX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNzaS1jZXBoZnMtcHJvdmlz - aW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lf - Q0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVCJdCiAgICAgICAgICAgIGFuZCBzZWxmLm91dF9tYXBb - IkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXQogICAgICAgICk6CiAgICAgICAg - ICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAg - ICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NF - Q1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAg - ICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5J - RCI6IHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSJdLAog - ICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5LZXkiOiBzZWxmLm91dF9tYXBbIkNTSV9DRVBI - RlNfUFJPVklTSU9ORVJfU0VDUkVUIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAg - ICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ0NTSV9DRVBIRlNfTk9ERV9TRUNS - RVQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktY2VwaGZzLW5vZGUnIFNlY3JldAog - ICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVfU0VD - UkVUIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JF - VF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAg - ICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBmInJvb2ste3NlbGYub3V0X21h - cFsnQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAi - a2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAg - ICAgICAgICAgICAgICAiYWRtaW5JRCI6IHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NF - Q1JFVF9OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pbktleSI6IHNlbGYub3V0 - X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAg - ICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdST09LX0VYVEVSTkFM - X0RBU0hCT0FSRF9MSU5LJyBleGlzdHMsIHRoZW4gb25seSBhZGQgJ3Jvb2stY2VwaC1kYXNoYm9h - cmQtbGluaycgU2VjcmV0CiAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0RB - U0hCT0FSRF9MSU5LIl06CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAg - ICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtZGFzaGJvYXJkLWxp - bmsiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAg - ICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VySUQiOiAiY2VwaC1k - YXNoYm9hcmQtbGluayIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VyS2V5Ijogc2VsZi5v - dXRfbWFwWyJST09LX0VYVEVSTkFMX0RBU0hCT0FSRF9MSU5LIl0sCiAgICAgICAgICAgICAgICAg - ICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ1JBRE9T - X05BTUVTUEFDRScgZXhpc3RzLCB0aGVuIG9ubHkgYWRkIHRoZSAiUkFET1NfTkFNRVNQQUNFIiBu - YW1lc3BhY2UKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiUkFET1NfTkFN - RVNQQUNFIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsiUkVTVFJJQ1RFRF9BVVRIX1BF - Uk1JU1NJT04iXQogICAgICAgICAgICBhbmQgbm90IHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRB - X0VDX1BPT0xfTkFNRSJdCiAgICAgICAgKToKICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAog - ICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICJuYW1lIjogInJhZG9zLW5hbWVz - cGFjZSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiQ2VwaEJsb2NrUG9vbFJhZG9zTmFt - ZXNwYWNlIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAg - ICAgICAgInJhZG9zTmFtZXNwYWNlTmFtZSI6IHNlbGYub3V0X21hcFsiUkFET1NfTkFNRVNQQUNF - Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9P - TF9OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAg - ICAgICAgKQogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAg - ICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQtcmFkb3MtbmFtZXNwYWNlIiwKICAg + em9uZV9uYW1lICE9ICIiCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgICgK + ICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJSR1dfQURNSU5fT1BTX1VTRVJf + QUNDRVNTX0tFWSJdLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19B + RE1JTl9PUFNfVVNFUl9TRUNSRVRfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgICAgIGluZm9f + Y2FwX3N1cHBvcnRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgZXJyLAogICAgICAgICAgICAg + ICAgICAgICkgPSBzZWxmLmNyZWF0ZV9yZ3dfYWRtaW5fb3BzX3VzZXIoKQogICAgICAgICAgICAg + ICAgICAgIGVyciA9IHNlbGYudmFsaWRhdGVfcmd3X2VuZHBvaW50KGluZm9fY2FwX3N1cHBvcnRl + ZCkKICAgICAgICAgICAgICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2VydF9w + YXRoOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19UTFNfQ0VSVCJd + ID0gKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi52YWxpZGF0ZV9yZ3dfZW5kcG9p + bnRfdGxzX2NlcnQoKQogICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAg + ICAgIyBpZiB0aGVyZSBpcyBubyBlcnJvciwgc2V0IHRoZSBSR1dfRU5EUE9JTlQKICAgICAgICAg + ICAgICAgICAgICBpZiBlcnIgIT0gIi0xIjoKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5v + dXRfbWFwWyJSR1dfRU5EUE9JTlQiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50CiAg + ICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIGVyciA9ICJQbGVhc2UgcHJv + dmlkZSBhbGwgdGhlIFJHVyBtdWx0aXNpdGUgcGFyYW1ldGVycyBvciBub25lIG9mIHRoZW0iCiAg + ICAgICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShlcnIpCgogICAgZGVmIGdlbl9zaGVs + bF9vdXQoc2VsZik6CiAgICAgICAgc2VsZi5fZ2VuX291dHB1dF9tYXAoKQogICAgICAgIHNoT3V0 + SU8gPSBTdHJpbmdJTygpCiAgICAgICAgZm9yIGssIHYgaW4gc2VsZi5vdXRfbWFwLml0ZW1zKCk6 + CiAgICAgICAgICAgIGlmIHYgYW5kIGsgbm90IGluIHNlbGYuX2V4Y2x1ZGVkX2tleXM6CiAgICAg + ICAgICAgICAgICBzaE91dElPLndyaXRlKGYiZXhwb3J0IHtrfT17dn17TElORVNFUH0iKQogICAg + ICAgIHNoT3V0ID0gc2hPdXRJTy5nZXR2YWx1ZSgpCiAgICAgICAgc2hPdXRJTy5jbG9zZSgpCiAg + ICAgICAgcmV0dXJuIHNoT3V0CgogICAgZGVmIGdlbl9qc29uX291dChzZWxmKToKICAgICAgICBz + ZWxmLl9nZW5fb3V0cHV0X21hcCgpCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVu + OgogICAgICAgICAgICByZXR1cm4gIiIKICAgICAgICBqc29uX291dCA9IFsKICAgICAgICAgICAg + ewogICAgICAgICAgICAgICAgIm5hbWUiOiAiZXh0ZXJuYWwtY2x1c3Rlci11c2VyLWNvbW1hbmQi + LAogICAgICAgICAgICAgICAgImtpbmQiOiAiQ29uZmlnTWFwIiwKICAgICAgICAgICAgICAgICJk + YXRhIjogewogICAgICAgICAgICAgICAgICAgICJhcmdzIjogc2VsZi5vdXRfbWFwWyJBUkdTIl0s + CiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAg + ICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtbW9uLWVuZHBvaW50cyIsCiAgICAgICAgICAgICAg + ICAia2luZCI6ICJDb25maWdNYXAiLAogICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAg + ICAgICAgICAgICAgImRhdGEiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfQ0VQSF9NT05f + REFUQSJdLAogICAgICAgICAgICAgICAgICAgICJtYXhNb25JZCI6ICIwIiwKICAgICAgICAgICAg + ICAgICAgICAibWFwcGluZyI6ICJ7fSIsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9 + LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtbW9uIiwK + ICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6 + IHsKICAgICAgICAgICAgICAgICAgICAiYWRtaW4tc2VjcmV0IjogImFkbWluLXNlY3JldCIsCiAg + ICAgICAgICAgICAgICAgICAgImZzaWQiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfRlNJ + RCJdLAogICAgICAgICAgICAgICAgICAgICJtb24tc2VjcmV0IjogIm1vbi1zZWNyZXQiLAogICAg + ICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAg + ICAgIm5hbWUiOiAicm9vay1jZXBoLW9wZXJhdG9yLWNyZWRzIiwKICAgICAgICAgICAgICAgICJr + aW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAg + ICAgICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX1VTRVJOQU1FIl0sCiAg + ICAgICAgICAgICAgICAgICAgInVzZXJLZXkiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxf + VVNFUl9TRUNSRVQiXSwKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAg + XQoKICAgICAgICAjIGlmICdNT05JVE9SSU5HX0VORFBPSU5UJyBleGlzdHMsIHRoZW4gb25seSBh + ZGQgJ21vbml0b3JpbmctZW5kcG9pbnQnIHRvIENsdXN0ZXIKICAgICAgICBpZiAoCiAgICAgICAg + ICAgIHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVCJdCiAgICAgICAgICAgIGFuZCBz + ZWxmLm91dF9tYXBbIk1PTklUT1JJTkdfRU5EUE9JTlRfUE9SVCJdCiAgICAgICAgKToKICAgICAg + ICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAg + ICAgICJuYW1lIjogIm1vbml0b3JpbmctZW5kcG9pbnQiLAogICAgICAgICAgICAgICAgICAgICJr + aW5kIjogIkNlcGhDbHVzdGVyIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAg + ICAgICAgICAgICAgICAgICAgIk1vbml0b3JpbmdFbmRwb2ludCI6IHNlbGYub3V0X21hcFsiTU9O + SVRPUklOR19FTkRQT0lOVCJdLAogICAgICAgICAgICAgICAgICAgICAgICAiTW9uaXRvcmluZ1Bv + cnQiOiBzZWxmLm91dF9tYXBbIk1PTklUT1JJTkdfRU5EUE9JTlRfUE9SVCJdLAogICAgICAgICAg + ICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgIyBp + ZiAnQ1NJX1JCRF9OT0RFX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNzaS1y + YmQtcHJvdmlzaW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRf + bWFwWyJDU0lfUkJEX05PREVfU0VDUkVUIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsi + Q1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291 + dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBm + InJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAg + ICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRh + IjogewogICAgICAgICAgICAgICAgICAgICAgICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJDU0lf + UkJEX05PREVfU0VDUkVUX05BTUUiXSwKICAgICAgICAgICAgICAgICAgICAgICAgInVzZXJLZXki + OiBzZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVQiXSwKICAgICAgICAgICAgICAgICAg + ICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnQ1NJX1JC + RF9QUk9WSVNJT05FUl9TRUNSRVQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktcmJk + LXByb3Zpc2lvbmVyJyBTZWNyZXQKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21h + cFsiQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2VsZi5vdXRf + bWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FIl0KICAgICAgICApOgogICAgICAg + ICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAg + ICAgIm5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNS + RVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAg + ICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgInVzZXJJRCI6 + IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSJdLAogICAgICAg + ICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9QUk9WSVNJ + T05FUl9TRUNSRVQiXSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgfQog + ICAgICAgICAgICApCiAgICAgICAgIyBpZiAnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVQn + IGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktY2VwaGZzLXByb3Zpc2lvbmVyJyBTZWNy + ZXQKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9W + SVNJT05FUl9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZT + X1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291 + dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBm + InJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSdd + fSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAg + ICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluSUQiOiBzZWxmLm91 + dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXSwKICAgICAgICAgICAg + ICAgICAgICAgICAgImFkbWluS2V5Ijogc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lP + TkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAg + ICAgICAgICAgICkKICAgICAgICAjIGlmICdDU0lfQ0VQSEZTX05PREVfU0VDUkVUJyBleGlzdHMs + IHRoZW4gb25seSBhZGQgJ3Jvb2stY3NpLWNlcGhmcy1ub2RlJyBTZWNyZXQKICAgICAgICBpZiAo + CiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVCJdCiAgICAg + ICAgICAgIGFuZCBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9TRUNSRVRfTkFNRSJdCiAg + ICAgICAgKToKICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewog + ICAgICAgICAgICAgICAgICAgICJuYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9DRVBI + RlNfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2Vj + cmV0IiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAg + ICAgImFkbWluSUQiOiBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9TRUNSRVRfTkFNRSJd + LAogICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5LZXkiOiBzZWxmLm91dF9tYXBbIkNTSV9D + RVBIRlNfTk9ERV9TRUNSRVQiXSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAg + ICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUk9PS19FWFRFUk5BTF9EQVNIQk9BUkRf + TElOSycgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNlcGgtZGFzaGJvYXJkLWxpbmsnIFNl + Y3JldAogICAgICAgIGlmIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5BTF9EQVNIQk9BUkRfTElO + SyJdOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAg + ICAgICAgICAgICAgICAgIm5hbWUiOiAicm9vay1jZXBoLWRhc2hib2FyZC1saW5rIiwKICAgICAg + ICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRh + IjogewogICAgICAgICAgICAgICAgICAgICAgICAidXNlcklEIjogImNlcGgtZGFzaGJvYXJkLWxp + bmsiLAogICAgICAgICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiUk9P + S19FWFRFUk5BTF9EQVNIQk9BUkRfTElOSyJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAg + ICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdSQURPU19OQU1FU1BBQ0Un + IGV4aXN0cywgdGhlbiBvbmx5IGFkZCB0aGUgIlJBRE9TX05BTUVTUEFDRSIgbmFtZXNwYWNlCiAg + ICAgICAgaWYgKAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJBRE9TX05BTUVTUEFDRSJdCiAg + ICAgICAgICAgIGFuZCBzZWxmLm91dF9tYXBbIlJFU1RSSUNURURfQVVUSF9QRVJNSVNTSU9OIl0K + ICAgICAgICAgICAgYW5kIG5vdCBzZWxmLm91dF9tYXBbIlJCRF9NRVRBREFUQV9FQ19QT09MX05B + TUUiXQogICAgICAgICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAg + ICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyYWRvcy1uYW1lc3BhY2UiLAogICAg + ICAgICAgICAgICAgICAgICJraW5kIjogIkNlcGhCbG9ja1Bvb2xSYWRvc05hbWVzcGFjZSIsCiAg + ICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJyYWRv + c05hbWVzcGFjZU5hbWUiOiBzZWxmLm91dF9tYXBbIlJBRE9TX05BTUVTUEFDRSJdLAogICAgICAg + ICAgICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21hcFsiUkJEX1BPT0xfTkFNRSJdLAog + ICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAg + ICAgICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAg + ICAgICAgICJuYW1lIjogImNlcGgtcmJkLXJhZG9zLW5hbWVzcGFjZSIsCiAgICAgICAgICAgICAg + ICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6 + IHsKICAgICAgICAgICAgICAgICAgICAgICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9QT09M + X05BTUUiXSwKICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9wcm92 + aXNpb25lci1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BST1ZJ + U0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9y + YWdlLms4cy5pby9jb250cm9sbGVyLWV4cGFuZC1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v + dXRfbWFwWydDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAg + ICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9ub2RlLXN0YWdlLXNlY3JldC1uYW1lIjog + ZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAg + ICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAg + IGVsc2U6CiAgICAgICAgICAgIGlmIHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xf + TkFNRSJdOgogICAgICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAg + ICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQiLAogICAgICAg ICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAogICAgICAgICAgICAgICAg - ICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21h - cFsiUkJEX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu - azhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NT - SV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAg - ICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhwYW5kLXNlY3JldC1uYW1lIjogZiJy - b29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAog - ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL25vZGUtc3RhZ2Utc2Vj - cmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1F - J119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAg - ICApCiAgICAgICAgZWxzZToKICAgICAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJSQkRfTUVUQURB - VEFfRUNfUE9PTF9OQU1FIl06CiAgICAgICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAg - ICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJjZXBoLXJi - ZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAg - ICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAg - ImRhdGFQb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1FIl0sCiAgICAgICAgICAgICAg - ICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xf - TkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9w - cm92aXNpb25lci1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BS - T1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJj - c2kuc3RvcmFnZS5rOHMuaW8vY29udHJvbGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2st - e3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAg - ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL25vZGUtc3RhZ2Utc2Vj - cmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1F - J119IiwKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICB9CiAg - ICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBqc29uX291 - dC5hcHBlbmQoCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAi - bmFtZSI6ICJjZXBoLXJiZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3Jh - Z2VDbGFzcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAg - ICAgICAgICAgICAgICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9QT09MX05BTUUiXSwKICAg + ICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkYXRhUG9vbCI6 + IHNlbGYub3V0X21hcFsiUkJEX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAg + ICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9NRVRBREFUQV9FQ19QT09MX05BTUUiXSwKICAg ICAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXIt c2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9T RUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu @@ -1549,147 +1542,159 @@ data: ICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9ub2RlLXN0YWdlLXNlY3JldC1uYW1lIjog ZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAg ICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAg - ICAgKQoKICAgICAgICAjIGlmICdUT1BPTE9HWV9QT09MUycsICdUT1BPTE9HWV9GQUlMVVJFX0RP - TUFJTl9MQUJFTCcsICdUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMnICBleGlzdHMsCiAg - ICAgICAgIyB0aGVuIG9ubHkgYWRkICd0b3BvbG9neScgU3RvcmFnZUNsYXNzCiAgICAgICAgaWYg - KAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0KICAgICAgICAgICAg - YW5kIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fTEFCRUwiXQogICAgICAg - ICAgICBhbmQgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXQog - ICAgICAgICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsK - ICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJjZXBoLXJiZC10b3BvbG9neSIsCiAgICAgICAg - ICAgICAgICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwKICAgICAgICAgICAgICAgICAgICAi - ZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgInRvcG9sb2d5RmFpbHVyZURvbWFpbkxh - YmVsIjogc2VsZi5vdXRfbWFwWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRPUE9MT0dZ - X0ZBSUxVUkVfRE9NQUlOX0xBQkVMIgogICAgICAgICAgICAgICAgICAgICAgICBdLAogICAgICAg - ICAgICAgICAgICAgICAgICAidG9wb2xvZ3lGYWlsdXJlRG9tYWluVmFsdWVzIjogc2VsZi5vdXRf - bWFwWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlO - X1ZBTFVFUyIKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgICAg - ICAgInRvcG9sb2d5UG9vbHMiOiBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0sCiAgICAg - ICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXItc2VjcmV0 - LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRf - TkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vY29u - dHJvbGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JC - RF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJj - c2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v - dXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAg - IH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgIyBpZiAnQ0VQSEZT - X0ZTX05BTUUnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAnY2VwaGZzJyBTdG9yYWdlQ2xhc3MKICAg - ICAgICBpZiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl06CiAgICAgICAgICAgIGpzb25f - b3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6 - ICJjZXBoZnMiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAg - ICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJmc05h - bWUiOiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAg - ICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJDRVBIRlNfUE9PTF9OQU1FIl0sCiAgICAgICAgICAg - ICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXItc2VjcmV0LW5hbWUi - OiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFN - RSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vY29udHJv - bGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhG - U19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJj - c2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v - dXRfbWFwWydDU0lfQ0VQSEZTX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAg - ICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdSR1df - RU5EUE9JTlQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAnY2VwaC1yZ3cnIFN0b3JhZ2VDbGFzcwog - ICAgICAgIGlmIHNlbGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl06CiAgICAgICAgICAgIGpzb25f + ICAgKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAog + ICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2Vw + aC1yYmQiLAogICAgICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAog + ICAgICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAg + ICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1FIl0sCiAgICAgICAgICAgICAg + ICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1l + IjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUn + XX0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9jb250 + cm9sbGVyLWV4cGFuZC1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJE + X1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAg + ICJjc2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2Vs + Zi5vdXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAg + ICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKCiAgICAg + ICAgIyBpZiAnVE9QT0xPR1lfUE9PTFMnLCAnVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fTEFCRUwn + LCAnVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fVkFMVUVTJyAgZXhpc3RzLAogICAgICAgICMgdGhl + biBvbmx5IGFkZCAndG9wb2xvZ3knIFN0b3JhZ2VDbGFzcwogICAgICAgIGlmICgKICAgICAgICAg + ICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdCiAgICAgICAgICAgIGFuZCBzZWxmLm91 + dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlOX0xBQkVMIl0KICAgICAgICAgICAgYW5kIHNl + bGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fVkFMVUVTIl0KICAgICAgICApOgog + ICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAg + ICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQtdG9wb2xvZ3kiLAogICAgICAgICAgICAgICAgICAg + ICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAg + ICAgICAgICAgICAgICAgICAgICAgICJ0b3BvbG9neUZhaWx1cmVEb21haW5MYWJlbCI6IHNlbGYu + b3V0X21hcFsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUT1BPTE9HWV9GQUlMVVJFX0RP + TUFJTl9MQUJFTCIKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAg + ICAgICAgInRvcG9sb2d5RmFpbHVyZURvbWFpblZhbHVlcyI6IHNlbGYub3V0X21hcFsKICAgICAg + ICAgICAgICAgICAgICAgICAgICAgICJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiCiAg + ICAgICAgICAgICAgICAgICAgICAgIF0sCiAgICAgICAgICAgICAgICAgICAgICAgICJ0b3BvbG9n + eVBvb2xzIjogc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdLAogICAgICAgICAgICAgICAg + ICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJy + b29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAog + ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhw + YW5kLXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9O + RVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu + azhzLmlvL25vZGUtc3RhZ2Utc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJ + X1JCRF9OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAg + ICAgICAgICAgfQogICAgICAgICAgICApCgogICAgICAgICMgaWYgJ0NFUEhGU19GU19OQU1FJyBl + eGlzdHMsIHRoZW4gb25seSBhZGQgJ2NlcGhmcycgU3RvcmFnZUNsYXNzCiAgICAgICAgaWYgc2Vs + Zi5vdXRfbWFwWyJDRVBIRlNfRlNfTkFNRSJdOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQo + CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaGZzIiwK + ICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAogICAgICAgICAgICAg + ICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAiZnNOYW1lIjogc2VsZi5v + dXRfbWFwWyJDRVBIRlNfRlNfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAicG9vbCI6 + IHNlbGYub3V0X21hcFsiQ0VQSEZTX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAg + ICAiY3NpLnN0b3JhZ2UuazhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJyb29rLXtz + ZWxmLm91dF9tYXBbJ0NTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAogICAg + ICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhwYW5k + LXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9DRVBIRlNfUFJPVklTSU9O + RVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu + azhzLmlvL25vZGUtc3RhZ2Utc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJ + X0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAg + ICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUkdXX0VORFBPSU5UJyBl + eGlzdHMsIHRoZW4gb25seSBhZGQgJ2NlcGgtcmd3JyBTdG9yYWdlQ2xhc3MKICAgICAgICBpZiBz + ZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQo + CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yZ3ci + LAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAgICAgICAg + ICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJlbmRwb2ludCI6IHNl + bGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJwb29s + UHJlZml4Ijogc2VsZi5vdXRfbWFwWyJSR1dfUE9PTF9QUkVGSVgiXSwKICAgICAgICAgICAgICAg + ICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgICAgIGpzb25f b3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6 - ICJjZXBoLXJndyIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwK - ICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImVu - ZHBvaW50Ijogc2VsZi5vdXRfbWFwWyJSR1dfRU5EUE9JTlQiXSwKICAgICAgICAgICAgICAgICAg - ICAgICAgInBvb2xQcmVmaXgiOiBzZWxmLm91dF9tYXBbIlJHV19QT09MX1BSRUZJWCJdLAogICAg - ICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAg - ICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAg - ICAgICJuYW1lIjogInJndy1hZG1pbi1vcHMtdXNlciIsCiAgICAgICAgICAgICAgICAgICAgImtp - bmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAg - ICAgICAgICAgICAgImFjY2Vzc0tleSI6IHNlbGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VS - X0FDQ0VTU19LRVkiXSwKICAgICAgICAgICAgICAgICAgICAgICAgInNlY3JldEtleSI6IHNlbGYu - b3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JFVF9LRVkiXSwKICAgICAgICAgICAgICAg - ICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUkdX - X1RMU19DRVJUJyBleGlzdHMsIHRoZW4gb25seSBhZGQgdGhlICJjZXBoLXJndy10bHMtY2VydCIg - c2VjcmV0CiAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJSR1dfVExTX0NFUlQiXToKICAgICAgICAg - ICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAg - ICJuYW1lIjogImNlcGgtcmd3LXRscy1jZXJ0IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6 - ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAg - ICAgICAgICAiY2VydCI6IHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl0sCiAgICAgICAgICAg - ICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQoKICAgICAgICByZXR1 - cm4ganNvbi5kdW1wcyhqc29uX291dCkgKyBMSU5FU0VQCgogICAgZGVmIHVwZ3JhZGVfdXNlcnNf - cGVybWlzc2lvbnMoc2VsZik6CiAgICAgICAgdXNlcnMgPSBbCiAgICAgICAgICAgICJjbGllbnQu - Y3NpLWNlcGhmcy1ub2RlIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv - bmVyIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktcmJkLW5vZGUiLAogICAgICAgICAgICAiY2xp - ZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiLAogICAgICAgICAgICAiY2xpZW50LmhlYWx0aGNoZWNr - ZXIiLAogICAgICAgIF0KICAgICAgICBpZiBzZWxmLnJ1bl9hc191c2VyICE9ICIiIGFuZCBzZWxm - LnJ1bl9hc191c2VyIG5vdCBpbiB1c2VyczoKICAgICAgICAgICAgdXNlcnMuYXBwZW5kKHNlbGYu - cnVuX2FzX3VzZXIpCiAgICAgICAgZm9yIHVzZXIgaW4gdXNlcnM6CiAgICAgICAgICAgIHNlbGYu - dXBncmFkZV91c2VyX3Blcm1pc3Npb25zKHVzZXIpCgogICAgZGVmIGdldF9yZ3dfcG9vbF9uYW1l - X2R1cmluZ191cGdyYWRlKHNlbGYsIHVzZXIsIGNhcHMpOgogICAgICAgIGlmIHVzZXIgPT0gImNs - aWVudC5oZWFsdGhjaGVja2VyIjoKICAgICAgICAgICAgIyB3aGVuIGFkbWluIGhhcyBub3QgcHJv - dmlkZWQgcmd3IHBvb2wgbmFtZSBkdXJpbmcgdXBncmFkZSwKICAgICAgICAgICAgIyBnZXQgdGhl - IHJndyBwb29sIG5hbWUgZnJvbSBjbGllbnQuaGVhbHRoY2hlY2tlciB1c2VyIHdoaWNoIHdhcyB1 - c2VkIGR1cmluZyBjb25uZWN0aW9uCiAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2Vy - LnJnd19wb29sX3ByZWZpeDoKICAgICAgICAgICAgICAgICMgVG8gZ2V0IHZhbHVlICdkZWZhdWx0 - JyB3aGljaCBpcyByZ3cgcG9vbCBuYW1lIGZyb20gJ2FsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3 - Lm1ldGEnCiAgICAgICAgICAgICAgICBwYXR0ZXJuID0gciJwb29sPSguKj8pXC5yZ3dcLm1ldGEi - CiAgICAgICAgICAgICAgICBtYXRjaCA9IHJlLnNlYXJjaChwYXR0ZXJuLCBjYXBzKQogICAgICAg - ICAgICAgICAgaWYgbWF0Y2g6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5y - Z3dfcG9vbF9wcmVmaXggPSBtYXRjaC5ncm91cCgxKQogICAgICAgICAgICAgICAgZWxzZToKICAg - ICAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg - ICAgICAgICAgICAgICAgICAiZmFpbGVkIHRvIGdldCByZ3cgcG9vbCBuYW1lIGZvciB1cGdyYWRl - IgogICAgICAgICAgICAgICAgICAgICkKCiAgICBkZWYgdXBncmFkZV91c2VyX3Blcm1pc3Npb25z - KHNlbGYsIHVzZXIpOgogICAgICAgICMgY2hlY2sgd2hldGhlciB0aGUgZ2l2ZW4gdXNlciBleGlz - dHMgb3Igbm90CiAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJhdXRoIGdldCIsICJlbnRp - dHkiOiBmInt1c2VyfSIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmV0X3ZhbCwganNvbl9v - dXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAg - IGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHByaW50 - KGYidXNlciB7dXNlcn0gbm90IGZvdW5kIGZvciB1cGdyYWRpbmcuIikKICAgICAgICAgICAgcmV0 - dXJuCiAgICAgICAgZXhpc3RpbmdfY2FwcyA9IGpzb25fb3V0WzBdWyJjYXBzIl0KICAgICAgICBz - ZWxmLmdldF9yZ3dfcG9vbF9uYW1lX2R1cmluZ191cGdyYWRlKHVzZXIsIHN0cihleGlzdGluZ19j - YXBzKSkKICAgICAgICBuZXdfY2FwLCBfID0gc2VsZi5nZXRfY2Fwc19hbmRfZW50aXR5KHVzZXIp - CiAgICAgICAgY2FwX2tleXMgPSBbIm1vbiIsICJtZ3IiLCAib3NkIiwgIm1kcyJdCiAgICAgICAg - Y2FwcyA9IFtdCiAgICAgICAgZm9yIGVhY2hDYXAgaW4gY2FwX2tleXM6CiAgICAgICAgICAgIGN1 - cl9jYXBfdmFsdWVzID0gZXhpc3RpbmdfY2Fwcy5nZXQoZWFjaENhcCwgIiIpCiAgICAgICAgICAg - IG5ld19jYXBfdmFsdWVzID0gbmV3X2NhcC5nZXQoZWFjaENhcCwgIiIpCiAgICAgICAgICAgIGN1 - cl9jYXBfcGVybV9saXN0ID0gWwogICAgICAgICAgICAgICAgeC5zdHJpcCgpIGZvciB4IGluIGN1 - cl9jYXBfdmFsdWVzLnNwbGl0KCIsIikgaWYgeC5zdHJpcCgpCiAgICAgICAgICAgIF0KICAgICAg - ICAgICAgbmV3X2NhcF9wZXJtX2xpc3QgPSBbCiAgICAgICAgICAgICAgICB4LnN0cmlwKCkgZm9y - IHggaW4gbmV3X2NhcF92YWx1ZXMuc3BsaXQoIiwiKSBpZiB4LnN0cmlwKCkKICAgICAgICAgICAg - XQogICAgICAgICAgICAjIGFwcGVuZCBuZXdfY2FwX2xpc3QgdG8gY3VyX2NhcF9saXN0IHRvIG1h - aW50YWluIHRoZSBvcmRlciBvZiBjYXBzCiAgICAgICAgICAgIGN1cl9jYXBfcGVybV9saXN0LmV4 - dGVuZChuZXdfY2FwX3Blcm1fbGlzdCkKICAgICAgICAgICAgIyBlbGltaW5hdGUgZHVwbGljYXRl - cyB3aXRob3V0IHVzaW5nICdzZXQnCiAgICAgICAgICAgICMgc2V0IHJlLW9yZGVycyBpdGVtcyBp - biB0aGUgbGlzdCBhbmQgd2UgaGF2ZSB0byBrZWVwIHRoZSBvcmRlcgogICAgICAgICAgICBuZXdf - Y2FwX2xpc3QgPSBbXQogICAgICAgICAgICBbbmV3X2NhcF9saXN0LmFwcGVuZCh4KSBmb3IgeCBp - biBjdXJfY2FwX3Blcm1fbGlzdCBpZiB4IG5vdCBpbiBuZXdfY2FwX2xpc3RdCiAgICAgICAgICAg - IGV4aXN0aW5nX2NhcHNbZWFjaENhcF0gPSAiLCAiLmpvaW4obmV3X2NhcF9saXN0KQogICAgICAg - ICAgICBpZiBleGlzdGluZ19jYXBzW2VhY2hDYXBdOgogICAgICAgICAgICAgICAgY2Fwcy5hcHBl - bmQoZWFjaENhcCkKICAgICAgICAgICAgICAgIGNhcHMuYXBwZW5kKGV4aXN0aW5nX2NhcHNbZWFj - aENhcF0pCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJwcmVmaXgiOiAiYXV0aCBj - YXBzIiwKICAgICAgICAgICAgImVudGl0eSI6IHVzZXIsCiAgICAgICAgICAgICJjYXBzIjogY2Fw - cywKICAgICAgICAgICAgImZvcm1hdCI6ICJqc29uIiwKICAgICAgICB9CiAgICAgICAgcmV0X3Zh - bCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29u - KQogICAgICAgIGlmIHJldF92YWwgIT0gMDoKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFp - bHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiJ2F1dGggY2FwcyB7dXNlcn0nIGNvbW1h - bmQgZmFpbGVkLlxuIEVycm9yOiB7ZXJyX21zZ30iCiAgICAgICAgICAgICkKICAgICAgICBwcmlu - dChmIlVwZGF0ZWQgdXNlciB7dXNlcn0gc3VjY2Vzc2Z1bGx5LiIpCgogICAgZGVmIG1haW4oc2Vs - Zik6CiAgICAgICAgZ2VuZXJhdGVkX291dHB1dCA9ICIiCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh - cnNlci51cGdyYWRlOgogICAgICAgICAgICBzZWxmLnVwZ3JhZGVfdXNlcnNfcGVybWlzc2lvbnMo - KQogICAgICAgIGVsaWYgc2VsZi5fYXJnX3BhcnNlci5mb3JtYXQgPT0gImpzb24iOgogICAgICAg - ICAgICBnZW5lcmF0ZWRfb3V0cHV0ID0gc2VsZi5nZW5fanNvbl9vdXQoKQogICAgICAgIGVsaWYg - c2VsZi5fYXJnX3BhcnNlci5mb3JtYXQgPT0gImJhc2giOgogICAgICAgICAgICBnZW5lcmF0ZWRf - b3V0cHV0ID0gc2VsZi5nZW5fc2hlbGxfb3V0KCkKICAgICAgICBlbHNlOgogICAgICAgICAgICBy - YWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJVbnN1cHBv - cnRlZCBmb3JtYXQ6IHtzZWxmLl9hcmdfcGFyc2VyLmZvcm1hdH0iCiAgICAgICAgICAgICkKICAg - ICAgICBwcmludChnZW5lcmF0ZWRfb3V0cHV0KQogICAgICAgIGlmIHNlbGYub3V0cHV0X2ZpbGUg - YW5kIGdlbmVyYXRlZF9vdXRwdXQ6CiAgICAgICAgICAgIGZPdXQgPSBvcGVuKHNlbGYub3V0cHV0 - X2ZpbGUsIG1vZGU9InciLCBlbmNvZGluZz0iVVRGLTgiKQogICAgICAgICAgICBmT3V0LndyaXRl - KGdlbmVyYXRlZF9vdXRwdXQpCiAgICAgICAgICAgIGZPdXQuY2xvc2UoKQoKCiMjIyMjIyMjIyMj - IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMj - IyMgTUFJTiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj - IyMjIyMjIyMjIyMjIyMjIyMjIyMjCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICByak9i - aiA9IFJhZG9zSlNPTigpCiAgICB0cnk6CiAgICAgICAgcmpPYmoubWFpbigpCiAgICBleGNlcHQg - RXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbiBhcyBlcnI6CiAgICAgICAgcHJpbnQoZiJFeGVjdXRp - b24gRmFpbGVkOiB7ZXJyfSIpCiAgICAgICAgcmFpc2UgZXJyCiAgICBleGNlcHQgS2V5RXJyb3Ig - YXMga0VycjoKICAgICAgICBwcmludChmIktleUVycm9yOiB7a0Vycn0iKQogICAgZXhjZXB0IE9T - RXJyb3IgYXMgb3NFcnI6CiAgICAgICAgcHJpbnQoZiJFcnJvciB3aGlsZSB0cnlpbmcgdG8gb3V0 - cHV0IHRoZSBkYXRhOiB7b3NFcnJ9IikKICAgIGZpbmFsbHk6CiAgICAgICAgcmpPYmouc2h1dGRv - d24oKQo= + ICJyZ3ctYWRtaW4tb3BzLXVzZXIiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3Jl + dCIsCiAgICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAg + ICJhY2Nlc3NLZXkiOiBzZWxmLm91dF9tYXBbIlJHV19BRE1JTl9PUFNfVVNFUl9BQ0NFU1NfS0VZ + Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJzZWNyZXRLZXkiOiBzZWxmLm91dF9tYXBbIlJH + V19BRE1JTl9PUFNfVVNFUl9TRUNSRVRfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAg + ICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ1JHV19UTFNfQ0VSVCcg + ZXhpc3RzLCB0aGVuIG9ubHkgYWRkIHRoZSAiY2VwaC1yZ3ctdGxzLWNlcnQiIHNlY3JldAogICAg + ICAgIGlmIHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl06CiAgICAgICAgICAgIGpzb25fb3V0 + LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJj + ZXBoLXJndy10bHMtY2VydCIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwK + ICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImNl + cnQiOiBzZWxmLm91dF9tYXBbIlJHV19UTFNfQ0VSVCJdLAogICAgICAgICAgICAgICAgICAgIH0s + CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIGpzb24uZHVt + cHMoanNvbl9vdXQpICsgTElORVNFUAoKICAgIGRlZiB1cGdyYWRlX3VzZXJzX3Blcm1pc3Npb25z + KHNlbGYpOgogICAgICAgIHVzZXJzID0gWwogICAgICAgICAgICAiY2xpZW50LmNzaS1jZXBoZnMt + bm9kZSIsCiAgICAgICAgICAgICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsCiAgICAg + ICAgICAgICJjbGllbnQuY3NpLXJiZC1ub2RlIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktcmJk + LXByb3Zpc2lvbmVyIiwKICAgICAgICAgICAgImNsaWVudC5oZWFsdGhjaGVja2VyIiwKICAgICAg + ICBdCiAgICAgICAgaWYgc2VsZi5ydW5fYXNfdXNlciAhPSAiIiBhbmQgc2VsZi5ydW5fYXNfdXNl + ciBub3QgaW4gdXNlcnM6CiAgICAgICAgICAgIHVzZXJzLmFwcGVuZChzZWxmLnJ1bl9hc191c2Vy + KQogICAgICAgIGZvciB1c2VyIGluIHVzZXJzOgogICAgICAgICAgICBzZWxmLnVwZ3JhZGVfdXNl + cl9wZXJtaXNzaW9ucyh1c2VyKQoKICAgIGRlZiBnZXRfcmd3X3Bvb2xfbmFtZV9kdXJpbmdfdXBn + cmFkZShzZWxmLCB1c2VyLCBjYXBzKToKICAgICAgICBpZiB1c2VyID09ICJjbGllbnQuaGVhbHRo + Y2hlY2tlciI6CiAgICAgICAgICAgICMgd2hlbiBhZG1pbiBoYXMgbm90IHByb3ZpZGVkIHJndyBw + b29sIG5hbWUgZHVyaW5nIHVwZ3JhZGUsCiAgICAgICAgICAgICMgZ2V0IHRoZSByZ3cgcG9vbCBu + YW1lIGZyb20gY2xpZW50LmhlYWx0aGNoZWNrZXIgdXNlciB3aGljaCB3YXMgdXNlZCBkdXJpbmcg + Y29ubmVjdGlvbgogICAgICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9w + cmVmaXg6CiAgICAgICAgICAgICAgICAjIFRvIGdldCB2YWx1ZSAnZGVmYXVsdCcgd2hpY2ggaXMg + cmd3IHBvb2wgbmFtZSBmcm9tICdhbGxvdyByd3ggcG9vbD1kZWZhdWx0LnJndy5tZXRhJwogICAg + ICAgICAgICAgICAgcGF0dGVybiA9IHIicG9vbD0oLio/KVwucmd3XC5tZXRhIgogICAgICAgICAg + ICAgICAgbWF0Y2ggPSByZS5zZWFyY2gocGF0dGVybiwgY2FwcykKICAgICAgICAgICAgICAgIGlm + IG1hdGNoOgogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJl + Zml4ID0gbWF0Y2guZ3JvdXAoMSkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAg + ICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAg + ICAgICAgImZhaWxlZCB0byBnZXQgcmd3IHBvb2wgbmFtZSBmb3IgdXBncmFkZSIKICAgICAgICAg + ICAgICAgICAgICApCgogICAgZGVmIHVwZ3JhZGVfdXNlcl9wZXJtaXNzaW9ucyhzZWxmLCB1c2Vy + KToKICAgICAgICAjIGNoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHVzZXIgZXhpc3RzIG9yIG5vdAog + ICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAiYXV0aCBnZXQiLCAiZW50aXR5IjogZiJ7dXNl + cn0iLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgIHJldF92YWwsIGpzb25fb3V0LCBlcnJfbXNn + ID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICBpZiByZXRfdmFs + ICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICBwcmludChmInVzZXIge3Vz + ZXJ9IG5vdCBmb3VuZCBmb3IgdXBncmFkaW5nLiIpCiAgICAgICAgICAgIHJldHVybgogICAgICAg + IGV4aXN0aW5nX2NhcHMgPSBqc29uX291dFswXVsiY2FwcyJdCiAgICAgICAgc2VsZi5nZXRfcmd3 + X3Bvb2xfbmFtZV9kdXJpbmdfdXBncmFkZSh1c2VyLCBzdHIoZXhpc3RpbmdfY2FwcykpCiAgICAg + ICAgbmV3X2NhcCwgXyA9IHNlbGYuZ2V0X2NhcHNfYW5kX2VudGl0eSh1c2VyKQogICAgICAgIGNh + cF9rZXlzID0gWyJtb24iLCAibWdyIiwgIm9zZCIsICJtZHMiXQogICAgICAgIGNhcHMgPSBbXQog + ICAgICAgIGZvciBlYWNoQ2FwIGluIGNhcF9rZXlzOgogICAgICAgICAgICBjdXJfY2FwX3ZhbHVl + cyA9IGV4aXN0aW5nX2NhcHMuZ2V0KGVhY2hDYXAsICIiKQogICAgICAgICAgICBuZXdfY2FwX3Zh + bHVlcyA9IG5ld19jYXAuZ2V0KGVhY2hDYXAsICIiKQogICAgICAgICAgICBjdXJfY2FwX3Blcm1f + bGlzdCA9IFsKICAgICAgICAgICAgICAgIHguc3RyaXAoKSBmb3IgeCBpbiBjdXJfY2FwX3ZhbHVl + cy5zcGxpdCgiLCIpIGlmIHguc3RyaXAoKQogICAgICAgICAgICBdCiAgICAgICAgICAgIG5ld19j + YXBfcGVybV9saXN0ID0gWwogICAgICAgICAgICAgICAgeC5zdHJpcCgpIGZvciB4IGluIG5ld19j + YXBfdmFsdWVzLnNwbGl0KCIsIikgaWYgeC5zdHJpcCgpCiAgICAgICAgICAgIF0KICAgICAgICAg + ICAgIyBhcHBlbmQgbmV3X2NhcF9saXN0IHRvIGN1cl9jYXBfbGlzdCB0byBtYWludGFpbiB0aGUg + b3JkZXIgb2YgY2FwcwogICAgICAgICAgICBjdXJfY2FwX3Blcm1fbGlzdC5leHRlbmQobmV3X2Nh + cF9wZXJtX2xpc3QpCiAgICAgICAgICAgICMgZWxpbWluYXRlIGR1cGxpY2F0ZXMgd2l0aG91dCB1 + c2luZyAnc2V0JwogICAgICAgICAgICAjIHNldCByZS1vcmRlcnMgaXRlbXMgaW4gdGhlIGxpc3Qg + YW5kIHdlIGhhdmUgdG8ga2VlcCB0aGUgb3JkZXIKICAgICAgICAgICAgbmV3X2NhcF9saXN0ID0g + W10KICAgICAgICAgICAgW25ld19jYXBfbGlzdC5hcHBlbmQoeCkgZm9yIHggaW4gY3VyX2NhcF9w + ZXJtX2xpc3QgaWYgeCBub3QgaW4gbmV3X2NhcF9saXN0XQogICAgICAgICAgICBleGlzdGluZ19j + YXBzW2VhY2hDYXBdID0gIiwgIi5qb2luKG5ld19jYXBfbGlzdCkKICAgICAgICAgICAgaWYgZXhp + c3RpbmdfY2Fwc1tlYWNoQ2FwXToKICAgICAgICAgICAgICAgIGNhcHMuYXBwZW5kKGVhY2hDYXAp + CiAgICAgICAgICAgICAgICBjYXBzLmFwcGVuZChleGlzdGluZ19jYXBzW2VhY2hDYXBdKQogICAg + ICAgIGNtZF9qc29uID0gewogICAgICAgICAgICAicHJlZml4IjogImF1dGggY2FwcyIsCiAgICAg + ICAgICAgICJlbnRpdHkiOiB1c2VyLAogICAgICAgICAgICAiY2FwcyI6IGNhcHMsCiAgICAgICAg + ICAgICJmb3JtYXQiOiAianNvbiIsCiAgICAgICAgfQogICAgICAgIHJldF92YWwsIGpzb25fb3V0 + LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICBp + ZiByZXRfdmFsICE9IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRp + b24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGNhcHMge3VzZXJ9JyBjb21tYW5kIGZhaWxlZC5c + biBFcnJvcjoge2Vycl9tc2d9IgogICAgICAgICAgICApCiAgICAgICAgcHJpbnQoZiJVcGRhdGVk + IHVzZXIge3VzZXJ9IHN1Y2Nlc3NmdWxseS4iKQoKICAgIGRlZiBtYWluKHNlbGYpOgogICAgICAg + IGdlbmVyYXRlZF9vdXRwdXQgPSAiIgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudXBncmFk + ZToKICAgICAgICAgICAgc2VsZi51cGdyYWRlX3VzZXJzX3Blcm1pc3Npb25zKCkKICAgICAgICBl + bGlmIHNlbGYuX2FyZ19wYXJzZXIuZm9ybWF0ID09ICJqc29uIjoKICAgICAgICAgICAgZ2VuZXJh + dGVkX291dHB1dCA9IHNlbGYuZ2VuX2pzb25fb3V0KCkKICAgICAgICBlbGlmIHNlbGYuX2FyZ19w + YXJzZXIuZm9ybWF0ID09ICJiYXNoIjoKICAgICAgICAgICAgZ2VuZXJhdGVkX291dHB1dCA9IHNl + bGYuZ2VuX3NoZWxsX291dCgpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmFpc2UgRXhlY3V0 + aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiVW5zdXBwb3J0ZWQgZm9ybWF0 + OiB7c2VsZi5fYXJnX3BhcnNlci5mb3JtYXR9IgogICAgICAgICAgICApCiAgICAgICAgcHJpbnQo + Z2VuZXJhdGVkX291dHB1dCkKICAgICAgICBpZiBzZWxmLm91dHB1dF9maWxlIGFuZCBnZW5lcmF0 + ZWRfb3V0cHV0OgogICAgICAgICAgICBmT3V0ID0gb3BlbihzZWxmLm91dHB1dF9maWxlLCBtb2Rl + PSJ3IiwgZW5jb2Rpbmc9IlVURi04IikKICAgICAgICAgICAgZk91dC53cml0ZShnZW5lcmF0ZWRf + b3V0cHV0KQogICAgICAgICAgICBmT3V0LmNsb3NlKCkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMj + IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIE1BSU4gIyMj + IyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj + IyMjIyMjIyMjIwppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgcmpPYmogPSBSYWRvc0pT + T04oKQogICAgdHJ5OgogICAgICAgIHJqT2JqLm1haW4oKQogICAgZXhjZXB0IEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24gYXMgZXJyOgogICAgICAgIHByaW50KGYiRXhlY3V0aW9uIEZhaWxlZDog + e2Vycn0iKQogICAgICAgIHJhaXNlIGVycgogICAgZXhjZXB0IEtleUVycm9yIGFzIGtFcnI6CiAg + ICAgICAgcHJpbnQoZiJLZXlFcnJvcjoge2tFcnJ9IikKICAgIGV4Y2VwdCBPU0Vycm9yIGFzIG9z + RXJyOgogICAgICAgIHByaW50KGYiRXJyb3Igd2hpbGUgdHJ5aW5nIHRvIG91dHB1dCB0aGUgZGF0 + YToge29zRXJyfSIpCiAgICBmaW5hbGx5OgogICAgICAgIHJqT2JqLnNodXRkb3duKCkK kind: ConfigMap metadata: name: rook-ceph-external-cluster-script-config diff --git a/build/csv/ceph/rook-ceph-operator.clusterserviceversion.yaml b/build/csv/ceph/rook-ceph-operator.clusterserviceversion.yaml index f8db3f5e62a1..fe419bffa43a 100644 --- a/build/csv/ceph/rook-ceph-operator.clusterserviceversion.yaml +++ b/build/csv/ceph/rook-ceph-operator.clusterserviceversion.yaml @@ -277,1473 +277,1466 @@ metadata: bGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMiLCAib3NkIiwgInByb2ZpbGUgcmJk LXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBwb29s PS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyB4IHBv - b2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJdLCAiZW50aXR5IjogImNsaWVudC5oZWFsdGhj - aGVja2VyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUi - fSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuaGVhbHRoY2hlY2tlciIsImtl - eSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNscmRBPT0iLCJjYXBzIjp7Im1v - biI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1cyIsIm9zZCI6InByb2ZpbGUg - cmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBw - b29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyB4 - IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9v - dXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJwcm9maWxlIHJiZCwg - YWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAib3NkIiwgInByb2ZpbGUgcmJkIl0sICJl - bnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtbm9kZSIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgi - OiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5IjoiY2xp - ZW50LmNzaS1yYmQtbm9kZSIsImtleSI6IkFRQk9nck5lSGJLMUF4QUF1YllCZVY4UzFVL0dQenE1 - U1ZlcTZnPT0iLCJjYXBzIjp7Im1vbiI6InByb2ZpbGUgcmJkLCBhbGxvdyBjb21tYW5kICdvc2Qg - YmxvY2tsaXN0JyIsIm9zZCI6InByb2ZpbGUgcmJkIn19XSIiIgogICAgICAgIHNlbGYuY21kX291 - dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgInByb2ZpbGUgcmJkLCBh - bGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwg - InByb2ZpbGUgcmJkIl0sICJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiLCAi + b2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCIsICJtZHMiLCAiYWxsb3cgKiJdLCAiZW50aXR5 + IjogImNsaWVudC5oZWFsdGhjaGVja2VyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJh + dXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQu + aGVhbHRoY2hlY2tlciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNs + cmRBPT0iLCJjYXBzIjp7Im1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1 + cyIsIm9zZCI6InByb2ZpbGUgcmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5y + Z3cubWV0YSwgYWxsb3cgciBwb29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJn + dy5jb250cm9sLCBhbGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCIsIm1kcyI6 + ImFsbG93ICoifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAg + IiIieyJjYXBzIjogWyJtb24iLCAicHJvZmlsZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9j + a2xpc3QnIiwgIm9zZCIsICJwcm9maWxlIHJiZCJdLCAiZW50aXR5IjogImNsaWVudC5jc2ktcmJk + LW5vZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9 + IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktcmJkLW5vZGUiLCJrZXki + OiJBUUJPZ3JOZUhiSzFBeEFBdWJZQmVWOFMxVS9HUHpxNVNWZXE2Zz09IiwiY2FwcyI6eyJtb24i + OiJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJwcm9m + aWxlIHJiZCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAi + IiJ7ImNhcHMiOiBbIm1vbiIsICJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2Nr + bGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIsICJwcm9maWxlIHJiZCJdLCAiZW50aXR5 + IjogImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZp + eCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJj + bGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIsImtleSI6IkFRQk5nck5lMWdleUt4QUE4ZWtWaVJk + RStoc3M1T3dlWUJrd05nPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoicHJvZmls + ZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwib3NkIjoicHJvZmlsZSByYmQi + fX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBz + IjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdy + IiwgImFsbG93IHJ3IiwgIm9zZCIsICJhbGxvdyBydyB0YWcgY2VwaGZzICo9KiIsICJtZHMiLCAi + YWxsb3cgcnciXSwgImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1ub2RlIiwgImZvcm1hdCI6 + ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAi + IiJbeyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1ub2RlIiwia2V5IjoiQVFCT2dyTmVFTnVu + S3hBQVBDbWdFN1I2RzhEY1huYUoxRjMycWc9PSIsImNhcHMiOnsibWRzIjoiYWxsb3cgcnciLCJt + Z3IiOiJhbGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xp + c3QnIiwib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyAqPSoifX1dIiIiCiAgICAgICAgc2VsZi5j + bWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBzIjogWyJtb24iLCAiYWxsb3cgciwg + YWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIs + ICJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiLCAibWRzIiwgImFsbG93ICoiXSwgImVu + dGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQiOiAianNvbiIs + ICJwcmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50 + aXR5IjoiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCJrZXkiOiJBUUJPZ3JOZUFGZ2NH + QkFBdkdxS09BRDBEM3h4bVZZMFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJhbGxvdyBydyIsIm1v + biI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwib3NkIjoiYWxsb3cg + cncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIiwibWRzIjoiYWxsb3cgKiJ9fV0iIiIKICAgICAgICBz + ZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxv + dyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAi + b3NkIiwgImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiIsICJtZHMiLCAiYWxsb3cgKiJd + LCAiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9y + YWdlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIi + IgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25l + ci1vcGVuc2hpZnQtc3RvcmFnZSIsImtleSI6IkJRQk9nck5lQUZnY0dCQUF2R3FLT0FEMEQzeHht + VlkwUjkxMmRnPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxs + b3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1l + dGFkYXRhPSoiLCAibWRzIjoiYWxsb3cgKiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRf + bWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21t + YW5kICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3 + IHRhZyBjZXBoZnMgbWV0YWRhdGE9bXlmcyIsICJtZHMiLCAiYWxsb3cgKiJdLCAiZW50aXR5Ijog + ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMiLCAi Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9IiIiCiAgICAg - ICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiwia2V5Ijoi - QVFCTmdyTmUxZ2V5S3hBQThla1ZpUmRFK2hzczVPd2VZQmt3Tmc9PSIsImNhcHMiOnsibWdyIjoi - YWxsb3cgcnciLCJtb24iOiJwcm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlz - dCciLCJvc2QiOiJwcm9maWxlIHJiZCJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFw - WwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5k - ICdvc2QgYmxvY2tsaXN0JyIsICJtZ3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3IHRh - ZyBjZXBoZnMgKj0qIiwgIm1kcyIsICJhbGxvdyBydyJdLCAiZW50aXR5IjogImNsaWVudC5jc2kt - Y2VwaGZzLW5vZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNy - ZWF0ZSJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLW5v - ZGUiLCJrZXkiOiJBUUJPZ3JOZUVOdW5LeEFBUENtZ0U3UjZHOERjWG5hSjFGMzJxZz09IiwiY2Fw - cyI6eyJtZHMiOiJhbGxvdyBydyIsIm1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxs - b3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzICo9 - KiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNh - cHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsICJt - Z3IiLCAiYWxsb3cgcnciLCAib3NkIiwgImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiJd - LCAiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJq - c29uIiwgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUifSIiIgogICAgICAgIF0gPSAiIiJb - eyJlbnRpdHkiOiJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsImtleSI6IkFRQk9nck5l - QUZnY0dCQUF2R3FLT0FEMEQzeHhtVlkwUjkxMmRnPT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3 - IiwibW9uIjoiYWxsb3cgciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJh - bGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0 - cHV0X21hcFsKICAgICAgICAgICAgIiIieyJjYXBzIjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cg - Y29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLCAibWdyIiwgImFsbG93IHJ3IiwgIm9zZCIsICJhbGxv - dyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiXSwgImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhm - cy1wcm92aXNpb25lci1vcGVuc2hpZnQtc3RvcmFnZSIsICJmb3JtYXQiOiAianNvbiIsICJwcmVm - aXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5Ijoi - Y2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UiLCJrZXkiOiJC - UUJPZ3JOZUFGZ2NHQkFBdkdxS09BRDBEM3h4bVZZMFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJh - bGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwi - b3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIn19XSIiIgogICAgICAgIHNlbGYu - Y21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgImFsbG93IHIs - IGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJhbGxvdyBydyIsICJvc2Qi - LCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT1teWZzIl0sICJlbnRpdHkiOiAiY2xpZW50 - LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UtbXlmcyIsICJmb3JtYXQi - OiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0g - IiIiW3siZW50aXR5IjoiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0 - b3JhZ2UtbXlmcyIsImtleSI6IkNRQk9nck5lQUZnY0dCQUF2R3FLT0FEMEQzeHhtVlkwUjkxMmRn - PT0iLCJjYXBzIjp7Im1nciI6ImFsbG93IHJ3IiwibW9uIjoiYWxsb3cgciwgYWxsb3cgY29tbWFu - ZCAnb3NkIGJsb2NrbGlzdCciLCJvc2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPW15 - ZnMifX1dIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJj - YXBzIjogWyJtb24iLCAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxv - dyBjb21tYW5kIHZlcnNpb24iLCAibWdyIiwgImFsbG93IGNvbW1hbmQgY29uZmlnIiwgIm9zZCIs - ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3Lm1ldGEs - IGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9ZGVmYXVsdC5yZ3cuY29udHJv - bCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93IHggcG9vbD1kZWZhdWx0LnJn - dy5idWNrZXRzLmluZGV4Il0sICJlbnRpdHkiOiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCAiZm9y - bWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0LW9yLWNyZWF0ZSJ9IiIiCiAgICAgICAg - XSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5oZWFsdGhjaGVja2VyIiwia2V5IjoiQVFERmtiTmVm - dDViRlJBQVRuZExOVVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjogImFsbG93IHIs - IGFsbG93IGNvbW1hbmQgcXVvcnVtX3N0YXR1cywgYWxsb3cgY29tbWFuZCB2ZXJzaW9uIiwgIm1n - ciI6ICJhbGxvdyBjb21tYW5kIGNvbmZpZyIsICJvc2QiOiAicHJvZmlsZSByYmQtcmVhZC1vbmx5 - LCBhbGxvdyByd3ggcG9vbD1kZWZhdWx0LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290 - LCBhbGxvdyBydyBwb29sPWRlZmF1bHQucmd3LmNvbnRyb2wsIGFsbG93IHJ4IHBvb2w9ZGVmYXVs - dC5yZ3cubG9nLCBhbGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIK + ICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5z + aGlmdC1zdG9yYWdlLW15ZnMiLCJrZXkiOiJDUUJPZ3JOZUFGZ2NHQkFBdkdxS09BRDBEM3h4bVZZ + MFI5MTJkZz09IiwiY2FwcyI6eyJtZ3IiOiJhbGxvdyBydyIsIm1vbiI6ImFsbG93IHIsIGFsbG93 + IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRh + ZGF0YT1teWZzIiwibWRzIjoiYWxsb3cgKiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRf + bWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1vbiIsICJhbGxvdyByLCBhbGxvdyBjb21t + YW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQgdmVyc2lvbiIsICJtZ3IiLCAiYWxsb3cg + Y29tbWFuZCBjb25maWciLCAib3NkIiwgInByb2ZpbGUgcmJkLXJlYWQtb25seSwgYWxsb3cgcnd4 + IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBwb29sPS5yZ3cucm9vdCwgYWxsb3cgcncg + cG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyByeCBwb29sPWRlZmF1bHQucmd3LmxvZywg + YWxsb3cgeCBwb29sPWRlZmF1bHQucmd3LmJ1Y2tldHMuaW5kZXgiLCAibWRzIiwgImFsbG93ICoi + XSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJw + cmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5 + IjoiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0NWJGUkFBVG5kTE5VU0VL + cnVvenhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBx + dW9ydW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdyIjogImFsbG93IGNvbW1h + bmQgY29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29s + PWRlZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9 + ZGVmYXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93 + IHggcG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4IiwibWRzIjoiYWxsb3cgKiJ9fV0iIiIK ICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImNhcHMiOiBbIm1v biIsICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQg dmVyc2lvbiIsICJtZ3IiLCAiYWxsb3cgY29tbWFuZCBjb25maWciLCAib3NkIiwgInByb2ZpbGUg cmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwgYWxsb3cgciBw b29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9sLCBhbGxvdyBy eCBwb29sPWRlZmF1bHQucmd3LmxvZywgYWxsb3cgeCBwb29sPWRlZmF1bHQucmd3LmJ1Y2tldHMu - aW5kZXgiXSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNv - biIsICJwcmVmaXgiOiAiYXV0aCBjYXBzIn0iIiIKICAgICAgICBdID0gIiIiW3siZW50aXR5Ijoi - Y2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0NWJGUkFBVG5kTE5VU1JLcnVv - enhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwgYWxsb3cgY29tbWFuZCBxdW9y - dW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdyIjogImFsbG93IGNvbW1hbmQg - Y29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPWRl - ZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9ZGVm - YXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0LnJndy5sb2csIGFsbG93IHgg - cG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4In19XSIiIgogICAgICAgIHNlbGYuY21kX291 - dHB1dF9tYXBbIiIieyJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAibWdyIHNlcnZpY2VzIn0i - IiJdID0gKAogICAgICAgICAgICAiIiJ7ImRhc2hib2FyZCI6ICJodHRwOi8vcm9vay1jZXBoLW1n - ci1hLTU3Y2Y5Zjg0YmMtZjRqbmw6NzAwMC8iLCAicHJvbWV0aGV1cyI6ICJodHRwOi8vcm9vay1j - ZXBoLW1nci1hLTU3Y2Y5Zjg0YmMtZjRqbmw6OTI4My8ifSIiIgogICAgICAgICkKICAgICAgICBz - ZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuaGVh - bHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgog - ICAgICAgIF0gPSAiIiJ7ImRhc2hib2FyZCI6ICJodHRwOi8vcm9vay1jZXBoLW1nci1hLTU3Y2Y5 - Zjg0YmMtZjRqbmw6NzAwMC8iLCAicHJvbWV0aGV1cyI6ICJodHRwOi8vcm9vay1jZXBoLW1nci1h - LTU3Y2Y5Zjg0YmMtZjRqbmw6OTI4My8ifSIiIgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBb - CiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5oZWFsdGhjaGVja2VyIiwgImZvcm1h - dCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVu - dGl0eSI6ImNsaWVudC5oZWFsdGhjaGVja2VyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExO - VVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjogImFsbG93IHIsIGFsbG93IGNvbW1h - bmQgcXVvcnVtX3N0YXR1cywgYWxsb3cgY29tbWFuZCB2ZXJzaW9uIiwgIm1nciI6ICJhbGxvdyBj - b21tYW5kIGNvbmZpZyIsICJvc2QiOiAicHJvZmlsZSByYmQtcmVhZC1vbmx5LCBhbGxvdyByd3gg - cG9vbD1kZWZhdWx0LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290LCBhbGxvdyBydyBw - b29sPWRlZmF1bHQucmd3LmNvbnRyb2wsIGFsbG93IHJ4IHBvb2w9ZGVmYXVsdC5yZ3cubG9nLCBh - bGxvdyB4IHBvb2w9ZGVmYXVsdC5yZ3cuYnVja2V0cy5pbmRleCJ9fV0iIiIKICAgICAgICBzZWxm - LmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuY3NpLWNl - cGhmcy1ub2RlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAg - ICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAg - ICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtbm9kZSIsICJmb3JtYXQiOiAianNvbiIs - ICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIiIgogICAgICAgIHNl - bGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5jc2kt - cmJkLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9 - IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAg - ICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAi - Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0gIiIi - W10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0 - eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lci1vcGVuc2hpZnQtc3RvcmFnZSIsICJm - b3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJb - XSIiIgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5 - IjogImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMi - LCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0g - IiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVu - dGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQiOiAianNvbiIs - ICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGll - bnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVT - RUtydW96eGlaaTNscmRBPT0iLCJjYXBzIjp7Im1vbiI6ImFsbG93IHIiLCAibWdyIjoiYWxsb3cg - cnciLCAib3NkIjoiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIn19XSIiIgogICAgICAg - IHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsibW9uIiwgImFs - bG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJhbGxvdyBydyIs - ICJvc2QiLCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIl0sICJlbnRpdHkiOiAiY2xp - ZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4Ijog - ImF1dGggY2FwcyJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2Vw - aGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExOVVNFS3J1b3p4aVpp - M2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cgciwgIGFsbG93IGNvbW1hbmQgJ29zZCBibG9j - a2xpc3QnIiwgIm1nciI6ImFsbG93IHJ3IiwgIm9zZCI6ImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0 - YWRhdGE9KiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWyd7ImZvcm1hdCI6ICJq - c29uIiwgInByZWZpeCI6ICJzdGF0dXMifSddID0gY2VwaF9zdGF0dXNfc3RyCgogICAgZGVmIHNo - dXRkb3duKHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgZ2V0X2ZzaWQoc2VsZik6CiAgICAg - ICAgcmV0dXJuICJhZjRlMTY3My0wYjcyLTQwMmQtOTkwYS0yMmQyOTE5ZDBmMWMiCgogICAgZGVm - IGNvbmZfcmVhZF9maWxlKHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBkZWYgY29ubmVjdChzZWxm - KToKICAgICAgICBwYXNzCgogICAgZGVmIHBvb2xfZXhpc3RzKHNlbGYsIHBvb2xfbmFtZSk6CiAg - ICAgICAgcmV0dXJuIFRydWUKCiAgICBkZWYgbW9uX2NvbW1hbmQoc2VsZiwgY21kLCBvdXQpOgog - ICAgICAgIGpzb25fY21kID0ganNvbi5sb2FkcyhjbWQpCiAgICAgICAganNvbl9jbWRfc3RyID0g - anNvbi5kdW1wcyhqc29uX2NtZCwgc29ydF9rZXlzPVRydWUpCiAgICAgICAgY21kX291dHB1dCA9 - IHNlbGYuY21kX291dHB1dF9tYXBbanNvbl9jbWRfc3RyXQogICAgICAgIHJldHVybiBzZWxmLnJl - dHVybl92YWwsIGNtZF9vdXRwdXQsIHN0cihzZWxmLmVycl9tZXNzYWdlLmVuY29kZSgidXRmLTgi - KSkKCiAgICBkZWYgX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoc2VsZiwgaG9zdF9uYW1lKToKICAg - ICAgICBpcF9yZWdfeCA9IHJlLmNvbXBpbGUociJcZHsxLDN9LlxkezEsM30uXGR7MSwzfS5cZHsx - LDN9IikKICAgICAgICAjIGlmIHByb3ZpZGVkIGhvc3QgaXMgZGlyZWN0bHkgYW4gSVAgYWRkcmVz - cywgcmV0dXJuIHRoZSBzYW1lCiAgICAgICAgaWYgaXBfcmVnX3gubWF0Y2goaG9zdF9uYW1lKToK - ICAgICAgICAgICAgcmV0dXJuIGhvc3RfbmFtZQogICAgICAgIGltcG9ydCByYW5kb20KCiAgICAg - ICAgaG9zdF9pcCA9IHNlbGYuZHVtbXlfaG9zdF9pcF9tYXAuZ2V0KGhvc3RfbmFtZSwgIiIpCiAg - ICAgICAgaWYgbm90IGhvc3RfaXA6CiAgICAgICAgICAgIGhvc3RfaXAgPSBmIjE3Mi45LntyYW5k - b20ucmFuZGludCgwLCAyNTQpfS57cmFuZG9tLnJhbmRpbnQoMCwgMjU0KX0iCiAgICAgICAgICAg - IHNlbGYuZHVtbXlfaG9zdF9pcF9tYXBbaG9zdF9uYW1lXSA9IGhvc3RfaXAKICAgICAgICBkZWwg - cmFuZG9tCiAgICAgICAgcmV0dXJuIGhvc3RfaXAKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBS - YWRvcyhjb25mZmlsZT1Ob25lKToKICAgICAgICByZXR1cm4gRHVtbXlSYWRvcygpCgoKY2xhc3Mg - UzNBdXRoKEF1dGhCYXNlKToKICAgICIiIkF0dGFjaGVzIEFXUyBBdXRoZW50aWNhdGlvbiB0byB0 - aGUgZ2l2ZW4gUmVxdWVzdCBvYmplY3QuIiIiCgogICAgc2VydmljZV9iYXNlX3VybCA9ICJzMy5h - bWF6b25hd3MuY29tIgoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhY2Nlc3Nfa2V5LCBzZWNyZXRf - a2V5LCBzZXJ2aWNlX3VybD1Ob25lKToKICAgICAgICBpZiBzZXJ2aWNlX3VybDoKICAgICAgICAg - ICAgc2VsZi5zZXJ2aWNlX2Jhc2VfdXJsID0gc2VydmljZV91cmwKICAgICAgICBzZWxmLmFjY2Vz - c19rZXkgPSBzdHIoYWNjZXNzX2tleSkKICAgICAgICBzZWxmLnNlY3JldF9rZXkgPSBzdHIoc2Vj - cmV0X2tleSkKCiAgICBkZWYgX19jYWxsX18oc2VsZiwgcik6CiAgICAgICAgIyBDcmVhdGUgZGF0 - ZSBoZWFkZXIgaWYgaXQgaXMgbm90IGNyZWF0ZWQgeWV0LgogICAgICAgIGlmICJkYXRlIiBub3Qg - aW4gci5oZWFkZXJzIGFuZCAieC1hbXotZGF0ZSIgbm90IGluIHIuaGVhZGVyczoKICAgICAgICAg - ICAgci5oZWFkZXJzWyJkYXRlIl0gPSBmb3JtYXRkYXRlKHRpbWV2YWw9Tm9uZSwgbG9jYWx0aW1l - PUZhbHNlLCB1c2VnbXQ9VHJ1ZSkKICAgICAgICBzaWduYXR1cmUgPSBzZWxmLmdldF9zaWduYXR1 - cmUocikKICAgICAgICBzaWduYXR1cmUgPSBzaWduYXR1cmUuZGVjb2RlKCJ1dGYtOCIpCiAgICAg - ICAgci5oZWFkZXJzWyJBdXRob3JpemF0aW9uIl0gPSBmIkFXUyB7c2VsZi5hY2Nlc3Nfa2V5fTp7 - c2lnbmF0dXJlfSIKICAgICAgICByZXR1cm4gcgoKICAgIGRlZiBnZXRfc2lnbmF0dXJlKHNlbGYs - IHIpOgogICAgICAgIGNhbm9uaWNhbF9zdHJpbmcgPSBzZWxmLmdldF9jYW5vbmljYWxfc3RyaW5n - KHIudXJsLCByLmhlYWRlcnMsIHIubWV0aG9kKQogICAgICAgIGtleSA9IHNlbGYuc2VjcmV0X2tl - eS5lbmNvZGUoInV0Zi04IikKICAgICAgICBtc2cgPSBjYW5vbmljYWxfc3RyaW5nLmVuY29kZSgi - dXRmLTgiKQogICAgICAgIGggPSBobWFjLm5ldyhrZXksIG1zZywgZGlnZXN0bW9kPXNoYSkKICAg - ICAgICByZXR1cm4gZW5jb2Rlc3RyaW5nKGguZGlnZXN0KCkpLnN0cmlwKCkKCiAgICBkZWYgZ2V0 - X2Nhbm9uaWNhbF9zdHJpbmcoc2VsZiwgdXJsLCBoZWFkZXJzLCBtZXRob2QpOgogICAgICAgIHBh - cnNlZHVybCA9IHVybHBhcnNlKHVybCkKICAgICAgICBvYmplY3RrZXkgPSBwYXJzZWR1cmwucGF0 - aFsxOl0KCiAgICAgICAgYnVja2V0ID0gcGFyc2VkdXJsLm5ldGxvY1s6IC1sZW4oc2VsZi5zZXJ2 - aWNlX2Jhc2VfdXJsKV0KICAgICAgICBpZiBsZW4oYnVja2V0KSA+IDE6CiAgICAgICAgICAgICMg - cmVtb3ZlIGxhc3QgZG90CiAgICAgICAgICAgIGJ1Y2tldCA9IGJ1Y2tldFs6LTFdCgogICAgICAg - IGludGVyZXN0aW5nX2hlYWRlcnMgPSB7ImNvbnRlbnQtbWQ1IjogIiIsICJjb250ZW50LXR5cGUi - OiAiIiwgImRhdGUiOiAiIn0KICAgICAgICBmb3Iga2V5IGluIGhlYWRlcnM6CiAgICAgICAgICAg - IGxrID0ga2V5Lmxvd2VyKCkKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgbGsgPSBs - ay5kZWNvZGUoInV0Zi04IikKICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgcGFz - cwogICAgICAgICAgICBpZiBoZWFkZXJzW2tleV0gYW5kICgKICAgICAgICAgICAgICAgIGxrIGlu - IGludGVyZXN0aW5nX2hlYWRlcnMua2V5cygpIG9yIGxrLnN0YXJ0c3dpdGgoIngtYW16LSIpCiAg - ICAgICAgICAgICk6CiAgICAgICAgICAgICAgICBpbnRlcmVzdGluZ19oZWFkZXJzW2xrXSA9IGhl - YWRlcnNba2V5XS5zdHJpcCgpCgogICAgICAgICMgSWYgeC1hbXotZGF0ZSBpcyB1c2VkIGl0IHN1 - cGVyc2VkZXMgdGhlIGRhdGUgaGVhZGVyLgogICAgICAgIGlmICJ4LWFtei1kYXRlIiBpbiBpbnRl - cmVzdGluZ19oZWFkZXJzOgogICAgICAgICAgICBpbnRlcmVzdGluZ19oZWFkZXJzWyJkYXRlIl0g - PSAiIgoKICAgICAgICBidWYgPSBmInttZXRob2R9XG4iCiAgICAgICAgZm9yIGtleSBpbiBzb3J0 - ZWQoaW50ZXJlc3RpbmdfaGVhZGVycy5rZXlzKCkpOgogICAgICAgICAgICB2YWwgPSBpbnRlcmVz - dGluZ19oZWFkZXJzW2tleV0KICAgICAgICAgICAgaWYga2V5LnN0YXJ0c3dpdGgoIngtYW16LSIp - OgogICAgICAgICAgICAgICAgYnVmICs9IGYie2tleX06e3ZhbH1cbiIKICAgICAgICAgICAgZWxz - ZToKICAgICAgICAgICAgICAgIGJ1ZiArPSBmInt2YWx9XG4iCgogICAgICAgICMgYXBwZW5kIHRo - ZSBidWNrZXQgaWYgaXQgZXhpc3RzCiAgICAgICAgaWYgYnVja2V0ICE9ICIiOgogICAgICAgICAg - ICBidWYgKz0gZiIve2J1Y2tldH0iCgogICAgICAgICMgYWRkIHRoZSBvYmplY3RrZXkuIGV2ZW4g - aWYgaXQgZG9lc24ndCBleGlzdCwgYWRkIHRoZSBzbGFzaAogICAgICAgIGJ1ZiArPSBmIi97b2Jq - ZWN0a2V5fSIKCiAgICAgICAgcmV0dXJuIGJ1ZgoKCmNsYXNzIFJhZG9zSlNPTjoKICAgIEVYVEVS - TkFMX1VTRVJfTkFNRSA9ICJjbGllbnQuaGVhbHRoY2hlY2tlciIKICAgIEVYVEVSTkFMX1JHV19B - RE1JTl9PUFNfVVNFUl9OQU1FID0gInJndy1hZG1pbi1vcHMtdXNlciIKICAgIEVNUFRZX09VVFBV - VF9MSVNUID0gIkVtcHR5IG91dHB1dCBsaXN0IgogICAgREVGQVVMVF9SR1dfUE9PTF9QUkVGSVgg - PSAiZGVmYXVsdCIKICAgIERFRkFVTFRfTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUID0gIjkyODMi - CgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgZ2VuX2FyZ19wYXJzZXIoY2xzLCBhcmdzX3RvX3Bh - cnNlPU5vbmUpOgogICAgICAgIGFyZ1AgPSBhcmdwYXJzZS5Bcmd1bWVudFBhcnNlcigpCgogICAg - ICAgIGNvbW1vbl9ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJjb21tb24iKQogICAg - ICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoIi0tdmVyYm9zZSIsICItdiIsIGFjdGlvbj0i - c3RvcmVfdHJ1ZSIsIGRlZmF1bHQ9RmFsc2UpCiAgICAgICAgY29tbW9uX2dyb3VwLmFkZF9hcmd1 - bWVudCgKICAgICAgICAgICAgIi0tY2VwaC1jb25mIiwgIi1jIiwgaGVscD0iUHJvdmlkZSBhIGNl - cGggY29uZiBmaWxlLiIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiCiAgICAgICAgKQogICAgICAgIGNv - bW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWtleXJpbmciLCAiLWsiLCBo - ZWxwPSJQYXRoIHRvIGNlcGgga2V5cmluZyBmaWxlLiIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiCiAg - ICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICIt - LXJ1bi1hcy11c2VyIiwKICAgICAgICAgICAgIi11IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwK - ICAgICAgICAgICAgdHlwZT1zdHIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIGEgdXNlciBu - YW1lIHRvIGNoZWNrIHRoZSBjbHVzdGVyJ3MgaGVhbHRoIHN0YXR1cywgbXVzdCBiZSBwcmVmaXhl - ZCBieSAnY2xpZW50LiciLAogICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3Vt - ZW50KAogICAgICAgICAgICAiLS1jbHVzdGVyLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIi - LAogICAgICAgICAgICBoZWxwPSJLdWJlcm5ldGVzIGNsdXN0ZXIgbmFtZShsZWdhY3kgZmxhZyks - IE5vdGU6IEVpdGhlciB1c2UgdGhpcyBvciAtLWs4cy1jbHVzdGVyLW5hbWUiLAogICAgICAgICkK - ICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1rOHMtY2x1 - c3Rlci1uYW1lIiwgZGVmYXVsdD0iIiwgaGVscD0iS3ViZXJuZXRlcyBjbHVzdGVyIG5hbWUiCiAg - ICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICIt - LW5hbWVzcGFjZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9Ik5h - bWVzcGFjZSB3aGVyZSBDZXBoQ2x1c3RlciBpcyBydW5uaW5nIiwKICAgICAgICApCiAgICAgICAg - Y29tbW9uX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXBvb2wtcHJlZml4 - IiwgZGVmYXVsdD0iIiwgaGVscD0iUkdXIFBvb2wgcHJlZml4IgogICAgICAgICkKICAgICAgICBj - b21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yZXN0cmljdGVkLWF1dGgt - cGVybWlzc2lvbiIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9 - IlJlc3RyaWN0IGNlcGhDU0lLZXlyaW5ncyBhdXRoIHBlcm1pc3Npb25zIHRvIHNwZWNpZmljIHBv - b2xzLCBjbHVzdGVyLiIKICAgICAgICAgICAgKyAiTWFuZGF0b3J5IGZsYWdzIHRoYXQgbmVlZCB0 - byBiZSBzZXQgYXJlIC0tcmJkLWRhdGEtcG9vbC1uYW1lLCBhbmQgLS1rOHMtY2x1c3Rlci1uYW1l - LiIKICAgICAgICAgICAgKyAiLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIGZsYWcgY2FuIGFsc28g - YmUgcGFzc2VkIGluIGNhc2Ugb2YgY2VwaGZzIHVzZXIgcmVzdHJpY3Rpb24sIHNvIGl0IGNhbiBy - ZXN0cmljdCB1c2VyIHRvIHBhcnRpY3VsYXIgY2VwaGZzIGZpbGVzeXN0ZW0iCiAgICAgICAgICAg - ICsgInNhbXBsZSBydW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rl - ci1yZXNvdXJjZXMucHkgLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIG15ZnMgLS1yYmQtZGF0YS1w - b29sLW5hbWUgcmVwbGljYXBvb2wgLS1rOHMtY2x1c3Rlci1uYW1lIHJvb2tzdG9yYWdlIC0tcmVz - dHJpY3RlZC1hdXRoLXBlcm1pc3Npb24gdHJ1ZWAiCiAgICAgICAgICAgICsgIk5vdGU6IFJlc3Ry - aWN0aW5nIHRoZSBjc2ktdXNlcnMgcGVyIHBvb2wsIGFuZCBwZXIgY2x1c3RlciB3aWxsIHJlcXVp - cmUgY3JlYXRpbmcgbmV3IGNzaS11c2VycyBhbmQgbmV3IHNlY3JldHMgZm9yIHRoYXQgY3NpLXVz - ZXJzLiIKICAgICAgICAgICAgKyAiU28gYXBwbHkgdGhlc2Ugc2VjcmV0cyBvbmx5IHRvIG5ldyBg - Q29uc3VtZXIgY2x1c3RlcmAgZGVwbG95bWVudCB3aGlsZSB1c2luZyB0aGUgc2FtZSBgU291cmNl - IGNsdXN0ZXJgLiIsCiAgICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQo - CiAgICAgICAgICAgICItLXYyLXBvcnQtZW5hYmxlIiwKICAgICAgICAgICAgYWN0aW9uPSJzdG9y - ZV90cnVlIiwKICAgICAgICAgICAgZGVmYXVsdD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iRW5h - YmxlIHYyIG1vbiBwb3J0KDMzMDApIGZvciBtb25zIiwKICAgICAgICApCgogICAgICAgIG91dHB1 - dF9ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJvdXRwdXQiKQogICAgICAgIG91dHB1 - dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWZvcm1hdCIsCiAgICAgICAgICAg - ICItdCIsCiAgICAgICAgICAgIGNob2ljZXM9WyJqc29uIiwgImJhc2giXSwKICAgICAgICAgICAg - ZGVmYXVsdD0ianNvbiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBvdXRwdXQgZm9y - bWF0IChqc29uIHwgYmFzaCkiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy - Z3VtZW50KAogICAgICAgICAgICAiLS1vdXRwdXQiLAogICAgICAgICAgICAiLW8iLAogICAgICAg - ICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJPdXRwdXQgd2lsbCBiZSBzdG9yZWQg - aW50byB0aGUgcHJvdmlkZWQgZmlsZSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5h - ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNlcGhmcy1maWxlc3lzdGVtLW5hbWUiLAogICAg - ICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBv - ZiB0aGUgQ2VwaCBmaWxlc3lzdGVtIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFk - ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tY2VwaGZzLW1ldGFkYXRhLXBvb2wtbmFtZSIsCiAg - ICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBuYW1l - IG9mIHRoZSBjZXBoZnMgbWV0YWRhdGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9n - cm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNlcGhmcy1kYXRhLXBvb2wtbmFtZSIs - CiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBu - YW1lIG9mIHRoZSBjZXBoZnMgZGF0YSBwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dy - b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmJkLWRhdGEtcG9vbC1uYW1lIiwKICAg - ICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAg - ICAgIGhlbHA9IlByb3ZpZGVzIHRoZSBuYW1lIG9mIHRoZSBSQkQgZGF0YXBvb2wiLAogICAgICAg - ICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1hbGlh - cy1yYmQtZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAg - ICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iUHJvdmlkZXMgYW4gYWxpYXMgZm9y - IHRoZSAgUkJEIGRhdGEgcG9vbCBuYW1lLCBuZWNlc3NhcnkgaWYgYSBzcGVjaWFsIGNoYXJhY3Rl - ciBpcyBwcmVzZW50IGluIHRoZSBwb29sIG5hbWUgc3VjaCBhcyBhIHBlcmlvZCBvciB1bmRlcnNj - b3JlIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg - ICAgICAgIi0tcmd3LWVuZHBvaW50IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAg - ICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IlJBRE9TIEdhdGV3YXkgZW5kcG9p - bnQgKGluIGA8SVB2ND46PFBPUlQ+YCBvciBgPFtJUHY2XT46PFBPUlQ+YCBvciBgPEZRRE4+OjxQ - T1JUPmAgZm9ybWF0KSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1l - bnQoCiAgICAgICAgICAgICItLXJndy10bHMtY2VydC1wYXRoIiwKICAgICAgICAgICAgZGVmYXVs - dD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IlJBRE9T - IEdhdGV3YXkgZW5kcG9pbnQgVExTIGNlcnRpZmljYXRlIiwKICAgICAgICApCiAgICAgICAgb3V0 - cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXNraXAtdGxzIiwKICAg - ICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAg - ICAgICAgIGhlbHA9Iklnbm9yZSBUTFMgY2VydGlmaWNhdGlvbiB2YWxpZGF0aW9uIHdoZW4gYSBz - ZWxmLXNpZ25lZCBjZXJ0aWZpY2F0ZSBpcyBwcm92aWRlZCAoTk9UIFJFQ09NTUVOREVEIiwKICAg - ICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0t - bW9uaXRvcmluZy1lbmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAg - IHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJDZXBoIE1hbmFnZXIgcHJvbWV0aGV1 - cyBleHBvcnRlciBlbmRwb2ludHMgKGNvbW1hIHNlcGFyYXRlZCBsaXN0IG9mIChmb3JtYXQgYDxJ - UHY0PmAgb3IgYDxbSVB2Nl0+YCBvciBgPEZRRE4+YCkgZW50cmllcyBvZiBhY3RpdmUgYW5kIHN0 - YW5kYnkgbWdycykiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50 - KAogICAgICAgICAgICAiLS1tb25pdG9yaW5nLWVuZHBvaW50LXBvcnQiLAogICAgICAgICAgICBk - ZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0i - Q2VwaCBNYW5hZ2VyIHByb21ldGhldXMgZXhwb3J0ZXIgcG9ydCIsCiAgICAgICAgKQogICAgICAg - IG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXNraXAtbW9uaXRvcmlu - Zy1lbmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGFjdGlv - bj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGhlbHA9IkRvIG5vdCBjaGVjayBmb3IgYSBtb25p - dG9yaW5nIGVuZHBvaW50IGZvciB0aGUgQ2VwaCBjbHVzdGVyIiwKICAgICAgICApCiAgICAgICAg - b3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmJkLW1ldGFkYXRhLWVj - LXBvb2wtbmFtZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVk - PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiBlcmFzdXJlIGNv - ZGVkIFJCRCBtZXRhZGF0YSBwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFk - ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tZHJ5LXJ1biIsCiAgICAgICAgICAgIGRlZmF1bHQ9 - RmFsc2UsCiAgICAgICAgICAgIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGhlbHA9 - IkRyeSBydW4gcHJpbnRzIHRoZSBleGVjdXRlZCBjb21tYW5kcyB3aXRob3V0IHJ1bm5pbmcgdGhl - bSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAg - ICAgICItLXJhZG9zLW5hbWVzcGFjZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAg - ICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJEaXZpZGVzIGEgcG9vbCBpbnRv - IHNlcGFyYXRlIGxvZ2ljYWwgbmFtZXNwYWNlcywgdXNlZCBmb3IgY3JlYXRpbmcgUkJEIFBWQyBp - biBhIENlcGhCbG9ja1Bvb2xSYWRvc05hbWVzcGFjZSAoc2hvdWxkIGJlIGxvd2VyIGNhc2UpIiwK + aW5kZXgiLCAibWRzIiwgImFsbG93ICoiXSwgImVudGl0eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tl + ciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBjYXBzIn0iIiIKICAgICAgICBd + ID0gIiIiW3siZW50aXR5IjoiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCJrZXkiOiJBUURGa2JOZWZ0 + NWJGUkFBVG5kTE5VU1JLcnVvenhpWmkzbHJkQT09IiwiY2FwcyI6eyJtb24iOiAiYWxsb3cgciwg + YWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLCAibWdy + IjogImFsbG93IGNvbW1hbmQgY29uZmlnIiwgIm9zZCI6ICJwcm9maWxlIHJiZC1yZWFkLW9ubHks + IGFsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3Qs + IGFsbG93IHJ3IHBvb2w9ZGVmYXVsdC5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD1kZWZhdWx0 + LnJndy5sb2csIGFsbG93IHggcG9vbD1kZWZhdWx0LnJndy5idWNrZXRzLmluZGV4IiwibWRzIjoi + YWxsb3cgKiJ9fV0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWyIiInsiZm9ybWF0Ijog + Impzb24iLCAicHJlZml4IjogIm1nciBzZXJ2aWNlcyJ9IiIiXSA9ICgKICAgICAgICAgICAgIiIi + eyJkYXNoYm9hcmQiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0am5sOjcw + MDAvIiwgInByb21ldGhldXMiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0 + am5sOjkyODMvIn0iIiIKICAgICAgICApCiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAg + ICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiLCAiZm9ybWF0Ijog + Impzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBdID0gIiIieyJkYXNoYm9h + cmQiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0am5sOjcwMDAvIiwgInBy + b21ldGhldXMiOiAiaHR0cDovL3Jvb2stY2VwaC1tZ3ItYS01N2NmOWY4NGJjLWY0am5sOjkyODMv + In0iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7ImVudGl0 + eSI6ICJjbGllbnQuaGVhbHRoY2hlY2tlciIsICJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgiOiAi + YXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbeyJlbnRpdHkiOiJjbGllbnQuaGVhbHRoY2hl + Y2tlciIsImtleSI6IkFRREZrYk5lZnQ1YkZSQUFUbmRMTlVTRUtydW96eGlaaTNscmRBPT0iLCJj + YXBzIjp7Im1vbiI6ICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1b3J1bV9zdGF0dXMsIGFsbG93 + IGNvbW1hbmQgdmVyc2lvbiIsICJtZ3IiOiAiYWxsb3cgY29tbWFuZCBjb25maWciLCAib3NkIjog + InByb2ZpbGUgcmJkLXJlYWQtb25seSwgYWxsb3cgcnd4IHBvb2w9ZGVmYXVsdC5yZ3cubWV0YSwg + YWxsb3cgciBwb29sPS5yZ3cucm9vdCwgYWxsb3cgcncgcG9vbD1kZWZhdWx0LnJndy5jb250cm9s + LCBhbGxvdyByeCBwb29sPWRlZmF1bHQucmd3LmxvZywgYWxsb3cgeCBwb29sPWRlZmF1bHQucmd3 + LmJ1Y2tldHMuaW5kZXgiLCJtZHMiOiJhbGxvdyAqIn19XSIiIgogICAgICAgIHNlbGYuY21kX291 + dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNsaWVudC5jc2ktY2VwaGZzLW5v + ZGUiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAgICAgICBd + ID0gIiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAgICAiIiJ7 + ImVudGl0eSI6ICJjbGllbnQuY3NpLXJiZC1ub2RlIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZp + eCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAgICAgICAgc2VsZi5jbWRf + b3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xpZW50LmNzaS1yYmQtcHJv + dmlzaW9uZXIiLCAiZm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggZ2V0In0iIiIKICAg + ICAgICBdID0gIiIiW10iIiIKICAgICAgICBzZWxmLmNtZF9vdXRwdXRfbWFwWwogICAgICAgICAg + ICAiIiJ7ImVudGl0eSI6ICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsICJmb3JtYXQi + OiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIiIgog + ICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5IjogImNs + aWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlIiwgImZvcm1hdCI6 + ICJqc29uIiwgInByZWZpeCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIltdIiIiCiAg + ICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsKICAgICAgICAgICAgIiIieyJlbnRpdHkiOiAiY2xp + ZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXItb3BlbnNoaWZ0LXN0b3JhZ2UtbXlmcyIsICJmb3Jt + YXQiOiAianNvbiIsICJwcmVmaXgiOiAiYXV0aCBnZXQifSIiIgogICAgICAgIF0gPSAiIiJbXSIi + IgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiZW50aXR5Ijog + ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwgImZvcm1hdCI6ICJqc29uIiwgInByZWZp + eCI6ICJhdXRoIGdldCJ9IiIiCiAgICAgICAgXSA9ICIiIlt7ImVudGl0eSI6ImNsaWVudC5jc2kt + Y2VwaGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmtiTmVmdDViRlJBQVRuZExOVVNFS3J1b3p4 + aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cgciIsICJtZ3IiOiJhbGxvdyBydyIsICJv + c2QiOiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFkYXRhPSoiLCJtZHMiOiJhbGxvdyAqIn19XSIi + IgogICAgICAgIHNlbGYuY21kX291dHB1dF9tYXBbCiAgICAgICAgICAgICIiInsiY2FwcyI6IFsi + bW9uIiwgImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciIsICJh + bGxvdyBydyIsICJvc2QiLCAiYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0qIiwgIm1kcyIs + ICJhbGxvdyAqIl0sICJlbnRpdHkiOiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIiLCAi + Zm9ybWF0IjogImpzb24iLCAicHJlZml4IjogImF1dGggY2FwcyJ9IiIiCiAgICAgICAgXSA9ICIi + Ilt7ImVudGl0eSI6ImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIiwia2V5IjoiQVFERmti + TmVmdDViRlJBQVRuZExOVVNFS3J1b3p4aVppM2xyZEE9PSIsImNhcHMiOnsibW9uIjoiYWxsb3cg + ciwgIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwgIm1nciI6ImFsbG93IHJ3IiwgIm9z + ZCI6ImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9KiIsIm1kcyI6ImFsbG93ICoifX1dIiIi + CiAgICAgICAgc2VsZi5jbWRfb3V0cHV0X21hcFsneyJmb3JtYXQiOiAianNvbiIsICJwcmVmaXgi + OiAic3RhdHVzIn0nXSA9IGNlcGhfc3RhdHVzX3N0cgoKICAgIGRlZiBzaHV0ZG93bihzZWxmKToK + ICAgICAgICBwYXNzCgogICAgZGVmIGdldF9mc2lkKHNlbGYpOgogICAgICAgIHJldHVybiAiYWY0 + ZTE2NzMtMGI3Mi00MDJkLTk5MGEtMjJkMjkxOWQwZjFjIgoKICAgIGRlZiBjb25mX3JlYWRfZmls + ZShzZWxmKToKICAgICAgICBwYXNzCgogICAgZGVmIGNvbm5lY3Qoc2VsZik6CiAgICAgICAgcGFz + cwoKICAgIGRlZiBwb29sX2V4aXN0cyhzZWxmLCBwb29sX25hbWUpOgogICAgICAgIHJldHVybiBU + cnVlCgogICAgZGVmIG1vbl9jb21tYW5kKHNlbGYsIGNtZCwgb3V0KToKICAgICAgICBqc29uX2Nt + ZCA9IGpzb24ubG9hZHMoY21kKQogICAgICAgIGpzb25fY21kX3N0ciA9IGpzb24uZHVtcHMoanNv + bl9jbWQsIHNvcnRfa2V5cz1UcnVlKQogICAgICAgIGNtZF9vdXRwdXQgPSBzZWxmLmNtZF9vdXRw + dXRfbWFwW2pzb25fY21kX3N0cl0KICAgICAgICByZXR1cm4gc2VsZi5yZXR1cm5fdmFsLCBjbWRf + b3V0cHV0LCBzdHIoc2VsZi5lcnJfbWVzc2FnZS5lbmNvZGUoInV0Zi04IikpCgogICAgZGVmIF9j + b252ZXJ0X2hvc3RuYW1lX3RvX2lwKHNlbGYsIGhvc3RfbmFtZSk6CiAgICAgICAgaXBfcmVnX3gg + PSByZS5jb21waWxlKHIiXGR7MSwzfS5cZHsxLDN9LlxkezEsM30uXGR7MSwzfSIpCiAgICAgICAg + IyBpZiBwcm92aWRlZCBob3N0IGlzIGRpcmVjdGx5IGFuIElQIGFkZHJlc3MsIHJldHVybiB0aGUg + c2FtZQogICAgICAgIGlmIGlwX3JlZ194Lm1hdGNoKGhvc3RfbmFtZSk6CiAgICAgICAgICAgIHJl + dHVybiBob3N0X25hbWUKICAgICAgICBpbXBvcnQgcmFuZG9tCgogICAgICAgIGhvc3RfaXAgPSBz + ZWxmLmR1bW15X2hvc3RfaXBfbWFwLmdldChob3N0X25hbWUsICIiKQogICAgICAgIGlmIG5vdCBo + b3N0X2lwOgogICAgICAgICAgICBob3N0X2lwID0gZiIxNzIuOS57cmFuZG9tLnJhbmRpbnQoMCwg + MjU0KX0ue3JhbmRvbS5yYW5kaW50KDAsIDI1NCl9IgogICAgICAgICAgICBzZWxmLmR1bW15X2hv + c3RfaXBfbWFwW2hvc3RfbmFtZV0gPSBob3N0X2lwCiAgICAgICAgZGVsIHJhbmRvbQogICAgICAg + IHJldHVybiBob3N0X2lwCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgUmFkb3MoY29uZmZpbGU9 + Tm9uZSk6CiAgICAgICAgcmV0dXJuIER1bW15UmFkb3MoKQoKCmNsYXNzIFMzQXV0aChBdXRoQmFz + ZSk6CiAgICAiIiJBdHRhY2hlcyBBV1MgQXV0aGVudGljYXRpb24gdG8gdGhlIGdpdmVuIFJlcXVl + c3Qgb2JqZWN0LiIiIgoKICAgIHNlcnZpY2VfYmFzZV91cmwgPSAiczMuYW1hem9uYXdzLmNvbSIK + CiAgICBkZWYgX19pbml0X18oc2VsZiwgYWNjZXNzX2tleSwgc2VjcmV0X2tleSwgc2VydmljZV91 + cmw9Tm9uZSk6CiAgICAgICAgaWYgc2VydmljZV91cmw6CiAgICAgICAgICAgIHNlbGYuc2Vydmlj + ZV9iYXNlX3VybCA9IHNlcnZpY2VfdXJsCiAgICAgICAgc2VsZi5hY2Nlc3Nfa2V5ID0gc3RyKGFj + Y2Vzc19rZXkpCiAgICAgICAgc2VsZi5zZWNyZXRfa2V5ID0gc3RyKHNlY3JldF9rZXkpCgogICAg + ZGVmIF9fY2FsbF9fKHNlbGYsIHIpOgogICAgICAgICMgQ3JlYXRlIGRhdGUgaGVhZGVyIGlmIGl0 + IGlzIG5vdCBjcmVhdGVkIHlldC4KICAgICAgICBpZiAiZGF0ZSIgbm90IGluIHIuaGVhZGVycyBh + bmQgIngtYW16LWRhdGUiIG5vdCBpbiByLmhlYWRlcnM6CiAgICAgICAgICAgIHIuaGVhZGVyc1si + ZGF0ZSJdID0gZm9ybWF0ZGF0ZSh0aW1ldmFsPU5vbmUsIGxvY2FsdGltZT1GYWxzZSwgdXNlZ210 + PVRydWUpCiAgICAgICAgc2lnbmF0dXJlID0gc2VsZi5nZXRfc2lnbmF0dXJlKHIpCiAgICAgICAg + c2lnbmF0dXJlID0gc2lnbmF0dXJlLmRlY29kZSgidXRmLTgiKQogICAgICAgIHIuaGVhZGVyc1si + QXV0aG9yaXphdGlvbiJdID0gZiJBV1Mge3NlbGYuYWNjZXNzX2tleX06e3NpZ25hdHVyZX0iCiAg + ICAgICAgcmV0dXJuIHIKCiAgICBkZWYgZ2V0X3NpZ25hdHVyZShzZWxmLCByKToKICAgICAgICBj + YW5vbmljYWxfc3RyaW5nID0gc2VsZi5nZXRfY2Fub25pY2FsX3N0cmluZyhyLnVybCwgci5oZWFk + ZXJzLCByLm1ldGhvZCkKICAgICAgICBrZXkgPSBzZWxmLnNlY3JldF9rZXkuZW5jb2RlKCJ1dGYt + OCIpCiAgICAgICAgbXNnID0gY2Fub25pY2FsX3N0cmluZy5lbmNvZGUoInV0Zi04IikKICAgICAg + ICBoID0gaG1hYy5uZXcoa2V5LCBtc2csIGRpZ2VzdG1vZD1zaGEpCiAgICAgICAgcmV0dXJuIGVu + Y29kZXN0cmluZyhoLmRpZ2VzdCgpKS5zdHJpcCgpCgogICAgZGVmIGdldF9jYW5vbmljYWxfc3Ry + aW5nKHNlbGYsIHVybCwgaGVhZGVycywgbWV0aG9kKToKICAgICAgICBwYXJzZWR1cmwgPSB1cmxw + YXJzZSh1cmwpCiAgICAgICAgb2JqZWN0a2V5ID0gcGFyc2VkdXJsLnBhdGhbMTpdCgogICAgICAg + IGJ1Y2tldCA9IHBhcnNlZHVybC5uZXRsb2NbOiAtbGVuKHNlbGYuc2VydmljZV9iYXNlX3VybCld + CiAgICAgICAgaWYgbGVuKGJ1Y2tldCkgPiAxOgogICAgICAgICAgICAjIHJlbW92ZSBsYXN0IGRv + dAogICAgICAgICAgICBidWNrZXQgPSBidWNrZXRbOi0xXQoKICAgICAgICBpbnRlcmVzdGluZ19o + ZWFkZXJzID0geyJjb250ZW50LW1kNSI6ICIiLCAiY29udGVudC10eXBlIjogIiIsICJkYXRlIjog + IiJ9CiAgICAgICAgZm9yIGtleSBpbiBoZWFkZXJzOgogICAgICAgICAgICBsayA9IGtleS5sb3dl + cigpCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGxrID0gbGsuZGVjb2RlKCJ1dGYt + OCIpCiAgICAgICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgICAgIHBhc3MKICAgICAgICAgICAg + aWYgaGVhZGVyc1trZXldIGFuZCAoCiAgICAgICAgICAgICAgICBsayBpbiBpbnRlcmVzdGluZ19o + ZWFkZXJzLmtleXMoKSBvciBsay5zdGFydHN3aXRoKCJ4LWFtei0iKQogICAgICAgICAgICApOgog + ICAgICAgICAgICAgICAgaW50ZXJlc3RpbmdfaGVhZGVyc1tsa10gPSBoZWFkZXJzW2tleV0uc3Ry + aXAoKQoKICAgICAgICAjIElmIHgtYW16LWRhdGUgaXMgdXNlZCBpdCBzdXBlcnNlZGVzIHRoZSBk + YXRlIGhlYWRlci4KICAgICAgICBpZiAieC1hbXotZGF0ZSIgaW4gaW50ZXJlc3RpbmdfaGVhZGVy + czoKICAgICAgICAgICAgaW50ZXJlc3RpbmdfaGVhZGVyc1siZGF0ZSJdID0gIiIKCiAgICAgICAg + YnVmID0gZiJ7bWV0aG9kfVxuIgogICAgICAgIGZvciBrZXkgaW4gc29ydGVkKGludGVyZXN0aW5n + X2hlYWRlcnMua2V5cygpKToKICAgICAgICAgICAgdmFsID0gaW50ZXJlc3RpbmdfaGVhZGVyc1tr + ZXldCiAgICAgICAgICAgIGlmIGtleS5zdGFydHN3aXRoKCJ4LWFtei0iKToKICAgICAgICAgICAg + ICAgIGJ1ZiArPSBmIntrZXl9Ont2YWx9XG4iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg + ICAgICBidWYgKz0gZiJ7dmFsfVxuIgoKICAgICAgICAjIGFwcGVuZCB0aGUgYnVja2V0IGlmIGl0 + IGV4aXN0cwogICAgICAgIGlmIGJ1Y2tldCAhPSAiIjoKICAgICAgICAgICAgYnVmICs9IGYiL3ti + dWNrZXR9IgoKICAgICAgICAjIGFkZCB0aGUgb2JqZWN0a2V5LiBldmVuIGlmIGl0IGRvZXNuJ3Qg + ZXhpc3QsIGFkZCB0aGUgc2xhc2gKICAgICAgICBidWYgKz0gZiIve29iamVjdGtleX0iCgogICAg + ICAgIHJldHVybiBidWYKCgpjbGFzcyBSYWRvc0pTT046CiAgICBFWFRFUk5BTF9VU0VSX05BTUUg + PSAiY2xpZW50LmhlYWx0aGNoZWNrZXIiCiAgICBFWFRFUk5BTF9SR1dfQURNSU5fT1BTX1VTRVJf + TkFNRSA9ICJyZ3ctYWRtaW4tb3BzLXVzZXIiCiAgICBFTVBUWV9PVVRQVVRfTElTVCA9ICJFbXB0 + eSBvdXRwdXQgbGlzdCIKICAgIERFRkFVTFRfUkdXX1BPT0xfUFJFRklYID0gImRlZmF1bHQiCiAg + ICBERUZBVUxUX01PTklUT1JJTkdfRU5EUE9JTlRfUE9SVCA9ICI5MjgzIgoKICAgIEBjbGFzc21l + dGhvZAogICAgZGVmIGdlbl9hcmdfcGFyc2VyKGNscywgYXJnc190b19wYXJzZT1Ob25lKToKICAg + ICAgICBhcmdQID0gYXJncGFyc2UuQXJndW1lbnRQYXJzZXIoKQoKICAgICAgICBjb21tb25fZ3Jv + dXAgPSBhcmdQLmFkZF9hcmd1bWVudF9ncm91cCgiY29tbW9uIikKICAgICAgICBjb21tb25fZ3Jv + dXAuYWRkX2FyZ3VtZW50KCItLXZlcmJvc2UiLCAiLXYiLCBhY3Rpb249InN0b3JlX3RydWUiLCBk + ZWZhdWx0PUZhbHNlKQogICAgICAgIGNvbW1vbl9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAg + ICAgICItLWNlcGgtY29uZiIsICItYyIsIGhlbHA9IlByb3ZpZGUgYSBjZXBoIGNvbmYgZmlsZS4i + LCB0eXBlPXN0ciwgZGVmYXVsdD0iIgogICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRk + X2FyZ3VtZW50KAogICAgICAgICAgICAiLS1rZXlyaW5nIiwgIi1rIiwgaGVscD0iUGF0aCB0byBj + ZXBoIGtleXJpbmcgZmlsZS4iLCB0eXBlPXN0ciwgZGVmYXVsdD0iIgogICAgICAgICkKICAgICAg + ICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1ydW4tYXMtdXNlciIs + CiAgICAgICAgICAgICItdSIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHR5 + cGU9c3RyLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyBhIHVzZXIgbmFtZSB0byBjaGVjayB0 + aGUgY2x1c3RlcidzIGhlYWx0aCBzdGF0dXMsIG11c3QgYmUgcHJlZml4ZWQgYnkgJ2NsaWVudC4n + IiwKICAgICAgICApCiAgICAgICAgY29tbW9uX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAg + ICAgIi0tY2x1c3Rlci1uYW1lIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAg + aGVscD0iS3ViZXJuZXRlcyBjbHVzdGVyIG5hbWUobGVnYWN5IGZsYWcpLCBOb3RlOiBFaXRoZXIg + dXNlIHRoaXMgb3IgLS1rOHMtY2x1c3Rlci1uYW1lIiwKICAgICAgICApCiAgICAgICAgY29tbW9u + X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tazhzLWNsdXN0ZXItbmFtZSIsIGRl + ZmF1bHQ9IiIsIGhlbHA9Ikt1YmVybmV0ZXMgY2x1c3RlciBuYW1lIgogICAgICAgICkKICAgICAg + ICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1uYW1lc3BhY2UiLAog + ICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJOYW1lc3BhY2Ugd2hlcmUg + Q2VwaENsdXN0ZXIgaXMgcnVubmluZyIsCiAgICAgICAgKQogICAgICAgIGNvbW1vbl9ncm91cC5h + ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXJndy1wb29sLXByZWZpeCIsIGRlZmF1bHQ9IiIs + IGhlbHA9IlJHVyBQb29sIHByZWZpeCIKICAgICAgICApCiAgICAgICAgY29tbW9uX2dyb3VwLmFk + ZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmVzdHJpY3RlZC1hdXRoLXBlcm1pc3Npb24iLAog + ICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJSZXN0cmljdCBjZXBo + Q1NJS2V5cmluZ3MgYXV0aCBwZXJtaXNzaW9ucyB0byBzcGVjaWZpYyBwb29scywgY2x1c3Rlci4i + CiAgICAgICAgICAgICsgIk1hbmRhdG9yeSBmbGFncyB0aGF0IG5lZWQgdG8gYmUgc2V0IGFyZSAt + LXJiZC1kYXRhLXBvb2wtbmFtZSwgYW5kIC0tazhzLWNsdXN0ZXItbmFtZS4iCiAgICAgICAgICAg + ICsgIi0tY2VwaGZzLWZpbGVzeXN0ZW0tbmFtZSBmbGFnIGNhbiBhbHNvIGJlIHBhc3NlZCBpbiBj + YXNlIG9mIGNlcGhmcyB1c2VyIHJlc3RyaWN0aW9uLCBzbyBpdCBjYW4gcmVzdHJpY3QgdXNlciB0 + byBwYXJ0aWN1bGFyIGNlcGhmcyBmaWxlc3lzdGVtIgogICAgICAgICAgICArICJzYW1wbGUgcnVu + OiBgcHl0aG9uMyAvZXRjL2NlcGgvY3JlYXRlLWV4dGVybmFsLWNsdXN0ZXItcmVzb3VyY2VzLnB5 + IC0tY2VwaGZzLWZpbGVzeXN0ZW0tbmFtZSBteWZzIC0tcmJkLWRhdGEtcG9vbC1uYW1lIHJlcGxp + Y2Fwb29sIC0tazhzLWNsdXN0ZXItbmFtZSByb29rc3RvcmFnZSAtLXJlc3RyaWN0ZWQtYXV0aC1w + ZXJtaXNzaW9uIHRydWVgIgogICAgICAgICAgICArICJOb3RlOiBSZXN0cmljdGluZyB0aGUgY3Np + LXVzZXJzIHBlciBwb29sLCBhbmQgcGVyIGNsdXN0ZXIgd2lsbCByZXF1aXJlIGNyZWF0aW5nIG5l + dyBjc2ktdXNlcnMgYW5kIG5ldyBzZWNyZXRzIGZvciB0aGF0IGNzaS11c2Vycy4iCiAgICAgICAg + ICAgICsgIlNvIGFwcGx5IHRoZXNlIHNlY3JldHMgb25seSB0byBuZXcgYENvbnN1bWVyIGNsdXN0 + ZXJgIGRlcGxveW1lbnQgd2hpbGUgdXNpbmcgdGhlIHNhbWUgYFNvdXJjZSBjbHVzdGVyYC4iLAog + ICAgICAgICkKICAgICAgICBjb21tb25fZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAi + LS12Mi1wb3J0LWVuYWJsZSIsCiAgICAgICAgICAgIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAg + ICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IkVuYWJsZSB2MiBtb24gcG9y + dCgzMzAwKSBmb3IgbW9ucyIsCiAgICAgICAgKQoKICAgICAgICBvdXRwdXRfZ3JvdXAgPSBhcmdQ + LmFkZF9hcmd1bWVudF9ncm91cCgib3V0cHV0IikKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy + Z3VtZW50KAogICAgICAgICAgICAiLS1mb3JtYXQiLAogICAgICAgICAgICAiLXQiLAogICAgICAg + ICAgICBjaG9pY2VzPVsianNvbiIsICJiYXNoIl0sCiAgICAgICAgICAgIGRlZmF1bHQ9Impzb24i + LAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgb3V0cHV0IGZvcm1hdCAoanNvbiB8IGJh + c2gpIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg + ICAgICAgIi0tb3V0cHV0IiwKICAgICAgICAgICAgIi1vIiwKICAgICAgICAgICAgZGVmYXVsdD0i + IiwKICAgICAgICAgICAgaGVscD0iT3V0cHV0IHdpbGwgYmUgc3RvcmVkIGludG8gdGhlIHByb3Zp + ZGVkIGZpbGUiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAog + ICAgICAgICAgICAiLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lIiwKICAgICAgICAgICAgZGVmYXVs + dD0iIiwKICAgICAgICAgICAgaGVscD0iUHJvdmlkZXMgdGhlIG5hbWUgb2YgdGhlIENlcGggZmls + ZXN5c3RlbSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAg + ICAgICAgICAgICItLWNlcGhmcy1tZXRhZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBkZWZh + dWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgY2VwaGZz + IG1ldGFkYXRhIHBvb2wiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3Vt + ZW50KAogICAgICAgICAgICAiLS1jZXBoZnMtZGF0YS1wb29sLW5hbWUiLAogICAgICAgICAgICBk + ZWZhdWx0PSIiLAogICAgICAgICAgICBoZWxwPSJQcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgY2Vw + aGZzIGRhdGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1l + bnQoCiAgICAgICAgICAgICItLXJiZC1kYXRhLXBvb2wtbmFtZSIsCiAgICAgICAgICAgIGRlZmF1 + bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJQcm92 + aWRlcyB0aGUgbmFtZSBvZiB0aGUgUkJEIGRhdGFwb29sIiwKICAgICAgICApCiAgICAgICAgb3V0 + cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tYWxpYXMtcmJkLWRhdGEtcG9v + bC1uYW1lIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFs + c2UsCiAgICAgICAgICAgIGhlbHA9IlByb3ZpZGVzIGFuIGFsaWFzIGZvciB0aGUgIFJCRCBkYXRh + IHBvb2wgbmFtZSwgbmVjZXNzYXJ5IGlmIGEgc3BlY2lhbCBjaGFyYWN0ZXIgaXMgcHJlc2VudCBp + biB0aGUgcG9vbCBuYW1lIHN1Y2ggYXMgYSBwZXJpb2Qgb3IgdW5kZXJzY29yZSIsCiAgICAgICAg + KQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXJndy1l + bmRwb2ludCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZh + bHNlLAogICAgICAgICAgICBoZWxwPSJSQURPUyBHYXRld2F5IGVuZHBvaW50IChpbiBgPElQdjQ+ + OjxQT1JUPmAgb3IgYDxbSVB2Nl0+OjxQT1JUPmAgb3IgYDxGUUROPjo8UE9SVD5gIGZvcm1hdCki + LAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAg + ICAiLS1yZ3ctdGxzLWNlcnQtcGF0aCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAg + ICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJSQURPUyBHYXRld2F5IGVuZHBv + aW50IFRMUyBjZXJ0aWZpY2F0ZSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRf + YXJndW1lbnQoCiAgICAgICAgICAgICItLXJndy1za2lwLXRscyIsCiAgICAgICAgICAgIHJlcXVp + cmVkPUZhbHNlLAogICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJJ + Z25vcmUgVExTIGNlcnRpZmljYXRpb24gdmFsaWRhdGlvbiB3aGVuIGEgc2VsZi1zaWduZWQgY2Vy + dGlmaWNhdGUgaXMgcHJvdmlkZWQgKE5PVCBSRUNPTU1FTkRFRCIsCiAgICAgICAgKQogICAgICAg + IG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLW1vbml0b3JpbmctZW5k + cG9pbnQiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxz + ZSwKICAgICAgICAgICAgaGVscD0iQ2VwaCBNYW5hZ2VyIHByb21ldGhldXMgZXhwb3J0ZXIgZW5k + cG9pbnRzIChjb21tYSBzZXBhcmF0ZWQgbGlzdCBvZiAoZm9ybWF0IGA8SVB2ND5gIG9yIGA8W0lQ + djZdPmAgb3IgYDxGUUROPmApIGVudHJpZXMgb2YgYWN0aXZlIGFuZCBzdGFuZGJ5IG1ncnMpIiwK ICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAg - Ii0tc3Vidm9sdW1lLWdyb3VwIiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAg - cmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9InByb3ZpZGVzIHRoZSBuYW1lIG9mIHRo - ZSBzdWJ2b2x1bWUgZ3JvdXAiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy - Z3VtZW50KAogICAgICAgICAgICAiLS1yZ3ctcmVhbG0tbmFtZSIsCiAgICAgICAgICAgIGRlZmF1 - bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJwcm92 - aWRlcyB0aGUgbmFtZSBvZiB0aGUgcmd3LXJlYWxtIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0 - X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXpvbmUtbmFtZSIsCiAgICAg - ICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAg - ICBoZWxwPSJwcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgcmd3LXpvbmUiLAogICAgICAgICkKICAg - ICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yZ3ctem9uZWdy - b3VwLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1G - YWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlkZXMgdGhlIG5hbWUgb2YgdGhlIHJndy16b25l - Z3JvdXAiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAg - ICAgICAgICAiLS10b3BvbG9neS1wb29scyIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAg - ICAgICAgIHJlcXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJjb21tYS1zZXBhcmF0ZWQg - bGlzdCBvZiB0b3BvbG9neS1jb25zdHJhaW5lZCByYmQgcG9vbHMiLAogICAgICAgICkKICAgICAg - ICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS10b3BvbG9neS1mYWls - dXJlLWRvbWFpbi1sYWJlbCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJl - cXVpcmVkPUZhbHNlLAogICAgICAgICAgICBoZWxwPSJrOHMgY2x1c3RlciBmYWlsdXJlIGRvbWFp - biBsYWJlbCAoZXhhbXBsZTogem9uZSwgcmFjaywgb3IgaG9zdCkgZm9yIHRoZSB0b3BvbG9neS1w - b29scyB0aGF0IG1hdGNoIHRoZSBjZXBoIGRvbWFpbiIsCiAgICAgICAgKQogICAgICAgIG91dHB1 - dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXRvcG9sb2d5LWZhaWx1cmUtZG9t - YWluLXZhbHVlcyIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVk - PUZhbHNlLAogICAgICAgICAgICBoZWxwPSJjb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiB0aGUgazhz - IGNsdXN0ZXIgZmFpbHVyZSBkb21haW4gdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gZWFjaCBvZiB0 - aGUgcG9vbHMgaW4gdGhlIGB0b3BvbG9neS1wb29sc2AgbGlzdCIsCiAgICAgICAgKQoKICAgICAg - ICB1cGdyYWRlX2dyb3VwID0gYXJnUC5hZGRfYXJndW1lbnRfZ3JvdXAoInVwZ3JhZGUiKQogICAg - ICAgIHVwZ3JhZGVfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS11cGdyYWRlIiwK - ICAgICAgICAgICAgYWN0aW9uPSJzdG9yZV90cnVlIiwKICAgICAgICAgICAgZGVmYXVsdD1GYWxz - ZSwKICAgICAgICAgICAgaGVscD0iVXBncmFkZXMgdGhlIGNlcGhDU0lLZXlyaW5ncyhGb3IgZXhh - bXBsZTogY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIpIGFuZCBjbGllbnQuaGVhbHRoY2hl - Y2tlciBjZXBoIHVzZXJzIHdpdGggbmV3IHBlcm1pc3Npb25zIG5lZWRlZCBmb3IgdGhlIG5ldyBj - bHVzdGVyIHZlcnNpb24gYW5kIG9sZGVyIHBlcm1pc3Npb24gd2lsbCBzdGlsbCBiZSBhcHBsaWVk - LiIKICAgICAgICAgICAgKyAiU2FtcGxlIHJ1bjogYHB5dGhvbjMgL2V0Yy9jZXBoL2NyZWF0ZS1l - eHRlcm5hbC1jbHVzdGVyLXJlc291cmNlcy5weSAtLXVwZ3JhZGVgLCB0aGlzIHdpbGwgdXBncmFk - ZSBhbGwgdGhlIGRlZmF1bHQgY3NpIHVzZXJzKG5vbi1yZXN0cmljdGVkKSIKICAgICAgICAgICAg - KyAiRm9yIHJlc3RyaWN0ZWQgdXNlcnMoRm9yIGV4YW1wbGU6IGNsaWVudC5jc2ktY2VwaGZzLXBy - b3Zpc2lvbmVyLW9wZW5zaGlmdC1zdG9yYWdlLW15ZnMpLCB1c2VycyBjcmVhdGVkIHVzaW5nIC0t - cmVzdHJpY3RlZC1hdXRoLXBlcm1pc3Npb24gZmxhZyBuZWVkIHRvIHBhc3MgbWFuZGF0b3J5IGZs - YWdzIgogICAgICAgICAgICArICJtYW5kYXRvcnkgZmxhZ3M6ICctLXJiZC1kYXRhLXBvb2wtbmFt - ZSwgLS1rOHMtY2x1c3Rlci1uYW1lIGFuZCAtLXJ1bi1hcy11c2VyJyBmbGFncyB3aGlsZSB1cGdy - YWRpbmciCiAgICAgICAgICAgICsgImluIGNhc2Ugb2YgY2VwaGZzIHVzZXJzIGlmIHlvdSBoYXZl - IHBhc3NlZCAtLWNlcGhmcy1maWxlc3lzdGVtLW5hbWUgZmxhZyB3aGlsZSBjcmVhdGluZyB1c2Vy - IHRoZW4gd2hpbGUgdXBncmFkaW5nIGl0IHdpbGwgYmUgbWFuZGF0b3J5IHRvbyIKICAgICAgICAg - ICAgKyAiU2FtcGxlIHJ1bjogYHB5dGhvbjMgL2V0Yy9jZXBoL2NyZWF0ZS1leHRlcm5hbC1jbHVz - dGVyLXJlc291cmNlcy5weSAtLXVwZ3JhZGUgLS1yYmQtZGF0YS1wb29sLW5hbWUgcmVwbGljYXBv - b2wgLS1rOHMtY2x1c3Rlci1uYW1lIHJvb2tzdG9yYWdlICAtLXJ1bi1hcy11c2VyIGNsaWVudC5j - c2ktcmJkLW5vZGUtcm9va3N0b3JhZ2UtcmVwbGljYXBvb2xgIgogICAgICAgICAgICArICJQUzog - QW4gZXhpc3Rpbmcgbm9uLXJlc3RyaWN0ZWQgdXNlciBjYW5ub3QgYmUgY29udmVydGVkIHRvIGEg - cmVzdHJpY3RlZCB1c2VyIGJ5IHVwZ3JhZGluZy4iCiAgICAgICAgICAgICsgIlVwZ3JhZGUgZmxh - ZyBzaG91bGQgb25seSBiZSB1c2VkIHRvIGFwcGVuZCBuZXcgcGVybWlzc2lvbnMgdG8gdXNlcnMs - IGl0IHNob3VsZG4ndCBiZSB1c2VkIGZvciBjaGFuZ2luZyB1c2VyIGFscmVhZHkgYXBwbGllZCBw - ZXJtaXNzaW9uLCBmb3IgZXhhbXBsZSB5b3Ugc2hvdWxkbid0IGNoYW5nZSBpbiB3aGljaCBwb29s - IHVzZXIgaGFzIGFjY2VzcyIsCiAgICAgICAgKQoKICAgICAgICAjIEFkZCBjb21tYW5kLWxpbmUg - YXJndW1lbnRzCiAgICAgICAgY29uZmlnX2dyb3VwID0gYXJnUC5hZGRfYXJndW1lbnRfZ3JvdXAo - ImNvbmZpZyIpCiAgICAgICAgY29uZmlnX2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAg - Ii0tY29uZmlnLWZpbGUiLAogICAgICAgICAgICB0eXBlPXN0ciwKICAgICAgICAgICAgaGVscD0i - UGF0aCB0byB0aGUgY29uZmlndXJhdGlvbiBmaWxlLCBQcmlvcml0eTogY29tbWFuZC1saW5lLWFy - Z3MgPiBjb25maWcuaW5pIGZpbGUgdmFsdWVzID4gZGVmYXVsdCB2YWx1ZXMiLAogICAgICAgICAg - ICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICApCgogICAg - ICAgIGlmIGFyZ3NfdG9fcGFyc2U6CiAgICAgICAgICAgIGFzc2VydCAoCiAgICAgICAgICAgICAg - ICB0eXBlKGFyZ3NfdG9fcGFyc2UpID09IGxpc3QKICAgICAgICAgICAgKSwgIkFyZ3VtZW50IHRv - ICdnZW5fYXJnX3BhcnNlcicgc2hvdWxkIGJlIGEgbGlzdCIKICAgICAgICBlbHNlOgogICAgICAg - ICAgICBhcmdzX3RvX3BhcnNlID0gc3lzLmFyZ3ZbMTpdCiAgICAgICAgcmV0dXJuIGFyZ1AucGFy - c2VfYXJncyhhcmdzX3RvX3BhcnNlKQoKICAgIGRlZiB2YWxpZGF0ZV9yYmRfbWV0YWRhdGFfZWNf - cG9vbF9uYW1lKHNlbGYpOgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmJkX21ldGFkYXRh - X2VjX3Bvb2xfbmFtZToKICAgICAgICAgICAgcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZSA9IHNl - bGYuX2FyZ19wYXJzZXIucmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQogICAgICAgICAgICByYmRf - cG9vbF9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5yYmRfZGF0YV9wb29sX25hbWUKCiAgICAgICAg - ICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRp - b25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJGbGFnICctLXJiZC1kYXRh - LXBvb2wtbmFtZScgc2hvdWxkIG5vdCBiZSBlbXB0eSIKICAgICAgICAgICAgICAgICkKCiAgICAg - ICAgICAgIGlmIHJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAg - ICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJG - bGFnICctLXJiZC1tZXRhZGF0YS1lYy1wb29sLW5hbWUnIHNob3VsZCBub3QgYmUgZW1wdHkiCiAg - ICAgICAgICAgICAgICApCgogICAgICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogIm9zZCBk - dW1wIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVy - cl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICBp - ZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFp - c2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBmIntjbWRf - anNvblsncHJlZml4J119IGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAgICAgICAgIGYi - RXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJ - U1R9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBtZXRhZGF0YV9wb29sX2V4aXN0LCBw - b29sX2V4aXN0ID0gRmFsc2UsIEZhbHNlCgogICAgICAgICAgICBmb3Iga2V5IGluIGpzb25fb3V0 - WyJwb29scyJdOgogICAgICAgICAgICAgICAgIyBpZiBlcmFzdXJlX2NvZGVfcHJvZmlsZSBpcyBl - bXB0eSBhbmQgcG9vbCBuYW1lIGV4aXN0cyB0aGVuIGl0IHJlcGxpY2EgcG9vbAogICAgICAgICAg - ICAgICAgaWYgKAogICAgICAgICAgICAgICAgICAgIGtleVsiZXJhc3VyZV9jb2RlX3Byb2ZpbGUi - XSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBrZXlbInBvb2xfbmFtZSJdID09IHJiZF9t - ZXRhZGF0YV9lY19wb29sX25hbWUKICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICAg - ICAgbWV0YWRhdGFfcG9vbF9leGlzdCA9IFRydWUKICAgICAgICAgICAgICAgICMgaWYgZXJhc3Vy - ZV9jb2RlX3Byb2ZpbGUgaXMgbm90IGVtcHR5IGFuZCBwb29sIG5hbWUgZXhpc3RzIHRoZW4gaXQg - aXMgZWMgcG9vbAogICAgICAgICAgICAgICAgaWYga2V5WyJlcmFzdXJlX2NvZGVfcHJvZmlsZSJd - IGFuZCBrZXlbInBvb2xfbmFtZSJdID09IHJiZF9wb29sX25hbWU6CiAgICAgICAgICAgICAgICAg - ICAgcG9vbF9leGlzdCA9IFRydWUKCiAgICAgICAgICAgIGlmIG5vdCBtZXRhZGF0YV9wb29sX2V4 - aXN0OgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAg - ICAgICAgICAgICAgICAgICAiUHJvdmlkZWQgcmJkX2VjX21ldGFkYXRhX3Bvb2wgbmFtZSwiCiAg - ICAgICAgICAgICAgICAgICAgZiIge3JiZF9tZXRhZGF0YV9lY19wb29sX25hbWV9LCBkb2VzIG5v - dCBleGlzdCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgbm90IHBvb2xfZXhpc3Q6 - CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg - ICAgICAgICAgICAgIGYiUHJvdmlkZWQgcmJkX2RhdGFfcG9vbCBuYW1lLCB7cmJkX3Bvb2xfbmFt - ZX0sIGRvZXMgbm90IGV4aXN0IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICByZXR1cm4g - cmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQoKICAgIGRlZiBkcnlfcnVuKHNlbGYsIG1zZyk6CiAg - ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICBwcmludCgiRXhl - Y3V0ZTogIiArICInIiArIG1zZyArICInIikKCiAgICBkZWYgdmFsaWRhdGVfcmd3X2VuZHBvaW50 - X3Rsc19jZXJ0KHNlbGYpOgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Rsc19jZXJ0 - X3BhdGg6CiAgICAgICAgICAgIHdpdGggb3BlbihzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2Vy - dF9wYXRoLCBlbmNvZGluZz0idXRmOCIpIGFzIGY6CiAgICAgICAgICAgICAgICBjb250ZW50cyA9 - IGYucmVhZCgpCiAgICAgICAgICAgICAgICByZXR1cm4gY29udGVudHMucnN0cmlwKCkKCiAgICBk - ZWYgX2NoZWNrX2NvbmZsaWN0aW5nX29wdGlvbnMoc2VsZik6CiAgICAgICAgaWYgbm90IHNlbGYu - X2FyZ19wYXJzZXIudXBncmFkZSBhbmQgbm90IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9v - bF9uYW1lOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAg - ICAgICAgICAgICAgIkVpdGhlciAnLS11cGdyYWRlJyBvciAnLS1yYmQtZGF0YS1wb29sLW5hbWUg - PHBvb2xfbmFtZT4nIHNob3VsZCBiZSBzcGVjaWZpZWQiCiAgICAgICAgICAgICkKCiAgICBkZWYg - X2ludmFsaWRfZW5kcG9pbnQoc2VsZiwgZW5kcG9pbnRfc3RyKToKICAgICAgICAjIGV4dHJhY3Qg - dGhlIHBvcnQgYnkgZ2V0dGluZyB0aGUgbGFzdCBzcGxpdCBvbiBgOmAgZGVsaW1pdGVyCiAgICAg - ICAgdHJ5OgogICAgICAgICAgICBlbmRwb2ludF9zdHJfaXAsIHBvcnQgPSBlbmRwb2ludF9zdHIu - cnNwbGl0KCI6IiwgMSkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgcmFp - c2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbihmIk5vdCBhIHByb3BlciBlbmRwb2ludDoge2Vu - ZHBvaW50X3N0cn0iKQoKICAgICAgICB0cnk6CiAgICAgICAgICAgIGlmIGVuZHBvaW50X3N0cl9p - cFswXSA9PSAiWyI6CiAgICAgICAgICAgICAgICBlbmRwb2ludF9zdHJfaXAgPSBlbmRwb2ludF9z - dHJfaXBbMSA6IGxlbihlbmRwb2ludF9zdHJfaXApIC0gMV0KICAgICAgICAgICAgaXBfdHlwZSA9 - ICgKICAgICAgICAgICAgICAgICJJUHY0IiBpZiB0eXBlKGlwX2FkZHJlc3MoZW5kcG9pbnRfc3Ry - X2lwKSkgaXMgSVB2NEFkZHJlc3MgZWxzZSAiSVB2NiIKICAgICAgICAgICAgKQogICAgICAgIGV4 - Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICBpcF90eXBlID0gIkZRRE4iCiAgICAgICAgaWYg - bm90IHBvcnQuaXNkaWdpdCgpOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj - ZXB0aW9uKGYiUG9ydCBub3QgdmFsaWQ6IHtwb3J0fSIpCiAgICAgICAgaW50UG9ydCA9IGludChw - b3J0KQogICAgICAgIGlmIGludFBvcnQgPCAxIG9yIGludFBvcnQgPiAyKioxNiAtIDE6CiAgICAg - ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oZiJPdXQgb2YgcmFuZ2UgcG9y - dCBudW1iZXI6IHtwb3J0fSIpCgogICAgICAgIHJldHVybiBpcF90eXBlCgogICAgZGVmIGVuZHBv - aW50X2RpYWwoc2VsZiwgZW5kcG9pbnRfc3RyLCBpcF90eXBlLCB0aW1lb3V0PTMsIGNlcnQ9Tm9u - ZSk6CiAgICAgICAgIyBpZiB0aGUgJ2NsdXN0ZXInIGluc3RhbmNlIGlzIGEgZHVtbXkgb25lLAog - ICAgICAgICMgZG9uJ3QgdHJ5IHRvIHJlYWNoIG91dCB0byB0aGUgZW5kcG9pbnQKICAgICAgICBp - ZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlSYWRvcyk6CiAgICAgICAgICAgIHJldHVy - biAiIiwgIiIsICIiCiAgICAgICAgaWYgaXBfdHlwZSA9PSAiSVB2NiI6CiAgICAgICAgICAgIHRy - eToKICAgICAgICAgICAgICAgIGVuZHBvaW50X3N0cl9pcCwgZW5kcG9pbnRfc3RyX3BvcnQgPSBl - bmRwb2ludF9zdHIucnNwbGl0KCI6IiwgMSkKICAgICAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6 - CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg - ICAgICAgICAgICAgIGYiTm90IGEgcHJvcGVyIGVuZHBvaW50OiB7ZW5kcG9pbnRfc3RyfSIKICAg - ICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgZW5kcG9pbnRfc3RyX2lwWzBdICE9ICJbIjoK - ICAgICAgICAgICAgICAgIGVuZHBvaW50X3N0cl9pcCA9ICJbIiArIGVuZHBvaW50X3N0cl9pcCAr - ICJdIgogICAgICAgICAgICBlbmRwb2ludF9zdHIgPSAiOiIuam9pbihbZW5kcG9pbnRfc3RyX2lw - LCBlbmRwb2ludF9zdHJfcG9ydF0pCgogICAgICAgIHByb3RvY29scyA9IFsiaHR0cCIsICJodHRw - cyJdCiAgICAgICAgcmVzcG9uc2VfZXJyb3IgPSBOb25lCiAgICAgICAgZm9yIHByZWZpeCBpbiBw - cm90b2NvbHM6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGVwID0gZiJ7cHJlZml4 - fTovL3tlbmRwb2ludF9zdHJ9IgogICAgICAgICAgICAgICAgdmVyaWZ5ID0gTm9uZQogICAgICAg - ICAgICAgICAgIyBJZiB2ZXJpZnkgaXMgc2V0IHRvIGEgcGF0aCB0byBhIGRpcmVjdG9yeSwKICAg - ICAgICAgICAgICAgICMgdGhlIGRpcmVjdG9yeSBtdXN0IGhhdmUgYmVlbiBwcm9jZXNzZWQgdXNp - bmcgdGhlIGNfcmVoYXNoIHV0aWxpdHkgc3VwcGxpZWQgd2l0aCBPcGVuU1NMLgogICAgICAgICAg - ICAgICAgaWYgcHJlZml4ID09ICJodHRwcyIgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3NraXBf - dGxzOgogICAgICAgICAgICAgICAgICAgIHZlcmlmeSA9IEZhbHNlCiAgICAgICAgICAgICAgICAg - ICAgciA9IHJlcXVlc3RzLmhlYWQoZXAsIHRpbWVvdXQ9dGltZW91dCwgdmVyaWZ5PUZhbHNlKQog - ICAgICAgICAgICAgICAgZWxpZiBwcmVmaXggPT0gImh0dHBzIiBhbmQgY2VydDoKICAgICAgICAg - ICAgICAgICAgICB2ZXJpZnkgPSBjZXJ0CiAgICAgICAgICAgICAgICAgICAgciA9IHJlcXVlc3Rz - LmhlYWQoZXAsIHRpbWVvdXQ9dGltZW91dCwgdmVyaWZ5PWNlcnQpCiAgICAgICAgICAgICAgICBl - bHNlOgogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0cy5oZWFkKGVwLCB0aW1lb3V0PXRp - bWVvdXQpCiAgICAgICAgICAgICAgICBpZiByLnN0YXR1c19jb2RlID09IDIwMDoKICAgICAgICAg - ICAgICAgICAgICByZXR1cm4gcHJlZml4LCB2ZXJpZnksICIiCiAgICAgICAgICAgIGV4Y2VwdCBF - eGNlcHRpb24gYXMgZXJyOgogICAgICAgICAgICAgICAgcmVzcG9uc2VfZXJyb3IgPSBlcnIKICAg - ICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgc3lzLnN0ZGVyci53cml0ZSgKICAgICAgICAg - ICAgZiJ1bmFibGUgdG8gY29ubmVjdCB0byBlbmRwb2ludDoge2VuZHBvaW50X3N0cn0sIGZhaWxl - ZCBlcnJvcjoge3Jlc3BvbnNlX2Vycm9yfSIKICAgICAgICApCiAgICAgICAgcmV0dXJuICgKICAg - ICAgICAgICAgIiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAoIi0xIiksCiAgICAgICAg - KQoKICAgIGRlZiBwYXJzZV9jb25maWdfZmlsZShzZWxmLCBjb25maWdfZmlsZSk6CiAgICAgICAg - Y29uZmlnID0gY29uZmlncGFyc2VyLkNvbmZpZ1BhcnNlcigpCiAgICAgICAgY29uZmlnLnJlYWQo - Y29uZmlnX2ZpbGUpCiAgICAgICAgZm9yIGFyZyBpbiBsaXN0KHZhcnMoc2VsZi5fYXJnX3BhcnNl - cikpOgogICAgICAgICAgICAjIHB5dGhvbiB0cmVhdHMgZmxhZy1uYW1lIGFzIGZsYWdfbmFtZSBp - bnRlcm5hbGx5LCBzbyBjb252ZXJ0aW5nIGJhY2sgdG8gZmxhZy1uYW1lLAogICAgICAgICAgICAj - IHNvIHdlIGNhbiBnZXQgdGhvc2UgdmFsdWVzIGZyb20gY29uZmlnIGZpbGUKICAgICAgICAgICAg - YXJndW1lbnQgPSBhcmcucmVwbGFjZSgiXyIsICItIikKICAgICAgICAgICAgYXJndW1lbnRWYWx1 - ZSA9IHN0cihnZXRhdHRyKHNlbGYuX2FyZ19wYXJzZXIsIGFyZykpCiAgICAgICAgICAgIGNvbmZp - Z192YWx1ZSA9IGNvbmZpZy5nZXQoIkNvbmZpZ3VyYXRpb25zIiwgYXJndW1lbnQsIGZhbGxiYWNr - PU5vbmUpCiAgICAgICAgICAgICMgZ2l2ZSBwcmlvcml0eSB0byBjb21tYW5kIGxpbmUgYXJndW1l - bnQsIGlmIGNvbW1hbmQgbGluZSBhcmd1bWVudCBpcyBub3QgcHJlc2VudCB1c2UgY29uZmlnLmlu - aSB2YWx1ZSwKICAgICAgICAgICAgaWYgKHN0cihzeXMuYXJndikuZmluZChhcmd1bWVudCkgPT0g - LTEpIGFuZCAoCiAgICAgICAgICAgICAgICAoY29uZmlnX3ZhbHVlICE9IE5vbmUpIGFuZCAoY29u - ZmlnX3ZhbHVlICE9ICIiKQogICAgICAgICAgICApOgogICAgICAgICAgICAgICAgc2VsZi5fYXJn - X3BhcnNlci5fX3NldGF0dHJfXyhhcmcsIGNvbmZpZ192YWx1ZSkKCiAgICAgICAgcmV0dXJuIGNv - bmZpZwoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhcmdfbGlzdD1Ob25lKToKICAgICAgICBzZWxm - Lm91dF9tYXAgPSB7fQogICAgICAgIHNlbGYuX2V4Y2x1ZGVkX2tleXMgPSBzZXQoKQogICAgICAg - IHNlbGYuX2FyZ19wYXJzZXIgPSBzZWxmLmdlbl9hcmdfcGFyc2VyKGFyZ3NfdG9fcGFyc2U9YXJn - X2xpc3QpCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jb25maWdfZmlsZToKICAgICAgICAg - ICAgc2VsZi5jb25maWcgPSBzZWxmLnBhcnNlX2NvbmZpZ19maWxlKHNlbGYuX2FyZ19wYXJzZXIu - Y29uZmlnX2ZpbGUpCiAgICAgICAgc2VsZi5fY2hlY2tfY29uZmxpY3Rpbmdfb3B0aW9ucygpCiAg - ICAgICAgc2VsZi5ydW5fYXNfdXNlciA9IHNlbGYuX2FyZ19wYXJzZXIucnVuX2FzX3VzZXIKICAg - ICAgICBzZWxmLm91dHB1dF9maWxlID0gc2VsZi5fYXJnX3BhcnNlci5vdXRwdXQKICAgICAgICBz - ZWxmLmNlcGhfY29uZiA9IHNlbGYuX2FyZ19wYXJzZXIuY2VwaF9jb25mCiAgICAgICAgc2VsZi5j - ZXBoX2tleXJpbmcgPSBzZWxmLl9hcmdfcGFyc2VyLmtleXJpbmcKICAgICAgICAjIGlmIHVzZXIg - bm90IHByb3ZpZGVkLCBnaXZlIGEgZGVmYXVsdCB1c2VyCiAgICAgICAgaWYgbm90IHNlbGYucnVu - X2FzX3VzZXIgYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVwZ3JhZGU6CiAgICAgICAgICAgIHNl - bGYucnVuX2FzX3VzZXIgPSBzZWxmLkVYVEVSTkFMX1VTRVJfTkFNRQogICAgICAgIGlmIG5vdCBz - ZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeCBhbmQgbm90IHNlbGYuX2FyZ19wYXJzZXIu - dXBncmFkZToKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXggPSBz - ZWxmLkRFRkFVTFRfUkdXX1BPT0xfUFJFRklYCiAgICAgICAgaWYgc2VsZi5jZXBoX2NvbmY6CiAg - ICAgICAgICAgIGt3YXJncyA9IHt9CiAgICAgICAgICAgIGlmIHNlbGYuY2VwaF9rZXlyaW5nOgog - ICAgICAgICAgICAgICAga3dhcmdzWyJjb25mIl0gPSB7ImtleXJpbmciOiBzZWxmLmNlcGhfa2V5 - cmluZ30KICAgICAgICAgICAgc2VsZi5jbHVzdGVyID0gcmFkb3MuUmFkb3MoY29uZmZpbGU9c2Vs - Zi5jZXBoX2NvbmYsICoqa3dhcmdzKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYuY2x1 - c3RlciA9IHJhZG9zLlJhZG9zKCkKICAgICAgICAgICAgc2VsZi5jbHVzdGVyLmNvbmZfcmVhZF9m - aWxlKCkKICAgICAgICBzZWxmLmNsdXN0ZXIuY29ubmVjdCgpCgogICAgZGVmIHNodXRkb3duKHNl - bGYpOgogICAgICAgIGlmIHNlbGYuY2x1c3Rlci5zdGF0ZSA9PSAiY29ubmVjdGVkIjoKICAgICAg - ICAgICAgc2VsZi5jbHVzdGVyLnNodXRkb3duKCkKCiAgICBkZWYgZ2V0X2ZzaWQoc2VsZik6CiAg - ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2Vs - Zi5kcnlfcnVuKCJjZXBoIGZzaWQiKQogICAgICAgIHJldHVybiBzdHIoc2VsZi5jbHVzdGVyLmdl - dF9mc2lkKCkpCgogICAgZGVmIF9jb21tb25fY21kX2pzb25fZ2VuKHNlbGYsIGNtZF9qc29uKToK - ICAgICAgICBjbWQgPSBqc29uLmR1bXBzKGNtZF9qc29uLCBzb3J0X2tleXM9VHJ1ZSkKICAgICAg - ICByZXRfdmFsLCBjbWRfb3V0LCBlcnJfbXNnID0gc2VsZi5jbHVzdGVyLm1vbl9jb21tYW5kKGNt - ZCwgYiIiKQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudmVyYm9zZToKICAgICAgICAgICAg - cHJpbnQoZiJDb21tYW5kIElucHV0OiB7Y21kfSIpCiAgICAgICAgICAgIHByaW50KAogICAgICAg - ICAgICAgICAgZiJSZXR1cm4gVmFsOiB7cmV0X3ZhbH1cbkNvbW1hbmQgT3V0cHV0OiB7Y21kX291 - dH1cbiIKICAgICAgICAgICAgICAgIGYiRXJyb3IgTWVzc2FnZToge2Vycl9tc2d9XG4tLS0tLS0t - LS0tXG4iCiAgICAgICAgICAgICkKICAgICAgICBqc29uX291dCA9IHt9CiAgICAgICAgIyBpZiB0 - aGVyZSBpcyBubyBlcnJvciAoaS5lOyByZXRfdmFsIGlzIFpFUk8pIGFuZCAnY21kX291dCcgaXMg - bm90IGVtcHR5CiAgICAgICAgIyB0aGVuIGNvbnZlcnQgJ2NtZF9vdXQnIHRvIGEganNvbiBvdXRw - dXQKICAgICAgICBpZiByZXRfdmFsID09IDAgYW5kIGNtZF9vdXQ6CiAgICAgICAgICAgIGpzb25f - b3V0ID0ganNvbi5sb2FkcyhjbWRfb3V0KQogICAgICAgIHJldHVybiByZXRfdmFsLCBqc29uX291 - dCwgZXJyX21zZwoKICAgIGRlZiBnZXRfY2VwaF9leHRlcm5hbF9tb25fZGF0YShzZWxmKToKICAg - ICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogInF1b3J1bV9zdGF0dXMiLCAiZm9ybWF0IjogImpz - b24ifQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0 - dXJuIHNlbGYuZHJ5X3J1bigiY2VwaCAiICsgY21kX2pzb25bInByZWZpeCJdKQogICAgICAgIHJl - dF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRf - anNvbikKICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAg - ICAgIGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJh - aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAiJ3F1b3J1bV9z - dGF0dXMnIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9t - c2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAg - ICAgICkKICAgICAgICBxX2xlYWRlcl9uYW1lID0ganNvbl9vdXRbInF1b3J1bV9sZWFkZXJfbmFt - ZSJdCiAgICAgICAgcV9sZWFkZXJfZGV0YWlscyA9IHt9CiAgICAgICAgcV9sZWFkZXJfbWF0Y2hp - bmdfbGlzdCA9IFsKICAgICAgICAgICAgbCBmb3IgbCBpbiBqc29uX291dFsibW9ubWFwIl1bIm1v - bnMiXSBpZiBsWyJuYW1lIl0gPT0gcV9sZWFkZXJfbmFtZQogICAgICAgIF0KICAgICAgICBpZiBs - ZW4ocV9sZWFkZXJfbWF0Y2hpbmdfbGlzdCkgPT0gMDoKICAgICAgICAgICAgcmFpc2UgRXhlY3V0 - aW9uRmFpbHVyZUV4Y2VwdGlvbigiTm8gbWF0Y2hpbmcgJ21vbicgZGV0YWlscyBmb3VuZCIpCiAg - ICAgICAgcV9sZWFkZXJfZGV0YWlscyA9IHFfbGVhZGVyX21hdGNoaW5nX2xpc3RbMF0KICAgICAg - ICAjIGdldCB0aGUgYWRkcmVzcyB2ZWN0b3Igb2YgdGhlIHF1b3J1bS1sZWFkZXIKICAgICAgICBx - X2xlYWRlcl9hZGRydmVjID0gcV9sZWFkZXJfZGV0YWlscy5nZXQoInB1YmxpY19hZGRycyIsIHt9 - KS5nZXQoImFkZHJ2ZWMiLCBbXSkKICAgICAgICBpcF9hZGRyID0gc3RyKHFfbGVhZGVyX2RldGFp - bHNbInB1YmxpY19hZGRyIl0uc3BsaXQoIi8iKVswXSkKCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh - cnNlci52Ml9wb3J0X2VuYWJsZToKICAgICAgICAgICAgaWYgcV9sZWFkZXJfYWRkcnZlY1swXVsi - dHlwZSJdID09ICJ2MiI6CiAgICAgICAgICAgICAgICBpcF9hZGRyID0gcV9sZWFkZXJfYWRkcnZl - Y1swXVsiYWRkciJdCiAgICAgICAgICAgIGVsaWYgbGVuKHFfbGVhZGVyX2FkZHJ2ZWMpID4gMSBh - bmQgcV9sZWFkZXJfYWRkcnZlY1sxXVsidHlwZSJdID09ICJ2MiI6CiAgICAgICAgICAgICAgICBp - cF9hZGRyID0gcV9sZWFkZXJfYWRkcnZlY1sxXVsiYWRkciJdCiAgICAgICAgICAgIGVsc2U6CiAg - ICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKAogICAgICAgICAgICAgICAgICAgICIndjIn - IGFkZHJlc3MgdHlwZSBub3QgcHJlc2VudCwgYW5kICd2Mi1wb3J0LWVuYWJsZScgZmxhZyBpcyBw - cm92aWRlZCIKICAgICAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIGYie3N0cihxX2xlYWRl - cl9uYW1lKX09e2lwX2FkZHJ9IgoKICAgIGRlZiBfY29udmVydF9ob3N0bmFtZV90b19pcChzZWxm - LCBob3N0X25hbWUsIHBvcnQsIGlwX3R5cGUpOgogICAgICAgICMgaWYgJ2NsdXN0ZXInIGluc3Rh - bmNlIGlzIGEgZHVtbXkgdHlwZSwKICAgICAgICAjIGNhbGwgdGhlIGR1bW15IGluc3RhbmNlJ3Mg - ImNvbnZlcnQiIG1ldGhvZAogICAgICAgIGlmIG5vdCBob3N0X25hbWU6CiAgICAgICAgICAgIHJh - aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oIkVtcHR5IGhvc3RuYW1lIHByb3ZpZGVkIikK - ICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlSYWRvcyk6CiAgICAgICAg - ICAgIHJldHVybiBzZWxmLmNsdXN0ZXIuX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoaG9zdF9uYW1l - KQoKICAgICAgICBpZiBpcF90eXBlID09ICJGUUROIjoKICAgICAgICAgICAgIyBjaGVjayB3aGlj - aCBpcCBGUUROIHNob3VsZCBiZSBjb252ZXJ0ZWQgdG8sIElQdjQgb3IgSVB2NgogICAgICAgICAg - ICAjIGNoZWNrIHRoZSBob3N0IGlwLCB0aGUgZW5kcG9pbnQgaXAgdHlwZSB3b3VsZCBiZSBzaW1p - bGFyIHRvIGhvc3QgaXAKICAgICAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJvcmNoIGhv - c3QgbHMiLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgICAgICByZXRfdmFsLCBqc29uX291dCwg - ZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgICAg - ICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0dGVtcHQsCiAgICAgICAgICAgIGlmIHJl - dF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgICAgICByYWlzZSBF - eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICInb3JjaCBob3N0 - IGxzJyBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgICAgICBmIkVycm9yOiB7ZXJy - X21zZyBpZiByZXRfdmFsICE9IDAgZWxzZSBzZWxmLkVNUFRZX09VVFBVVF9MSVNUfSIKICAgICAg - ICAgICAgICAgICkKICAgICAgICAgICAgaG9zdF9hZGRyID0ganNvbl9vdXRbMF1bImFkZHIiXQog - ICAgICAgICAgICAjIGFkZCA6ODAgc2FtcGxlIHBvcnQgaW4gaXBfdHlwZSwgYXMgX2ludmFsaWRf - ZW5kcG9pbnQgYWxzbyB2ZXJpZnkgcG9ydAogICAgICAgICAgICBob3N0X2lwX3R5cGUgPSBzZWxm - Ll9pbnZhbGlkX2VuZHBvaW50KGhvc3RfYWRkciArICI6ODAiKQogICAgICAgICAgICBpbXBvcnQg - c29ja2V0CgogICAgICAgICAgICBpcCA9IFtdCiAgICAgICAgICAgICMgZXhhbXBsZSBvdXRwdXQg - Wyg8QWRkcmVzc0ZhbWlseS5BRl9JTkVUOiAyPiwgPFNvY2tldEtpbmQuU09DS19TVFJFQU06IDE+ - LCA2LCAnJywgKCc5My4xODQuMjE2LjM0JywgODApKSwgLi4uXQogICAgICAgICAgICAjIHdlIG5l - ZWQgdG8gZ2V0IDkzLjE4NC4yMTYuMzQgc28gaXQgd291bGQgYmUgaXBbMF1bNF1bMF0KICAgICAg - ICAgICAgaWYgaG9zdF9pcF90eXBlID09ICJJUHY2IjoKICAgICAgICAgICAgICAgIGlwID0gc29j - a2V0LmdldGFkZHJpbmZvKAogICAgICAgICAgICAgICAgICAgIGhvc3RfbmFtZSwgcG9ydCwgZmFt - aWx5PXNvY2tldC5BRl9JTkVUNiwgcHJvdG89c29ja2V0LklQUFJPVE9fVENQCiAgICAgICAgICAg - ICAgICApCiAgICAgICAgICAgIGVsaWYgaG9zdF9pcF90eXBlID09ICJJUHY0IjoKICAgICAgICAg - ICAgICAgIGlwID0gc29ja2V0LmdldGFkZHJpbmZvKAogICAgICAgICAgICAgICAgICAgIGhvc3Rf - bmFtZSwgcG9ydCwgZmFtaWx5PXNvY2tldC5BRl9JTkVULCBwcm90bz1zb2NrZXQuSVBQUk9UT19U - Q1AKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgZGVsIHNvY2tldAogICAgICAgICAgICBy - ZXR1cm4gaXBbMF1bNF1bMF0KICAgICAgICByZXR1cm4gaG9zdF9uYW1lCgogICAgZGVmIGdldF9h - Y3RpdmVfYW5kX3N0YW5kYnlfbWdycyhzZWxmKToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2Vy - LmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiAiIiwgc2VsZi5kcnlfcnVuKCJjZXBoIHN0YXR1 - cyIpCiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0ID0gc2VsZi5fYXJnX3BhcnNlci5t - b25pdG9yaW5nX2VuZHBvaW50X3BvcnQKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xp - c3QgPSBzZWxmLl9hcmdfcGFyc2VyLm1vbml0b3JpbmdfZW5kcG9pbnQKICAgICAgICBzdGFuZGJ5 - X21ncnMgPSBbXQogICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3Q6CiAg - ICAgICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAic3RhdHVzIiwgImZvcm1hdCI6ICJqc29u - In0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25f - Y21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3Vj - Y2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgICAgICBpZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25f - b3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv - bigKICAgICAgICAgICAgICAgICAgICAiJ21nciBzZXJ2aWNlcycgY29tbWFuZCBmYWlsZWQuXG4i - CiAgICAgICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVs - c2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAg - IG1vbml0b3JpbmdfZW5kcG9pbnQgPSAoCiAgICAgICAgICAgICAgICBqc29uX291dC5nZXQoIm1n - cm1hcCIsIHt9KS5nZXQoInNlcnZpY2VzIiwge30pLmdldCgicHJvbWV0aGV1cyIsICIiKQogICAg - ICAgICAgICApCiAgICAgICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2VuZHBvaW50OgogICAgICAg + Ii0tbW9uaXRvcmluZy1lbmRwb2ludC1wb3J0IiwKICAgICAgICAgICAgZGVmYXVsdD0iIiwKICAg + ICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAgICAgIGhlbHA9IkNlcGggTWFuYWdlciBw + cm9tZXRoZXVzIGV4cG9ydGVyIHBvcnQiLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAu + YWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1za2lwLW1vbml0b3JpbmctZW5kcG9pbnQiLAog + ICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAgICAgICBhY3Rpb249InN0b3JlX3RydWUi + LAogICAgICAgICAgICBoZWxwPSJEbyBub3QgY2hlY2sgZm9yIGEgbW9uaXRvcmluZyBlbmRwb2lu + dCBmb3IgdGhlIENlcGggY2x1c3RlciIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5h + ZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXJiZC1tZXRhZGF0YS1lYy1wb29sLW5hbWUiLAog + ICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAg + ICAgICAgaGVscD0iUHJvdmlkZXMgdGhlIG5hbWUgb2YgZXJhc3VyZSBjb2RlZCBSQkQgbWV0YWRh + dGEgcG9vbCIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAg + ICAgICAgICAgICItLWRyeS1ydW4iLAogICAgICAgICAgICBkZWZhdWx0PUZhbHNlLAogICAgICAg + ICAgICBhY3Rpb249InN0b3JlX3RydWUiLAogICAgICAgICAgICBoZWxwPSJEcnkgcnVuIHByaW50 + cyB0aGUgZXhlY3V0ZWQgY29tbWFuZHMgd2l0aG91dCBydW5uaW5nIHRoZW0iLAogICAgICAgICkK + ICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1yYWRvcy1u + YW1lc3BhY2UiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1G + YWxzZSwKICAgICAgICAgICAgaGVscD0iRGl2aWRlcyBhIHBvb2wgaW50byBzZXBhcmF0ZSBsb2dp + Y2FsIG5hbWVzcGFjZXMsIHVzZWQgZm9yIGNyZWF0aW5nIFJCRCBQVkMgaW4gYSBDZXBoQmxvY2tQ + b29sUmFkb3NOYW1lc3BhY2UgKHNob3VsZCBiZSBsb3dlciBjYXNlKSIsCiAgICAgICAgKQogICAg + ICAgIG91dHB1dF9ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLXN1YnZvbHVtZS1n + cm91cCIsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgICAgIHJlcXVpcmVkPUZhbHNl + LAogICAgICAgICAgICBoZWxwPSJwcm92aWRlcyB0aGUgbmFtZSBvZiB0aGUgc3Vidm9sdW1lIGdy + b3VwIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAg + ICAgICAgIi0tcmd3LXJlYWxtLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAg + ICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlkZXMgdGhlIG5hbWUg + b2YgdGhlIHJndy1yZWFsbSIsCiAgICAgICAgKQogICAgICAgIG91dHB1dF9ncm91cC5hZGRfYXJn + dW1lbnQoCiAgICAgICAgICAgICItLXJndy16b25lLW5hbWUiLAogICAgICAgICAgICBkZWZhdWx0 + PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0icHJvdmlk + ZXMgdGhlIG5hbWUgb2YgdGhlIHJndy16b25lIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dy + b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cC1uYW1lIiwKICAg + ICAgICAgICAgZGVmYXVsdD0iIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFsc2UsCiAgICAgICAg + ICAgIGhlbHA9InByb3ZpZGVzIHRoZSBuYW1lIG9mIHRoZSByZ3ctem9uZWdyb3VwIiwKICAgICAg + ICApCiAgICAgICAgb3V0cHV0X2dyb3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tdG9w + b2xvZ3ktcG9vbHMiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJl + ZD1GYWxzZSwKICAgICAgICAgICAgaGVscD0iY29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgdG9wb2xv + Z3ktY29uc3RyYWluZWQgcmJkIHBvb2xzIiwKICAgICAgICApCiAgICAgICAgb3V0cHV0X2dyb3Vw + LmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tdG9wb2xvZ3ktZmFpbHVyZS1kb21haW4tbGFi + ZWwiLAogICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwK + ICAgICAgICAgICAgaGVscD0iazhzIGNsdXN0ZXIgZmFpbHVyZSBkb21haW4gbGFiZWwgKGV4YW1w + bGU6IHpvbmUsIHJhY2ssIG9yIGhvc3QpIGZvciB0aGUgdG9wb2xvZ3ktcG9vbHMgdGhhdCBtYXRj + aCB0aGUgY2VwaCBkb21haW4iLAogICAgICAgICkKICAgICAgICBvdXRwdXRfZ3JvdXAuYWRkX2Fy + Z3VtZW50KAogICAgICAgICAgICAiLS10b3BvbG9neS1mYWlsdXJlLWRvbWFpbi12YWx1ZXMiLAog + ICAgICAgICAgICBkZWZhdWx0PSIiLAogICAgICAgICAgICByZXF1aXJlZD1GYWxzZSwKICAgICAg + ICAgICAgaGVscD0iY29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgdGhlIGs4cyBjbHVzdGVyIGZhaWx1 + cmUgZG9tYWluIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggb2YgdGhlIHBvb2xzIGluIHRo + ZSBgdG9wb2xvZ3ktcG9vbHNgIGxpc3QiLAogICAgICAgICkKCiAgICAgICAgdXBncmFkZV9ncm91 + cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJ1cGdyYWRlIikKICAgICAgICB1cGdyYWRlX2dy + b3VwLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tdXBncmFkZSIsCiAgICAgICAgICAgIGFj + dGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgIGRlZmF1bHQ9RmFsc2UsCiAgICAgICAgICAg + IGhlbHA9IlVwZ3JhZGVzIHRoZSBjZXBoQ1NJS2V5cmluZ3MoRm9yIGV4YW1wbGU6IGNsaWVudC5j + c2ktY2VwaGZzLXByb3Zpc2lvbmVyKSBhbmQgY2xpZW50LmhlYWx0aGNoZWNrZXIgY2VwaCB1c2Vy + cyB3aXRoIG5ldyBwZXJtaXNzaW9ucyBuZWVkZWQgZm9yIHRoZSBuZXcgY2x1c3RlciB2ZXJzaW9u + IGFuZCBvbGRlciBwZXJtaXNzaW9uIHdpbGwgc3RpbGwgYmUgYXBwbGllZC4iCiAgICAgICAgICAg + ICsgIlNhbXBsZSBydW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rl + ci1yZXNvdXJjZXMucHkgLS11cGdyYWRlYCwgdGhpcyB3aWxsIHVwZ3JhZGUgYWxsIHRoZSBkZWZh + dWx0IGNzaSB1c2Vycyhub24tcmVzdHJpY3RlZCkiCiAgICAgICAgICAgICsgIkZvciByZXN0cmlj + dGVkIHVzZXJzKEZvciBleGFtcGxlOiBjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lci1vcGVu + c2hpZnQtc3RvcmFnZS1teWZzKSwgdXNlcnMgY3JlYXRlZCB1c2luZyAtLXJlc3RyaWN0ZWQtYXV0 + aC1wZXJtaXNzaW9uIGZsYWcgbmVlZCB0byBwYXNzIG1hbmRhdG9yeSBmbGFncyIKICAgICAgICAg + ICAgKyAibWFuZGF0b3J5IGZsYWdzOiAnLS1yYmQtZGF0YS1wb29sLW5hbWUsIC0tazhzLWNsdXN0 + ZXItbmFtZSBhbmQgLS1ydW4tYXMtdXNlcicgZmxhZ3Mgd2hpbGUgdXBncmFkaW5nIgogICAgICAg + ICAgICArICJpbiBjYXNlIG9mIGNlcGhmcyB1c2VycyBpZiB5b3UgaGF2ZSBwYXNzZWQgLS1jZXBo + ZnMtZmlsZXN5c3RlbS1uYW1lIGZsYWcgd2hpbGUgY3JlYXRpbmcgdXNlciB0aGVuIHdoaWxlIHVw + Z3JhZGluZyBpdCB3aWxsIGJlIG1hbmRhdG9yeSB0b28iCiAgICAgICAgICAgICsgIlNhbXBsZSBy + dW46IGBweXRob24zIC9ldGMvY2VwaC9jcmVhdGUtZXh0ZXJuYWwtY2x1c3Rlci1yZXNvdXJjZXMu + cHkgLS11cGdyYWRlIC0tcmJkLWRhdGEtcG9vbC1uYW1lIHJlcGxpY2Fwb29sIC0tazhzLWNsdXN0 + ZXItbmFtZSByb29rc3RvcmFnZSAgLS1ydW4tYXMtdXNlciBjbGllbnQuY3NpLXJiZC1ub2RlLXJv + b2tzdG9yYWdlLXJlcGxpY2Fwb29sYCIKICAgICAgICAgICAgKyAiUFM6IEFuIGV4aXN0aW5nIG5v + bi1yZXN0cmljdGVkIHVzZXIgY2Fubm90IGJlIGNvbnZlcnRlZCB0byBhIHJlc3RyaWN0ZWQgdXNl + ciBieSB1cGdyYWRpbmcuIgogICAgICAgICAgICArICJVcGdyYWRlIGZsYWcgc2hvdWxkIG9ubHkg + YmUgdXNlZCB0byBhcHBlbmQgbmV3IHBlcm1pc3Npb25zIHRvIHVzZXJzLCBpdCBzaG91bGRuJ3Qg + YmUgdXNlZCBmb3IgY2hhbmdpbmcgdXNlciBhbHJlYWR5IGFwcGxpZWQgcGVybWlzc2lvbiwgZm9y + IGV4YW1wbGUgeW91IHNob3VsZG4ndCBjaGFuZ2UgaW4gd2hpY2ggcG9vbCB1c2VyIGhhcyBhY2Nl + c3MiLAogICAgICAgICkKCiAgICAgICAgIyBBZGQgY29tbWFuZC1saW5lIGFyZ3VtZW50cwogICAg + ICAgIGNvbmZpZ19ncm91cCA9IGFyZ1AuYWRkX2FyZ3VtZW50X2dyb3VwKCJjb25maWciKQogICAg + ICAgIGNvbmZpZ19ncm91cC5hZGRfYXJndW1lbnQoCiAgICAgICAgICAgICItLWNvbmZpZy1maWxl + IiwKICAgICAgICAgICAgdHlwZT1zdHIsCiAgICAgICAgICAgIGhlbHA9IlBhdGggdG8gdGhlIGNv + bmZpZ3VyYXRpb24gZmlsZSwgUHJpb3JpdHk6IGNvbW1hbmQtbGluZS1hcmdzID4gY29uZmlnLmlu + aSBmaWxlIHZhbHVlcyA+IGRlZmF1bHQgdmFsdWVzIiwKICAgICAgICAgICAgcmVxdWlyZWQ9RmFs + c2UsCiAgICAgICAgICAgIGRlZmF1bHQ9IiIsCiAgICAgICAgKQoKICAgICAgICBpZiBhcmdzX3Rv + X3BhcnNlOgogICAgICAgICAgICBhc3NlcnQgKAogICAgICAgICAgICAgICAgdHlwZShhcmdzX3Rv + X3BhcnNlKSA9PSBsaXN0CiAgICAgICAgICAgICksICJBcmd1bWVudCB0byAnZ2VuX2FyZ19wYXJz + ZXInIHNob3VsZCBiZSBhIGxpc3QiCiAgICAgICAgZWxzZToKICAgICAgICAgICAgYXJnc190b19w + YXJzZSA9IHN5cy5hcmd2WzE6XQogICAgICAgIHJldHVybiBhcmdQLnBhcnNlX2FyZ3MoYXJnc190 + b19wYXJzZSkKCiAgICBkZWYgdmFsaWRhdGVfcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZShzZWxm + KToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJiZF9tZXRhZGF0YV9lY19wb29sX25hbWU6 + CiAgICAgICAgICAgIHJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFyc2Vy + LnJiZF9tZXRhZGF0YV9lY19wb29sX25hbWUKICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNl + bGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCgogICAgICAgICAgICBpZiByYmRfcG9v + bF9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2Vw + dGlvbigKICAgICAgICAgICAgICAgICAgICAiRmxhZyAnLS1yYmQtZGF0YS1wb29sLW5hbWUnIHNo + b3VsZCBub3QgYmUgZW1wdHkiCiAgICAgICAgICAgICAgICApCgogICAgICAgICAgICBpZiByYmRf + bWV0YWRhdGFfZWNfcG9vbF9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0 + aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiRmxhZyAnLS1yYmQtbWV0 + YWRhdGEtZWMtcG9vbC1uYW1lJyBzaG91bGQgbm90IGJlIGVtcHR5IgogICAgICAgICAgICAgICAg + KQoKICAgICAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJvc2QgZHVtcCIsICJmb3JtYXQi + OiAianNvbiJ9CiAgICAgICAgICAgIHJldF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5f + Y29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICAgICAgaWYgcmV0X3ZhbCAhPSAw + IG9yIGxlbihqc29uX291dCkgPT0gMDoKICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgZiJ7Y21kX2pzb25bJ3ByZWZpeCdd + fSBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgICAgICBmIkVycm9yOiB7ZXJyX21z + ZyBpZiByZXRfdmFsICE9IDAgZWxzZSBzZWxmLkVNUFRZX09VVFBVVF9MSVNUfSIKICAgICAgICAg + ICAgICAgICkKICAgICAgICAgICAgbWV0YWRhdGFfcG9vbF9leGlzdCwgcG9vbF9leGlzdCA9IEZh + bHNlLCBGYWxzZQoKICAgICAgICAgICAgZm9yIGtleSBpbiBqc29uX291dFsicG9vbHMiXToKICAg + ICAgICAgICAgICAgICMgaWYgZXJhc3VyZV9jb2RlX3Byb2ZpbGUgaXMgZW1wdHkgYW5kIHBvb2wg + bmFtZSBleGlzdHMgdGhlbiBpdCByZXBsaWNhIHBvb2wKICAgICAgICAgICAgICAgIGlmICgKICAg + ICAgICAgICAgICAgICAgICBrZXlbImVyYXN1cmVfY29kZV9wcm9maWxlIl0gPT0gIiIKICAgICAg + ICAgICAgICAgICAgICBhbmQga2V5WyJwb29sX25hbWUiXSA9PSByYmRfbWV0YWRhdGFfZWNfcG9v + bF9uYW1lCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhX3Bv + b2xfZXhpc3QgPSBUcnVlCiAgICAgICAgICAgICAgICAjIGlmIGVyYXN1cmVfY29kZV9wcm9maWxl + IGlzIG5vdCBlbXB0eSBhbmQgcG9vbCBuYW1lIGV4aXN0cyB0aGVuIGl0IGlzIGVjIHBvb2wKICAg + ICAgICAgICAgICAgIGlmIGtleVsiZXJhc3VyZV9jb2RlX3Byb2ZpbGUiXSBhbmQga2V5WyJwb29s + X25hbWUiXSA9PSByYmRfcG9vbF9uYW1lOgogICAgICAgICAgICAgICAgICAgIHBvb2xfZXhpc3Qg + PSBUcnVlCgogICAgICAgICAgICBpZiBub3QgbWV0YWRhdGFfcG9vbF9leGlzdDoKICAgICAgICAg + ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAg + ICAgIlByb3ZpZGVkIHJiZF9lY19tZXRhZGF0YV9wb29sIG5hbWUsIgogICAgICAgICAgICAgICAg + ICAgIGYiIHtyYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lfSwgZG9lcyBub3QgZXhpc3QiCiAgICAg + ICAgICAgICAgICApCiAgICAgICAgICAgIGlmIG5vdCBwb29sX2V4aXN0OgogICAgICAgICAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBm + IlByb3ZpZGVkIHJiZF9kYXRhX3Bvb2wgbmFtZSwge3JiZF9wb29sX25hbWV9LCBkb2VzIG5vdCBl + eGlzdCIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgcmV0dXJuIHJiZF9tZXRhZGF0YV9l + Y19wb29sX25hbWUKCiAgICBkZWYgZHJ5X3J1bihzZWxmLCBtc2cpOgogICAgICAgIGlmIHNlbGYu + X2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcHJpbnQoIkV4ZWN1dGU6ICIgKyAiJyIg + KyBtc2cgKyAiJyIpCgogICAgZGVmIHZhbGlkYXRlX3Jnd19lbmRwb2ludF90bHNfY2VydChzZWxm + KToKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2VydF9wYXRoOgogICAgICAg + ICAgICB3aXRoIG9wZW4oc2VsZi5fYXJnX3BhcnNlci5yZ3dfdGxzX2NlcnRfcGF0aCwgZW5jb2Rp + bmc9InV0ZjgiKSBhcyBmOgogICAgICAgICAgICAgICAgY29udGVudHMgPSBmLnJlYWQoKQogICAg + ICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnRzLnJzdHJpcCgpCgogICAgZGVmIF9jaGVja19jb25m + bGljdGluZ19vcHRpb25zKHNlbGYpOgogICAgICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVw + Z3JhZGUgYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZToKICAgICAg + ICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICJF + aXRoZXIgJy0tdXBncmFkZScgb3IgJy0tcmJkLWRhdGEtcG9vbC1uYW1lIDxwb29sX25hbWU+JyBz + aG91bGQgYmUgc3BlY2lmaWVkIgogICAgICAgICAgICApCgogICAgZGVmIF9pbnZhbGlkX2VuZHBv + aW50KHNlbGYsIGVuZHBvaW50X3N0cik6CiAgICAgICAgIyBleHRyYWN0IHRoZSBwb3J0IGJ5IGdl + dHRpbmcgdGhlIGxhc3Qgc3BsaXQgb24gYDpgIGRlbGltaXRlcgogICAgICAgIHRyeToKICAgICAg + ICAgICAgZW5kcG9pbnRfc3RyX2lwLCBwb3J0ID0gZW5kcG9pbnRfc3RyLnJzcGxpdCgiOiIsIDEp + CiAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24oZiJOb3QgYSBwcm9wZXIgZW5kcG9pbnQ6IHtlbmRwb2ludF9zdHJ9IikK + CiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBlbmRwb2ludF9zdHJfaXBbMF0gPT0gIlsiOgog + ICAgICAgICAgICAgICAgZW5kcG9pbnRfc3RyX2lwID0gZW5kcG9pbnRfc3RyX2lwWzEgOiBsZW4o + ZW5kcG9pbnRfc3RyX2lwKSAtIDFdCiAgICAgICAgICAgIGlwX3R5cGUgPSAoCiAgICAgICAgICAg + ICAgICAiSVB2NCIgaWYgdHlwZShpcF9hZGRyZXNzKGVuZHBvaW50X3N0cl9pcCkpIGlzIElQdjRB + ZGRyZXNzIGVsc2UgIklQdjYiCiAgICAgICAgICAgICkKICAgICAgICBleGNlcHQgVmFsdWVFcnJv + cjoKICAgICAgICAgICAgaXBfdHlwZSA9ICJGUUROIgogICAgICAgIGlmIG5vdCBwb3J0LmlzZGln + aXQoKToKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbihmIlBvcnQg + bm90IHZhbGlkOiB7cG9ydH0iKQogICAgICAgIGludFBvcnQgPSBpbnQocG9ydCkKICAgICAgICBp + ZiBpbnRQb3J0IDwgMSBvciBpbnRQb3J0ID4gMioqMTYgLSAxOgogICAgICAgICAgICByYWlzZSBF + eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKGYiT3V0IG9mIHJhbmdlIHBvcnQgbnVtYmVyOiB7cG9y + dH0iKQoKICAgICAgICByZXR1cm4gaXBfdHlwZQoKICAgIGRlZiBlbmRwb2ludF9kaWFsKHNlbGYs + IGVuZHBvaW50X3N0ciwgaXBfdHlwZSwgdGltZW91dD0zLCBjZXJ0PU5vbmUpOgogICAgICAgICMg + aWYgdGhlICdjbHVzdGVyJyBpbnN0YW5jZSBpcyBhIGR1bW15IG9uZSwKICAgICAgICAjIGRvbid0 + IHRyeSB0byByZWFjaCBvdXQgdG8gdGhlIGVuZHBvaW50CiAgICAgICAgaWYgaXNpbnN0YW5jZShz + ZWxmLmNsdXN0ZXIsIER1bW15UmFkb3MpOgogICAgICAgICAgICByZXR1cm4gIiIsICIiLCAiIgog + ICAgICAgIGlmIGlwX3R5cGUgPT0gIklQdjYiOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAg + ICAgICBlbmRwb2ludF9zdHJfaXAsIGVuZHBvaW50X3N0cl9wb3J0ID0gZW5kcG9pbnRfc3RyLnJz + cGxpdCgiOiIsIDEpCiAgICAgICAgICAgIGV4Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBm + Ik5vdCBhIHByb3BlciBlbmRwb2ludDoge2VuZHBvaW50X3N0cn0iCiAgICAgICAgICAgICAgICAp + CiAgICAgICAgICAgIGlmIGVuZHBvaW50X3N0cl9pcFswXSAhPSAiWyI6CiAgICAgICAgICAgICAg + ICBlbmRwb2ludF9zdHJfaXAgPSAiWyIgKyBlbmRwb2ludF9zdHJfaXAgKyAiXSIKICAgICAgICAg + ICAgZW5kcG9pbnRfc3RyID0gIjoiLmpvaW4oW2VuZHBvaW50X3N0cl9pcCwgZW5kcG9pbnRfc3Ry + X3BvcnRdKQoKICAgICAgICBwcm90b2NvbHMgPSBbImh0dHAiLCAiaHR0cHMiXQogICAgICAgIHJl + c3BvbnNlX2Vycm9yID0gTm9uZQogICAgICAgIGZvciBwcmVmaXggaW4gcHJvdG9jb2xzOgogICAg + ICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBlcCA9IGYie3ByZWZpeH06Ly97ZW5kcG9pbnRf + c3RyfSIKICAgICAgICAgICAgICAgIHZlcmlmeSA9IE5vbmUKICAgICAgICAgICAgICAgICMgSWYg + dmVyaWZ5IGlzIHNldCB0byBhIHBhdGggdG8gYSBkaXJlY3RvcnksCiAgICAgICAgICAgICAgICAj + IHRoZSBkaXJlY3RvcnkgbXVzdCBoYXZlIGJlZW4gcHJvY2Vzc2VkIHVzaW5nIHRoZSBjX3JlaGFz + aCB1dGlsaXR5IHN1cHBsaWVkIHdpdGggT3BlblNTTC4KICAgICAgICAgICAgICAgIGlmIHByZWZp + eCA9PSAiaHR0cHMiIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnJnd19za2lwX3RsczoKICAgICAgICAg + ICAgICAgICAgICB2ZXJpZnkgPSBGYWxzZQogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0 + cy5oZWFkKGVwLCB0aW1lb3V0PXRpbWVvdXQsIHZlcmlmeT1GYWxzZSkKICAgICAgICAgICAgICAg + IGVsaWYgcHJlZml4ID09ICJodHRwcyIgYW5kIGNlcnQ6CiAgICAgICAgICAgICAgICAgICAgdmVy + aWZ5ID0gY2VydAogICAgICAgICAgICAgICAgICAgIHIgPSByZXF1ZXN0cy5oZWFkKGVwLCB0aW1l + b3V0PXRpbWVvdXQsIHZlcmlmeT1jZXJ0KQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAg + ICAgICAgICAgICByID0gcmVxdWVzdHMuaGVhZChlcCwgdGltZW91dD10aW1lb3V0KQogICAgICAg + ICAgICAgICAgaWYgci5zdGF0dXNfY29kZSA9PSAyMDA6CiAgICAgICAgICAgICAgICAgICAgcmV0 + dXJuIHByZWZpeCwgdmVyaWZ5LCAiIgogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGVy + cjoKICAgICAgICAgICAgICAgIHJlc3BvbnNlX2Vycm9yID0gZXJyCiAgICAgICAgICAgICAgICBj + b250aW51ZQogICAgICAgIHN5cy5zdGRlcnIud3JpdGUoCiAgICAgICAgICAgIGYidW5hYmxlIHRv + IGNvbm5lY3QgdG8gZW5kcG9pbnQ6IHtlbmRwb2ludF9zdHJ9LCBmYWlsZWQgZXJyb3I6IHtyZXNw + b25zZV9lcnJvcn0iCiAgICAgICAgKQogICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICIiLAog + ICAgICAgICAgICAiIiwKICAgICAgICAgICAgKCItMSIpLAogICAgICAgICkKCiAgICBkZWYgcGFy + c2VfY29uZmlnX2ZpbGUoc2VsZiwgY29uZmlnX2ZpbGUpOgogICAgICAgIGNvbmZpZyA9IGNvbmZp + Z3BhcnNlci5Db25maWdQYXJzZXIoKQogICAgICAgIGNvbmZpZy5yZWFkKGNvbmZpZ19maWxlKQog + ICAgICAgIGZvciBhcmcgaW4gbGlzdCh2YXJzKHNlbGYuX2FyZ19wYXJzZXIpKToKICAgICAgICAg + ICAgIyBweXRob24gdHJlYXRzIGZsYWctbmFtZSBhcyBmbGFnX25hbWUgaW50ZXJuYWxseSwgc28g + Y29udmVydGluZyBiYWNrIHRvIGZsYWctbmFtZSwKICAgICAgICAgICAgIyBzbyB3ZSBjYW4gZ2V0 + IHRob3NlIHZhbHVlcyBmcm9tIGNvbmZpZyBmaWxlCiAgICAgICAgICAgIGFyZ3VtZW50ID0gYXJn + LnJlcGxhY2UoIl8iLCAiLSIpCiAgICAgICAgICAgIGFyZ3VtZW50VmFsdWUgPSBzdHIoZ2V0YXR0 + cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpKQogICAgICAgICAgICBjb25maWdfdmFsdWUgPSBjb25m + aWcuZ2V0KCJDb25maWd1cmF0aW9ucyIsIGFyZ3VtZW50LCBmYWxsYmFjaz1Ob25lKQogICAgICAg + ICAgICAjIGdpdmUgcHJpb3JpdHkgdG8gY29tbWFuZCBsaW5lIGFyZ3VtZW50LCBpZiBjb21tYW5k + IGxpbmUgYXJndW1lbnQgaXMgbm90IHByZXNlbnQgdXNlIGNvbmZpZy5pbmkgdmFsdWUsCiAgICAg + ICAgICAgIGlmIChzdHIoc3lzLmFyZ3YpLmZpbmQoYXJndW1lbnQpID09IC0xKSBhbmQgKAogICAg + ICAgICAgICAgICAgKGNvbmZpZ192YWx1ZSAhPSBOb25lKSBhbmQgKGNvbmZpZ192YWx1ZSAhPSAi + IikKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuX19zZXRh + dHRyX18oYXJnLCBjb25maWdfdmFsdWUpCgogICAgICAgIHJldHVybiBjb25maWcKCiAgICBkZWYg + X19pbml0X18oc2VsZiwgYXJnX2xpc3Q9Tm9uZSk6CiAgICAgICAgc2VsZi5vdXRfbWFwID0ge30K + ICAgICAgICBzZWxmLl9leGNsdWRlZF9rZXlzID0gc2V0KCkKICAgICAgICBzZWxmLl9hcmdfcGFy + c2VyID0gc2VsZi5nZW5fYXJnX3BhcnNlcihhcmdzX3RvX3BhcnNlPWFyZ19saXN0KQogICAgICAg + IGlmIHNlbGYuX2FyZ19wYXJzZXIuY29uZmlnX2ZpbGU6CiAgICAgICAgICAgIHNlbGYuY29uZmln + ID0gc2VsZi5wYXJzZV9jb25maWdfZmlsZShzZWxmLl9hcmdfcGFyc2VyLmNvbmZpZ19maWxlKQog + ICAgICAgIHNlbGYuX2NoZWNrX2NvbmZsaWN0aW5nX29wdGlvbnMoKQogICAgICAgIHNlbGYucnVu + X2FzX3VzZXIgPSBzZWxmLl9hcmdfcGFyc2VyLnJ1bl9hc191c2VyCiAgICAgICAgc2VsZi5vdXRw + dXRfZmlsZSA9IHNlbGYuX2FyZ19wYXJzZXIub3V0cHV0CiAgICAgICAgc2VsZi5jZXBoX2NvbmYg + PSBzZWxmLl9hcmdfcGFyc2VyLmNlcGhfY29uZgogICAgICAgIHNlbGYuY2VwaF9rZXlyaW5nID0g + c2VsZi5fYXJnX3BhcnNlci5rZXlyaW5nCiAgICAgICAgIyBpZiB1c2VyIG5vdCBwcm92aWRlZCwg + Z2l2ZSBhIGRlZmF1bHQgdXNlcgogICAgICAgIGlmIG5vdCBzZWxmLnJ1bl9hc191c2VyIGFuZCBu + b3Qgc2VsZi5fYXJnX3BhcnNlci51cGdyYWRlOgogICAgICAgICAgICBzZWxmLnJ1bl9hc191c2Vy + ID0gc2VsZi5FWFRFUk5BTF9VU0VSX05BTUUKICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNl + ci5yZ3dfcG9vbF9wcmVmaXggYW5kIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnVwZ3JhZGU6CiAgICAg + ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4ID0gc2VsZi5ERUZBVUxUX1JH + V19QT09MX1BSRUZJWAogICAgICAgIGlmIHNlbGYuY2VwaF9jb25mOgogICAgICAgICAgICBrd2Fy + Z3MgPSB7fQogICAgICAgICAgICBpZiBzZWxmLmNlcGhfa2V5cmluZzoKICAgICAgICAgICAgICAg + IGt3YXJnc1siY29uZiJdID0geyJrZXlyaW5nIjogc2VsZi5jZXBoX2tleXJpbmd9CiAgICAgICAg + ICAgIHNlbGYuY2x1c3RlciA9IHJhZG9zLlJhZG9zKGNvbmZmaWxlPXNlbGYuY2VwaF9jb25mLCAq + Kmt3YXJncykKICAgICAgICBlbHNlOgogICAgICAgICAgICBzZWxmLmNsdXN0ZXIgPSByYWRvcy5S + YWRvcygpCiAgICAgICAgICAgIHNlbGYuY2x1c3Rlci5jb25mX3JlYWRfZmlsZSgpCiAgICAgICAg + c2VsZi5jbHVzdGVyLmNvbm5lY3QoKQoKICAgIGRlZiBzaHV0ZG93bihzZWxmKToKICAgICAgICBp + ZiBzZWxmLmNsdXN0ZXIuc3RhdGUgPT0gImNvbm5lY3RlZCI6CiAgICAgICAgICAgIHNlbGYuY2x1 + c3Rlci5zaHV0ZG93bigpCgogICAgZGVmIGdldF9mc2lkKHNlbGYpOgogICAgICAgIGlmIHNlbGYu + X2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigiY2Vw + aCBmc2lkIikKICAgICAgICByZXR1cm4gc3RyKHNlbGYuY2x1c3Rlci5nZXRfZnNpZCgpKQoKICAg + IGRlZiBfY29tbW9uX2NtZF9qc29uX2dlbihzZWxmLCBjbWRfanNvbik6CiAgICAgICAgY21kID0g + anNvbi5kdW1wcyhjbWRfanNvbiwgc29ydF9rZXlzPVRydWUpCiAgICAgICAgcmV0X3ZhbCwgY21k + X291dCwgZXJyX21zZyA9IHNlbGYuY2x1c3Rlci5tb25fY29tbWFuZChjbWQsIGIiIikKICAgICAg + ICBpZiBzZWxmLl9hcmdfcGFyc2VyLnZlcmJvc2U6CiAgICAgICAgICAgIHByaW50KGYiQ29tbWFu + ZCBJbnB1dDoge2NtZH0iKQogICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgIGYiUmV0 + dXJuIFZhbDoge3JldF92YWx9XG5Db21tYW5kIE91dHB1dDoge2NtZF9vdXR9XG4iCiAgICAgICAg + ICAgICAgICBmIkVycm9yIE1lc3NhZ2U6IHtlcnJfbXNnfVxuLS0tLS0tLS0tLVxuIgogICAgICAg + ICAgICApCiAgICAgICAganNvbl9vdXQgPSB7fQogICAgICAgICMgaWYgdGhlcmUgaXMgbm8gZXJy + b3IgKGkuZTsgcmV0X3ZhbCBpcyBaRVJPKSBhbmQgJ2NtZF9vdXQnIGlzIG5vdCBlbXB0eQogICAg + ICAgICMgdGhlbiBjb252ZXJ0ICdjbWRfb3V0JyB0byBhIGpzb24gb3V0cHV0CiAgICAgICAgaWYg + cmV0X3ZhbCA9PSAwIGFuZCBjbWRfb3V0OgogICAgICAgICAgICBqc29uX291dCA9IGpzb24ubG9h + ZHMoY21kX291dCkKICAgICAgICByZXR1cm4gcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cKCiAg + ICBkZWYgZ2V0X2NlcGhfZXh0ZXJuYWxfbW9uX2RhdGEoc2VsZik6CiAgICAgICAgY21kX2pzb24g + PSB7InByZWZpeCI6ICJxdW9ydW1fc3RhdHVzIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICBp + ZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiBzZWxmLmRyeV9y + dW4oImNlcGggIiArIGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRfdmFsLCBqc29uX291 + dCwgZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAg + IyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwKICAgICAgICBpZiByZXRfdmFs + ICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25G + YWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgIidxdW9ydW1fc3RhdHVzJyBjb21tYW5k + IGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgIGYiRXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwg + IT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJU1R9IgogICAgICAgICAgICApCiAgICAgICAg + cV9sZWFkZXJfbmFtZSA9IGpzb25fb3V0WyJxdW9ydW1fbGVhZGVyX25hbWUiXQogICAgICAgIHFf + bGVhZGVyX2RldGFpbHMgPSB7fQogICAgICAgIHFfbGVhZGVyX21hdGNoaW5nX2xpc3QgPSBbCiAg + ICAgICAgICAgIGwgZm9yIGwgaW4ganNvbl9vdXRbIm1vbm1hcCJdWyJtb25zIl0gaWYgbFsibmFt + ZSJdID09IHFfbGVhZGVyX25hbWUKICAgICAgICBdCiAgICAgICAgaWYgbGVuKHFfbGVhZGVyX21h + dGNoaW5nX2xpc3QpID09IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl + cHRpb24oIk5vIG1hdGNoaW5nICdtb24nIGRldGFpbHMgZm91bmQiKQogICAgICAgIHFfbGVhZGVy + X2RldGFpbHMgPSBxX2xlYWRlcl9tYXRjaGluZ19saXN0WzBdCiAgICAgICAgIyBnZXQgdGhlIGFk + ZHJlc3MgdmVjdG9yIG9mIHRoZSBxdW9ydW0tbGVhZGVyCiAgICAgICAgcV9sZWFkZXJfYWRkcnZl + YyA9IHFfbGVhZGVyX2RldGFpbHMuZ2V0KCJwdWJsaWNfYWRkcnMiLCB7fSkuZ2V0KCJhZGRydmVj + IiwgW10pCiAgICAgICAgaXBfYWRkciA9IHN0cihxX2xlYWRlcl9kZXRhaWxzWyJwdWJsaWNfYWRk + ciJdLnNwbGl0KCIvIilbMF0pCgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudjJfcG9ydF9l + bmFibGU6CiAgICAgICAgICAgIGlmIHFfbGVhZGVyX2FkZHJ2ZWNbMF1bInR5cGUiXSA9PSAidjIi + OgogICAgICAgICAgICAgICAgaXBfYWRkciA9IHFfbGVhZGVyX2FkZHJ2ZWNbMF1bImFkZHIiXQog + ICAgICAgICAgICBlbGlmIGxlbihxX2xlYWRlcl9hZGRydmVjKSA+IDEgYW5kIHFfbGVhZGVyX2Fk + ZHJ2ZWNbMV1bInR5cGUiXSA9PSAidjIiOgogICAgICAgICAgICAgICAgaXBfYWRkciA9IHFfbGVh + ZGVyX2FkZHJ2ZWNbMV1bImFkZHIiXQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAg + c3lzLnN0ZGVyci53cml0ZSgKICAgICAgICAgICAgICAgICAgICAiJ3YyJyBhZGRyZXNzIHR5cGUg + bm90IHByZXNlbnQsIGFuZCAndjItcG9ydC1lbmFibGUnIGZsYWcgaXMgcHJvdmlkZWQiCiAgICAg + ICAgICAgICAgICApCgogICAgICAgIHJldHVybiBmIntzdHIocV9sZWFkZXJfbmFtZSl9PXtpcF9h + ZGRyfSIKCiAgICBkZWYgX2NvbnZlcnRfaG9zdG5hbWVfdG9faXAoc2VsZiwgaG9zdF9uYW1lLCBw + b3J0LCBpcF90eXBlKToKICAgICAgICAjIGlmICdjbHVzdGVyJyBpbnN0YW5jZSBpcyBhIGR1bW15 + IHR5cGUsCiAgICAgICAgIyBjYWxsIHRoZSBkdW1teSBpbnN0YW5jZSdzICJjb252ZXJ0IiBtZXRo + b2QKICAgICAgICBpZiBub3QgaG9zdF9uYW1lOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25G + YWlsdXJlRXhjZXB0aW9uKCJFbXB0eSBob3N0bmFtZSBwcm92aWRlZCIpCiAgICAgICAgaWYgaXNp + bnN0YW5jZShzZWxmLmNsdXN0ZXIsIER1bW15UmFkb3MpOgogICAgICAgICAgICByZXR1cm4gc2Vs + Zi5jbHVzdGVyLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKGhvc3RfbmFtZSkKCiAgICAgICAgaWYg + aXBfdHlwZSA9PSAiRlFETiI6CiAgICAgICAgICAgICMgY2hlY2sgd2hpY2ggaXAgRlFETiBzaG91 + bGQgYmUgY29udmVydGVkIHRvLCBJUHY0IG9yIElQdjYKICAgICAgICAgICAgIyBjaGVjayB0aGUg + aG9zdCBpcCwgdGhlIGVuZHBvaW50IGlwIHR5cGUgd291bGQgYmUgc2ltaWxhciB0byBob3N0IGlw + CiAgICAgICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAib3JjaCBob3N0IGxzIiwgImZvcm1h + dCI6ICJqc29uIn0KICAgICAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxm + Ll9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgICAgICAjIGlmIHRoZXJlIGlz + IGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgICAgICBpZiByZXRfdmFsICE9IDAgb3Ig + bGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVy + ZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiJ29yY2ggaG9zdCBscycgY29tbWFuZCBm + YWlsZWQuXG4iCiAgICAgICAgICAgICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3Zh + bCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICAgICApCiAg + ICAgICAgICAgIGhvc3RfYWRkciA9IGpzb25fb3V0WzBdWyJhZGRyIl0KICAgICAgICAgICAgIyBh + ZGQgOjgwIHNhbXBsZSBwb3J0IGluIGlwX3R5cGUsIGFzIF9pbnZhbGlkX2VuZHBvaW50IGFsc28g + dmVyaWZ5IHBvcnQKICAgICAgICAgICAgaG9zdF9pcF90eXBlID0gc2VsZi5faW52YWxpZF9lbmRw + b2ludChob3N0X2FkZHIgKyAiOjgwIikKICAgICAgICAgICAgaW1wb3J0IHNvY2tldAoKICAgICAg + ICAgICAgaXAgPSBbXQogICAgICAgICAgICAjIGV4YW1wbGUgb3V0cHV0IFsoPEFkZHJlc3NGYW1p + bHkuQUZfSU5FVDogMj4sIDxTb2NrZXRLaW5kLlNPQ0tfU1RSRUFNOiAxPiwgNiwgJycsICgnOTMu + MTg0LjIxNi4zNCcsIDgwKSksIC4uLl0KICAgICAgICAgICAgIyB3ZSBuZWVkIHRvIGdldCA5My4x + ODQuMjE2LjM0IHNvIGl0IHdvdWxkIGJlIGlwWzBdWzRdWzBdCiAgICAgICAgICAgIGlmIGhvc3Rf + aXBfdHlwZSA9PSAiSVB2NiI6CiAgICAgICAgICAgICAgICBpcCA9IHNvY2tldC5nZXRhZGRyaW5m + bygKICAgICAgICAgICAgICAgICAgICBob3N0X25hbWUsIHBvcnQsIGZhbWlseT1zb2NrZXQuQUZf + SU5FVDYsIHByb3RvPXNvY2tldC5JUFBST1RPX1RDUAogICAgICAgICAgICAgICAgKQogICAgICAg + ICAgICBlbGlmIGhvc3RfaXBfdHlwZSA9PSAiSVB2NCI6CiAgICAgICAgICAgICAgICBpcCA9IHNv + Y2tldC5nZXRhZGRyaW5mbygKICAgICAgICAgICAgICAgICAgICBob3N0X25hbWUsIHBvcnQsIGZh + bWlseT1zb2NrZXQuQUZfSU5FVCwgcHJvdG89c29ja2V0LklQUFJPVE9fVENQCiAgICAgICAgICAg + ICAgICApCiAgICAgICAgICAgIGRlbCBzb2NrZXQKICAgICAgICAgICAgcmV0dXJuIGlwWzBdWzRd + WzBdCiAgICAgICAgcmV0dXJuIGhvc3RfbmFtZQoKICAgIGRlZiBnZXRfYWN0aXZlX2FuZF9zdGFu + ZGJ5X21ncnMoc2VsZik6CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAg + ICAgICAgICByZXR1cm4gIiIsIHNlbGYuZHJ5X3J1bigiY2VwaCBzdGF0dXMiKQogICAgICAgIG1v + bml0b3JpbmdfZW5kcG9pbnRfcG9ydCA9IHNlbGYuX2FyZ19wYXJzZXIubW9uaXRvcmluZ19lbmRw + b2ludF9wb3J0CiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0ID0gc2VsZi5fYXJn + X3BhcnNlci5tb25pdG9yaW5nX2VuZHBvaW50CiAgICAgICAgc3RhbmRieV9tZ3JzID0gW10KICAg + ICAgICBpZiBub3QgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0OgogICAgICAgICAgICBjbWRf + anNvbiA9IHsicHJlZml4IjogInN0YXR1cyIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgICAg + IHJldF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihj + bWRfanNvbikKICAgICAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1w + dCwKICAgICAgICAgICAgaWYgcmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAg + ICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAg + ICAgICAgICAgIidtZ3Igc2VydmljZXMnIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAgICAgICAg + ICAgICAgIGYiRXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlf + T1VUUFVUX0xJU1R9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBtb25pdG9yaW5nX2Vu + ZHBvaW50ID0gKAogICAgICAgICAgICAgICAganNvbl9vdXQuZ2V0KCJtZ3JtYXAiLCB7fSkuZ2V0 + KCJzZXJ2aWNlcyIsIHt9KS5nZXQoInByb21ldGhldXMiLCAiIikKICAgICAgICAgICAgKQogICAg + ICAgICAgICBpZiBub3QgbW9uaXRvcmluZ19lbmRwb2ludDoKICAgICAgICAgICAgICAgIHJhaXNl + IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgImNhbid0IGZp + bmQgbW9uaXRvcmluZ19lbmRwb2ludCwgcHJvbWV0aGV1cyBtb2R1bGUgbWlnaHQgbm90IGJlIGVu + YWJsZWQsICIKICAgICAgICAgICAgICAgICAgICAiZW5hYmxlIHRoZSBtb2R1bGUgYnkgcnVubmlu + ZyAnY2VwaCBtZ3IgbW9kdWxlIGVuYWJsZSBwcm9tZXRoZXVzJyIKICAgICAgICAgICAgICAgICkK + ICAgICAgICAgICAgIyBub3cgY2hlY2sgdGhlIHN0YW5kLWJ5IG1nci1zCiAgICAgICAgICAgIHN0 + YW5kYnlfYXJyID0ganNvbl9vdXQuZ2V0KCJtZ3JtYXAiLCB7fSkuZ2V0KCJzdGFuZGJ5cyIsIFtd + KQogICAgICAgICAgICBmb3IgZWFjaF9zdGFuZGJ5IGluIHN0YW5kYnlfYXJyOgogICAgICAgICAg + ICAgICAgaWYgIm5hbWUiIGluIGVhY2hfc3RhbmRieS5rZXlzKCk6CiAgICAgICAgICAgICAgICAg + ICAgc3RhbmRieV9tZ3JzLmFwcGVuZChlYWNoX3N0YW5kYnlbIm5hbWUiXSkKICAgICAgICAgICAg + dHJ5OgogICAgICAgICAgICAgICAgcGFyc2VkX2VuZHBvaW50ID0gdXJscGFyc2UobW9uaXRvcmlu + Z19lbmRwb2ludCkKICAgICAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgICAg + ICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgIGYi + aW52YWxpZCBlbmRwb2ludDoge21vbml0b3JpbmdfZW5kcG9pbnR9IgogICAgICAgICAgICAgICAg + KQogICAgICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3QgPSBwYXJzZWRfZW5kcG9p + bnQuaG9zdG5hbWUKICAgICAgICAgICAgaWYgbm90IG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydDoK + ICAgICAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydCA9IHN0cihwYXJzZWRfZW5k + cG9pbnQucG9ydCkKCiAgICAgICAgIyBpZiBtb25pdG9yaW5nIGVuZHBvaW50IHBvcnQgaXMgbm90 + IHNldCwgcHV0IGEgZGVmYXVsdCBtb24gcG9ydAogICAgICAgIGlmIG5vdCBtb25pdG9yaW5nX2Vu + ZHBvaW50X3BvcnQ6CiAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydCA9IHNlbGYu + REVGQVVMVF9NT05JVE9SSU5HX0VORFBPSU5UX1BPUlQKCiAgICAgICAgIyB1c2VyIGNvdWxkIGdp + dmUgY29tbWEgYW5kIHNwYWNlIHNlcGFyYXRlZCBpbnB1dHMgKGxpa2UgLS1tb25pdG9yaW5nLWVu + ZHBvaW50PSI8aXAxPiwgPGlwMj4iKQogICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlz + dCA9IG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdC5yZXBsYWNlKCIsIiwgIiAiKQogICAgICAg + IG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdF9zcGxpdCA9IG1vbml0b3JpbmdfZW5kcG9pbnRf + aXBfbGlzdC5zcGxpdCgpCiAgICAgICAgIyBpZiBtb25pdG9yaW5nLWVuZHBvaW50IGNvdWxkIG5v + dCBiZSBmb3VuZCwgcmFpc2UgYW4gZXJyb3IKICAgICAgICBpZiBsZW4obW9uaXRvcmluZ19lbmRw + b2ludF9pcF9saXN0X3NwbGl0KSA9PSAwOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls + dXJlRXhjZXB0aW9uKCJObyAnbW9uaXRvcmluZy1lbmRwb2ludCcgZm91bmQiKQogICAgICAgICMg + Zmlyc3QgaXAgaXMgdHJlYXRlZCBhcyB0aGUgbWFpbiBtb25pdG9yaW5nLWVuZHBvaW50CiAgICAg + ICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcCA9IG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdF9z + cGxpdFswXQogICAgICAgICMgcmVzdCBvZiB0aGUgaXAtcyBhcmUgYWRkZWQgdG8gdGhlICdzdGFu + ZGJ5X21ncnMnIGxpc3QKICAgICAgICBzdGFuZGJ5X21ncnMuZXh0ZW5kKG1vbml0b3JpbmdfZW5k + cG9pbnRfaXBfbGlzdF9zcGxpdFsxOl0pCiAgICAgICAgZmFpbGVkX2lwID0gbW9uaXRvcmluZ19l + bmRwb2ludF9pcAoKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50ID0gIjoiLmpvaW4oCiAgICAg + ICAgICAgIFttb25pdG9yaW5nX2VuZHBvaW50X2lwLCBtb25pdG9yaW5nX2VuZHBvaW50X3BvcnRd + CiAgICAgICAgKQogICAgICAgIGlwX3R5cGUgPSBzZWxmLl9pbnZhbGlkX2VuZHBvaW50KG1vbml0 + b3JpbmdfZW5kcG9pbnQpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBtb25pdG9yaW5nX2VuZHBv + aW50X2lwID0gc2VsZi5fY29udmVydF9ob3N0bmFtZV90b19pcCgKICAgICAgICAgICAgICAgIG1v + bml0b3JpbmdfZW5kcG9pbnRfaXAsIG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydCwgaXBfdHlwZQog + ICAgICAgICAgICApCiAgICAgICAgICAgICMgY29sbGVjdCBhbGwgdGhlICdzdGFuZC1ieScgbWdy + IGlwcwogICAgICAgICAgICBtZ3JfaXBzID0gW10KICAgICAgICAgICAgZm9yIGVhY2hfc3RhbmRi + eV9tZ3IgaW4gc3RhbmRieV9tZ3JzOgogICAgICAgICAgICAgICAgZmFpbGVkX2lwID0gZWFjaF9z + dGFuZGJ5X21ncgogICAgICAgICAgICAgICAgbWdyX2lwcy5hcHBlbmQoCiAgICAgICAgICAgICAg + ICAgICAgc2VsZi5fY29udmVydF9ob3N0bmFtZV90b19pcCgKICAgICAgICAgICAgICAgICAgICAg + ICAgZWFjaF9zdGFuZGJ5X21nciwgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0LCBpcF90eXBlCiAg + ICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKQogICAgICAgIGV4Y2VwdDoKICAg ICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAg - ICAgICAiY2FuJ3QgZmluZCBtb25pdG9yaW5nX2VuZHBvaW50LCBwcm9tZXRoZXVzIG1vZHVsZSBt - aWdodCBub3QgYmUgZW5hYmxlZCwgIgogICAgICAgICAgICAgICAgICAgICJlbmFibGUgdGhlIG1v - ZHVsZSBieSBydW5uaW5nICdjZXBoIG1nciBtb2R1bGUgZW5hYmxlIHByb21ldGhldXMnIgogICAg - ICAgICAgICAgICAgKQogICAgICAgICAgICAjIG5vdyBjaGVjayB0aGUgc3RhbmQtYnkgbWdyLXMK - ICAgICAgICAgICAgc3RhbmRieV9hcnIgPSBqc29uX291dC5nZXQoIm1ncm1hcCIsIHt9KS5nZXQo - InN0YW5kYnlzIiwgW10pCiAgICAgICAgICAgIGZvciBlYWNoX3N0YW5kYnkgaW4gc3RhbmRieV9h - cnI6CiAgICAgICAgICAgICAgICBpZiAibmFtZSIgaW4gZWFjaF9zdGFuZGJ5LmtleXMoKToKICAg - ICAgICAgICAgICAgICAgICBzdGFuZGJ5X21ncnMuYXBwZW5kKGVhY2hfc3RhbmRieVsibmFtZSJd - KQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBwYXJzZWRfZW5kcG9pbnQgPSB1cmxw - YXJzZShtb25pdG9yaW5nX2VuZHBvaW50KQogICAgICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoK - ICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAg - ICAgICAgICAgICAgZiJpbnZhbGlkIGVuZHBvaW50OiB7bW9uaXRvcmluZ19lbmRwb2ludH0iCiAg - ICAgICAgICAgICAgICApCiAgICAgICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnRfaXBfbGlzdCA9 - IHBhcnNlZF9lbmRwb2ludC5ob3N0bmFtZQogICAgICAgICAgICBpZiBub3QgbW9uaXRvcmluZ19l - bmRwb2ludF9wb3J0OgogICAgICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9wb3J0ID0g - c3RyKHBhcnNlZF9lbmRwb2ludC5wb3J0KQoKICAgICAgICAjIGlmIG1vbml0b3JpbmcgZW5kcG9p - bnQgcG9ydCBpcyBub3Qgc2V0LCBwdXQgYSBkZWZhdWx0IG1vbiBwb3J0CiAgICAgICAgaWYgbm90 - IG1vbml0b3JpbmdfZW5kcG9pbnRfcG9ydDoKICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2lu - dF9wb3J0ID0gc2VsZi5ERUZBVUxUX01PTklUT1JJTkdfRU5EUE9JTlRfUE9SVAoKICAgICAgICAj - IHVzZXIgY291bGQgZ2l2ZSBjb21tYSBhbmQgc3BhY2Ugc2VwYXJhdGVkIGlucHV0cyAobGlrZSAt - LW1vbml0b3JpbmctZW5kcG9pbnQ9IjxpcDE+LCA8aXAyPiIpCiAgICAgICAgbW9uaXRvcmluZ19l - bmRwb2ludF9pcF9saXN0ID0gbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0LnJlcGxhY2UoIiwi - LCAiICIpCiAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0X3NwbGl0ID0gbW9uaXRv - cmluZ19lbmRwb2ludF9pcF9saXN0LnNwbGl0KCkKICAgICAgICAjIGlmIG1vbml0b3JpbmctZW5k - cG9pbnQgY291bGQgbm90IGJlIGZvdW5kLCByYWlzZSBhbiBlcnJvcgogICAgICAgIGlmIGxlbiht - b25pdG9yaW5nX2VuZHBvaW50X2lwX2xpc3Rfc3BsaXQpID09IDA6CiAgICAgICAgICAgIHJhaXNl - IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oIk5vICdtb25pdG9yaW5nLWVuZHBvaW50JyBmb3Vu - ZCIpCiAgICAgICAgIyBmaXJzdCBpcCBpcyB0cmVhdGVkIGFzIHRoZSBtYWluIG1vbml0b3Jpbmct - ZW5kcG9pbnQKICAgICAgICBtb25pdG9yaW5nX2VuZHBvaW50X2lwID0gbW9uaXRvcmluZ19lbmRw - b2ludF9pcF9saXN0X3NwbGl0WzBdCiAgICAgICAgIyByZXN0IG9mIHRoZSBpcC1zIGFyZSBhZGRl - ZCB0byB0aGUgJ3N0YW5kYnlfbWdycycgbGlzdAogICAgICAgIHN0YW5kYnlfbWdycy5leHRlbmQo - bW9uaXRvcmluZ19lbmRwb2ludF9pcF9saXN0X3NwbGl0WzE6XSkKICAgICAgICBmYWlsZWRfaXAg - PSBtb25pdG9yaW5nX2VuZHBvaW50X2lwCgogICAgICAgIG1vbml0b3JpbmdfZW5kcG9pbnQgPSAi - OiIuam9pbigKICAgICAgICAgICAgW21vbml0b3JpbmdfZW5kcG9pbnRfaXAsIG1vbml0b3Jpbmdf - ZW5kcG9pbnRfcG9ydF0KICAgICAgICApCiAgICAgICAgaXBfdHlwZSA9IHNlbGYuX2ludmFsaWRf - ZW5kcG9pbnQobW9uaXRvcmluZ19lbmRwb2ludCkKICAgICAgICB0cnk6CiAgICAgICAgICAgIG1v - bml0b3JpbmdfZW5kcG9pbnRfaXAgPSBzZWxmLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKAogICAg - ICAgICAgICAgICAgbW9uaXRvcmluZ19lbmRwb2ludF9pcCwgbW9uaXRvcmluZ19lbmRwb2ludF9w - b3J0LCBpcF90eXBlCiAgICAgICAgICAgICkKICAgICAgICAgICAgIyBjb2xsZWN0IGFsbCB0aGUg - J3N0YW5kLWJ5JyBtZ3IgaXBzCiAgICAgICAgICAgIG1ncl9pcHMgPSBbXQogICAgICAgICAgICBm - b3IgZWFjaF9zdGFuZGJ5X21nciBpbiBzdGFuZGJ5X21ncnM6CiAgICAgICAgICAgICAgICBmYWls - ZWRfaXAgPSBlYWNoX3N0YW5kYnlfbWdyCiAgICAgICAgICAgICAgICBtZ3JfaXBzLmFwcGVuZCgK - ICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb252ZXJ0X2hvc3RuYW1lX3RvX2lwKAogICAgICAg - ICAgICAgICAgICAgICAgICBlYWNoX3N0YW5kYnlfbWdyLCBtb25pdG9yaW5nX2VuZHBvaW50X3Bv - cnQsIGlwX3R5cGUKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApCiAgICAg - ICAgZXhjZXB0OgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAog - ICAgICAgICAgICAgICAgZiJDb252ZXJzaW9uIG9mIGhvc3Q6IHtmYWlsZWRfaXB9IHRvIElQIGZh - aWxlZC4gIgogICAgICAgICAgICAgICAgIlBsZWFzZSBlbnRlciB0aGUgSVAgYWRkcmVzc2VzIG9m - IGFsbCB0aGUgY2VwaC1tZ3JzIHdpdGggdGhlICctLW1vbml0b3JpbmctZW5kcG9pbnQnIGZsYWci - CiAgICAgICAgICAgICkKCiAgICAgICAgXywgXywgZXJyID0gc2VsZi5lbmRwb2ludF9kaWFsKG1v - bml0b3JpbmdfZW5kcG9pbnQsIGlwX3R5cGUpCiAgICAgICAgaWYgZXJyID09ICItMSI6CiAgICAg - ICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oZXJyKQogICAgICAgICMgYWRk - IHRoZSB2YWxpZGF0ZWQgYWN0aXZlIG1nciBJUCBpbnRvIHRoZSBmaXJzdCBpbmRleAogICAgICAg - IG1ncl9pcHMuaW5zZXJ0KDAsIG1vbml0b3JpbmdfZW5kcG9pbnRfaXApCiAgICAgICAgYWxsX21n - cl9pcHNfc3RyID0gIiwiLmpvaW4obWdyX2lwcykKICAgICAgICByZXR1cm4gYWxsX21ncl9pcHNf - c3RyLCBtb25pdG9yaW5nX2VuZHBvaW50X3BvcnQKCiAgICBkZWYgY2hlY2tfdXNlcl9leGlzdChz - ZWxmLCB1c2VyKToKICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogImF1dGggZ2V0IiwgImVu - dGl0eSI6IGYie3VzZXJ9IiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICByZXRfdmFsLCBqc29u - X291dCwgXyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgaWYg - cmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAgICAgICAgICAgcmV0dXJuICIi - CiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0pCgogICAgZGVmIGdldF9jZXBo - ZnNfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KHNlbGYpOgogICAgICAgIGVudGl0eSA9ICJj - bGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIKICAgICAgICBjYXBzID0gewogICAgICAgICAg + IGYiQ29udmVyc2lvbiBvZiBob3N0OiB7ZmFpbGVkX2lwfSB0byBJUCBmYWlsZWQuICIKICAgICAg + ICAgICAgICAgICJQbGVhc2UgZW50ZXIgdGhlIElQIGFkZHJlc3NlcyBvZiBhbGwgdGhlIGNlcGgt + bWdycyB3aXRoIHRoZSAnLS1tb25pdG9yaW5nLWVuZHBvaW50JyBmbGFnIgogICAgICAgICAgICAp + CgogICAgICAgIF8sIF8sIGVyciA9IHNlbGYuZW5kcG9pbnRfZGlhbChtb25pdG9yaW5nX2VuZHBv + aW50LCBpcF90eXBlKQogICAgICAgIGlmIGVyciA9PSAiLTEiOgogICAgICAgICAgICByYWlzZSBF + eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKGVycikKICAgICAgICAjIGFkZCB0aGUgdmFsaWRhdGVk + IGFjdGl2ZSBtZ3IgSVAgaW50byB0aGUgZmlyc3QgaW5kZXgKICAgICAgICBtZ3JfaXBzLmluc2Vy + dCgwLCBtb25pdG9yaW5nX2VuZHBvaW50X2lwKQogICAgICAgIGFsbF9tZ3JfaXBzX3N0ciA9ICIs + Ii5qb2luKG1ncl9pcHMpCiAgICAgICAgcmV0dXJuIGFsbF9tZ3JfaXBzX3N0ciwgbW9uaXRvcmlu + Z19lbmRwb2ludF9wb3J0CgogICAgZGVmIGNoZWNrX3VzZXJfZXhpc3Qoc2VsZiwgdXNlcik6CiAg + ICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJhdXRoIGdldCIsICJlbnRpdHkiOiBmInt1c2Vy + fSIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIF8gPSBzZWxm + Ll9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAgIGlmIHJldF92YWwgIT0gMCBv + ciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJldHVybiAiIgogICAgICAgIHJldHVy + biBzdHIoanNvbl9vdXRbMF1bImtleSJdKQoKICAgIGRlZiBnZXRfY2VwaGZzX3Byb3Zpc2lvbmVy + X2NhcHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSAiY2xpZW50LmNzaS1jZXBo + ZnMtcHJvdmlzaW9uZXIiCiAgICAgICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJhbGxv + dyByLCBhbGxvdyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJtZ3IiOiAi + YWxsb3cgcnciLAogICAgICAgICAgICAib3NkIjogImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRh + dGE9KiIsCiAgICAgICAgICAgICJtZHMiOiAiYWxsb3cgKiIsCiAgICAgICAgfQogICAgICAgIGlm + IHNlbGYuX2FyZ19wYXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb246CiAgICAgICAgICAg + IGs4c19jbHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAg + ICAgICAgICAgaWYgazhzX2NsdXN0ZXJfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNl + IEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIms4c19jbHVz + dGVyX25hbWUgbm90IGZvdW5kLCBwbGVhc2Ugc2V0IHRoZSAnLS1rOHMtY2x1c3Rlci1uYW1lJyBm + bGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBjZXBoZnNfZmlsZXN5c3RlbSA9IHNl + bGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgICAgICBpZiBjZXBo + ZnNfZmlsZXN5c3RlbSA9PSAiIjoKICAgICAgICAgICAgICAgIGVudGl0eSA9IGYie2VudGl0eX0t + e2s4c19jbHVzdGVyX25hbWV9IgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZW50 + aXR5ID0gZiJ7ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFtZX0te2NlcGhmc19maWxlc3lzdGVtfSIK + ICAgICAgICAgICAgICAgIGNhcHNbIm9zZCJdID0gZiJhbGxvdyBydyB0YWcgY2VwaGZzIG1ldGFk + YXRhPXtjZXBoZnNfZmlsZXN5c3RlbX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAg + ICBkZWYgZ2V0X2NlcGhmc19ub2RlX2NhcHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRp + dHkgPSAiY2xpZW50LmNzaS1jZXBoZnMtbm9kZSIKICAgICAgICBjYXBzID0gewogICAgICAgICAg ICAibW9uIjogImFsbG93IHIsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3QnIiwKICAgICAg ICAgICAgIm1nciI6ICJhbGxvdyBydyIsCiAgICAgICAgICAgICJvc2QiOiAiYWxsb3cgcncgdGFn - IGNlcGhmcyBtZXRhZGF0YT0qIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl - ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgazhzX2NsdXN0ZXJfbmFt - ZSA9IHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZQogICAgICAgICAgICBpZiBrOHNf - Y2x1c3Rlcl9uYW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVy - ZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAiazhzX2NsdXN0ZXJfbmFtZSBub3QgZm91 - bmQsIHBsZWFzZSBzZXQgdGhlICctLWs4cy1jbHVzdGVyLW5hbWUnIGZsYWciCiAgICAgICAgICAg - ICAgICApCiAgICAgICAgICAgIGNlcGhmc19maWxlc3lzdGVtID0gc2VsZi5fYXJnX3BhcnNlci5j - ZXBoZnNfZmlsZXN5c3RlbV9uYW1lCiAgICAgICAgICAgIGlmIGNlcGhmc19maWxlc3lzdGVtID09 - ICIiOgogICAgICAgICAgICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFt - ZX0iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9 - LXtrOHNfY2x1c3Rlcl9uYW1lfS17Y2VwaGZzX2ZpbGVzeXN0ZW19IgogICAgICAgICAgICAgICAg - Y2Fwc1sib3NkIl0gPSBmImFsbG93IHJ3IHRhZyBjZXBoZnMgbWV0YWRhdGE9e2NlcGhmc19maWxl - c3lzdGVtfSIKCiAgICAgICAgcmV0dXJuIGNhcHMsIGVudGl0eQoKICAgIGRlZiBnZXRfY2VwaGZz - X25vZGVfY2Fwc19hbmRfZW50aXR5KHNlbGYpOgogICAgICAgIGVudGl0eSA9ICJjbGllbnQuY3Np - LWNlcGhmcy1ub2RlIgogICAgICAgIGNhcHMgPSB7CiAgICAgICAgICAgICJtb24iOiAiYWxsb3cg - ciwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLAogICAgICAgICAgICAibWdyIjogImFs - bG93IHJ3IiwKICAgICAgICAgICAgIm9zZCI6ICJhbGxvdyBydyB0YWcgY2VwaGZzICo9KiIsCiAg - ICAgICAgICAgICJtZHMiOiAiYWxsb3cgcnciLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9h - cmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uOgogICAgICAgICAgICBrOHNfY2x1 - c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lCiAgICAgICAgICAg - IGlmIGs4c19jbHVzdGVyX25hbWUgPT0gIiI6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRp - b25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICJrOHNfY2x1c3Rlcl9uYW1l - IG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAg - ICAgICAgICAgICAgICkKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW0gPSBzZWxmLl9hcmdf - cGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICAgICAgaWYgY2VwaGZzX2ZpbGVz - eXN0ZW0gPT0gIiI6CiAgICAgICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1 - c3Rlcl9uYW1lfSIKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGVudGl0eSA9IGYi - e2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXtjZXBoZnNfZmlsZXN5c3RlbX0iCiAgICAgICAg - ICAgICAgICBjYXBzWyJvc2QiXSA9IGYiYWxsb3cgcncgdGFnIGNlcGhmcyAqPXtjZXBoZnNfZmls - ZXN5c3RlbX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2VudGl0 - eSgKICAgICAgICBzZWxmLAogICAgICAgIGVudGl0eSwKICAgICAgICByYmRfcG9vbF9uYW1lLAog - ICAgICAgIGFsaWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgazhzX2NsdXN0ZXJfbmFtZSwKICAg - ICAgICByYWRvc19uYW1lc3BhY2UsCiAgICApOgogICAgICAgIGlmICgKICAgICAgICAgICAgcmJk - X3Bvb2xfbmFtZS5jb3VudCgiLiIpICE9IDAKICAgICAgICAgICAgb3IgcmJkX3Bvb2xfbmFtZS5j - b3VudCgiXyIpICE9IDAKICAgICAgICAgICAgb3IgYWxpYXNfcmJkX3Bvb2xfbmFtZSAhPSAiIgog - ICAgICAgICAgICAjIGNoZWNraW5nIGFsaWFzX3JiZF9wb29sX25hbWUgaXMgbm90IGVtcHR5IGFz - IHRoZXJlIG1heWJlIGEgc3BlY2lhbCBjaGFyYWN0ZXIgdXNlZCBvdGhlciB0aGFuIC4gb3IgXwog - ICAgICAgICk6CiAgICAgICAgICAgIGlmIGFsaWFzX3JiZF9wb29sX25hbWUgPT0gIiI6CiAgICAg - ICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAg - ICAgICAgICJwbGVhc2Ugc2V0IHRoZSAnLS1hbGlhcy1yYmQtZGF0YS1wb29sLW5hbWUnIGZsYWcg - YXMgdGhlIHJiZCBkYXRhIHBvb2wgbmFtZSBjb250YWlucyAnLicgb3IgJ18nIgogICAgICAgICAg - ICAgICAgKQogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICBhbGlhc19yYmRfcG9vbF9u - YW1lLmNvdW50KCIuIikgIT0gMAogICAgICAgICAgICAgICAgb3IgYWxpYXNfcmJkX3Bvb2xfbmFt - ZS5jb3VudCgiXyIpICE9IDAKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHJhaXNlIEV4 - ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIictLWFsaWFzLXJi - ZC1kYXRhLXBvb2wtbmFtZScgZmxhZyB2YWx1ZSBzaG91bGQgbm90IGNvbnRhaW4gJy4nIG9yICdf - JyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17azhz - X2NsdXN0ZXJfbmFtZX0te2FsaWFzX3JiZF9wb29sX25hbWV9IgogICAgICAgIGVsc2U6CiAgICAg - ICAgICAgIGVudGl0eSA9IGYie2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXtyYmRfcG9vbF9u - YW1lfSIKCiAgICAgICAgaWYgcmFkb3NfbmFtZXNwYWNlOgogICAgICAgICAgICBlbnRpdHkgPSBm - IntlbnRpdHl9LXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgIHJldHVybiBlbnRpdHkKCiAgICBk - ZWYgZ2V0X3JiZF9wcm92aXNpb25lcl9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50 - aXR5ID0gImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIgogICAgICAgIGNhcHMgPSB7CiAgICAg - ICAgICAgICJtb24iOiAicHJvZmlsZSByYmQsIGFsbG93IGNvbW1hbmQgJ29zZCBibG9ja2xpc3Qn - IiwKICAgICAgICAgICAgIm1nciI6ICJhbGxvdyBydyIsCiAgICAgICAgICAgICJvc2QiOiAicHJv - ZmlsZSByYmQiLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0 - ZWRfYXV0aF9wZXJtaXNzaW9uOgogICAgICAgICAgICByYmRfcG9vbF9uYW1lID0gc2VsZi5fYXJn - X3BhcnNlci5yYmRfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFt - ZSA9IHNlbGYuX2FyZ19wYXJzZXIuYWxpYXNfcmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAg - IGs4c19jbHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAg - ICAgICAgICAgcmFkb3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3Bh - Y2UKICAgICAgICAgICAgaWYgcmJkX3Bvb2xfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJh - aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRh - dG9yeSBmbGFnIG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tcmJkLWRhdGEtcG9vbC1uYW1l - JyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1l - ID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigK - ICAgICAgICAgICAgICAgICAgICAibWFuZGF0b3J5IGZsYWcgbm90IGZvdW5kLCBwbGVhc2Ugc2V0 - IHRoZSAnLS1rOHMtY2x1c3Rlci1uYW1lJyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAg - ICAgICBlbnRpdHkgPSBzZWxmLmdldF9lbnRpdHkoCiAgICAgICAgICAgICAgICBlbnRpdHksCiAg - ICAgICAgICAgICAgICByYmRfcG9vbF9uYW1lLAogICAgICAgICAgICAgICAgYWxpYXNfcmJkX3Bv - b2xfbmFtZSwKICAgICAgICAgICAgICAgIGs4c19jbHVzdGVyX25hbWUsCiAgICAgICAgICAgICAg - ICByYWRvc19uYW1lc3BhY2UsCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgcmFkb3NfbmFt - ZXNwYWNlICE9ICIiOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSAoCiAgICAgICAgICAg - ICAgICAgICAgZiJwcm9maWxlIHJiZCBwb29sPXtyYmRfcG9vbF9uYW1lfSBuYW1lc3BhY2U9e3Jh - ZG9zX25hbWVzcGFjZX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAg - ICAgICAgICAgICBjYXBzWyJvc2QiXSA9IGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFt - ZX0iCgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X3JiZF9ub2RlX2Nh - cHNfYW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSAiY2xpZW50LmNzaS1yYmQtbm9k - ZSIKICAgICAgICBjYXBzID0gewogICAgICAgICAgICAibW9uIjogInByb2ZpbGUgcmJkLCBhbGxv - dyBjb21tYW5kICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJvc2QiOiAicHJvZmlsZSBy - YmQiLAogICAgICAgIH0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0 - aF9wZXJtaXNzaW9uOgogICAgICAgICAgICByYmRfcG9vbF9uYW1lID0gc2VsZi5fYXJnX3BhcnNl - ci5yYmRfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFtZSA9IHNl - bGYuX2FyZ19wYXJzZXIuYWxpYXNfcmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGs4c19j - bHVzdGVyX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAgICAgICAg - ICAgcmFkb3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UKICAg - ICAgICAgICAgaWYgcmJkX3Bvb2xfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4 - ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBm - bGFnIG5vdCBmb3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tcmJkLWRhdGEtcG9vbC1uYW1lJyBmbGFn - IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1lID09ICIi - OgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAg - ICAgICAgICAgICAgICAibWFuZGF0b3J5IGZsYWcgbm90IGZvdW5kLCBwbGVhc2Ugc2V0IHRoZSAn - LS1rOHMtY2x1c3Rlci1uYW1lJyBmbGFnIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBl - bnRpdHkgPSBzZWxmLmdldF9lbnRpdHkoCiAgICAgICAgICAgICAgICBlbnRpdHksCiAgICAgICAg - ICAgICAgICByYmRfcG9vbF9uYW1lLAogICAgICAgICAgICAgICAgYWxpYXNfcmJkX3Bvb2xfbmFt - ZSwKICAgICAgICAgICAgICAgIGs4c19jbHVzdGVyX25hbWUsCiAgICAgICAgICAgICAgICByYWRv - c19uYW1lc3BhY2UsCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgcmFkb3NfbmFtZXNwYWNl - ICE9ICIiOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSAoCiAgICAgICAgICAgICAgICAg - ICAgZiJwcm9maWxlIHJiZCBwb29sPXtyYmRfcG9vbF9uYW1lfSBuYW1lc3BhY2U9e3JhZG9zX25h - bWVzcGFjZX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg - ICAgICBjYXBzWyJvc2QiXSA9IGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFtZX0iCgog - ICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2RlZmF1bHRVc2VyX2NhcHNf - YW5kX2VudGl0eShzZWxmKToKICAgICAgICBlbnRpdHkgPSBzZWxmLnJ1bl9hc191c2VyCiAgICAg - ICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJhbGxvdyByLCBhbGxvdyBjb21tYW5kIHF1 - b3J1bV9zdGF0dXMsIGFsbG93IGNvbW1hbmQgdmVyc2lvbiIsCiAgICAgICAgICAgICJtZ3IiOiAi - YWxsb3cgY29tbWFuZCBjb25maWciLAogICAgICAgICAgICAib3NkIjogZiJwcm9maWxlIHJiZC1y - ZWFkLW9ubHksIGFsbG93IHJ3eCBwb29sPXtzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZp - eH0ucmd3Lm1ldGEsIGFsbG93IHIgcG9vbD0ucmd3LnJvb3QsIGFsbG93IHJ3IHBvb2w9e3NlbGYu - X2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuY29udHJvbCwgYWxsb3cgcnggcG9vbD17 - c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5sb2csIGFsbG93IHggcG9vbD17 - c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5idWNrZXRzLmluZGV4IiwKICAg - ICAgICB9CgogICAgICAgIHJldHVybiBjYXBzLCBlbnRpdHkKCiAgICBkZWYgZ2V0X2NhcHNfYW5k - X2VudGl0eShzZWxmLCB1c2VyX25hbWUpOgogICAgICAgIGlmICJjbGllbnQuY3NpLWNlcGhmcy1w - cm92aXNpb25lciIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAiY2xpZW50LmNzaS1jZXBo - ZnMtcHJvdmlzaW9uZXIiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19w - YXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAgIHJldHVy - biBzZWxmLmdldF9jZXBoZnNfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KCkKICAgICAgICBp - ZiAiY2xpZW50LmNzaS1jZXBoZnMtbm9kZSIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAi - Y2xpZW50LmNzaS1jZXBoZnMtbm9kZSIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2Vs - Zi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAg - ICAgcmV0dXJuIHNlbGYuZ2V0X2NlcGhmc19ub2RlX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAg - aWYgImNsaWVudC5jc2ktcmJkLXByb3Zpc2lvbmVyIiBpbiB1c2VyX25hbWU6CiAgICAgICAgICAg - IGlmICJjbGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIgIT0gdXNlcl9uYW1lOgogICAgICAgICAg - ICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUK - ICAgICAgICAgICAgcmV0dXJuIHNlbGYuZ2V0X3JiZF9wcm92aXNpb25lcl9jYXBzX2FuZF9lbnRp - dHkoKQogICAgICAgIGlmICJjbGllbnQuY3NpLXJiZC1ub2RlIiBpbiB1c2VyX25hbWU6CiAgICAg - ICAgICAgIGlmICJjbGllbnQuY3NpLXJiZC1ub2RlIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAg - ICAgICBzZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQog - ICAgICAgICAgICByZXR1cm4gc2VsZi5nZXRfcmJkX25vZGVfY2Fwc19hbmRfZW50aXR5KCkKICAg - ICAgICBpZiAiY2xpZW50LmhlYWx0aGNoZWNrZXIiIGluIHVzZXJfbmFtZToKICAgICAgICAgICAg - aWYgImNsaWVudC5oZWFsdGhjaGVja2VyIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAgICAgICBz - ZWxmLl9hcmdfcGFyc2VyLnJlc3RyaWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQogICAgICAg - ICAgICByZXR1cm4gc2VsZi5nZXRfZGVmYXVsdFVzZXJfY2Fwc19hbmRfZW50aXR5KCkKCiAgICAg - ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgZiJubyB1c2Vy - IGZvdW5kIHdpdGggdXNlcl9uYW1lOiB7dXNlcl9uYW1lfSwgIgogICAgICAgICAgICAiZ2V0X2Nh - cHNfYW5kX2VudGl0eSBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICApCgogICAgZGVmIGNyZWF0 - ZV9jZXBoQ1NJS2V5cmluZ191c2VyKHNlbGYsIHVzZXIpOgogICAgICAgICIiIgogICAgICAgIGNv - bW1hbmQ6IGNlcGggYXV0aCBnZXQtb3ItY3JlYXRlIGNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv - bmVyIG1vbiAnYWxsb3cgcicgbWdyICdhbGxvdyBydycgb3NkICdhbGxvdyBydyB0YWcgY2VwaGZz - IG1ldGFkYXRhPSonCiAgICAgICAgIiIiCiAgICAgICAgY2FwcywgZW50aXR5ID0gc2VsZi5nZXRf - Y2Fwc19hbmRfZW50aXR5KHVzZXIpCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJw - cmVmaXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIiwKICAgICAgICAgICAgImVudGl0eSI6IGVudGl0 - eSwKICAgICAgICAgICAgImNhcHMiOiBbY2FwIGZvciBjYXBfbGlzdCBpbiBsaXN0KGNhcHMuaXRl - bXMoKSkgZm9yIGNhcCBpbiBjYXBfbGlzdF0sCiAgICAgICAgICAgICJmb3JtYXQiOiAianNvbiIs - CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAg - ICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICBzZWxmLmRyeV9ydW4oCiAgICAgICAgICAgICAg - ICAgICAgImNlcGggIgogICAgICAgICAgICAgICAgICAgICsgY21kX2pzb25bInByZWZpeCJdCiAg - ICAgICAgICAgICAgICAgICAgKyAiICIKICAgICAgICAgICAgICAgICAgICArIGNtZF9qc29uWyJl - bnRpdHkiXQogICAgICAgICAgICAgICAgICAgICsgIiAiCiAgICAgICAgICAgICAgICAgICAgKyAi - ICIuam9pbihjbWRfanNvblsiY2FwcyJdKQogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAg - ICAgICIiLAogICAgICAgICAgICApCiAgICAgICAgIyBjaGVjayBpZiB1c2VyIGFscmVhZHkgZXhp - c3QKICAgICAgICB1c2VyX2tleSA9IHNlbGYuY2hlY2tfdXNlcl9leGlzdChlbnRpdHkpCiAgICAg - ICAgaWYgdXNlcl9rZXkgIT0gIiI6CiAgICAgICAgICAgIHJldHVybiB1c2VyX2tleSwgZiJ7ZW50 - aXR5LnNwbGl0KCcuJywgMSlbMV19IgogICAgICAgICAgICAjIGVudGl0eS5zcGxpdCgnLicsMSlb - MV0gdG8gcmVuYW1lIGVudGl0eShjbGllbnQuY3NpLXJiZC1ub2RlKSBhcyBjc2ktcmJkLW5vZGUK - CiAgICAgICAgcmV0X3ZhbCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pz - b25fZ2VuKGNtZF9qc29uKQogICAgICAgICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0 - dGVtcHQsCiAgICAgICAgaWYgcmV0X3ZhbCAhPSAwIG9yIGxlbihqc29uX291dCkgPT0gMDoKICAg - ICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAg - IGYiJ2F1dGggZ2V0LW9yLWNyZWF0ZSB7dXNlcn0nIGNvbW1hbmQgZmFpbGVkLlxuIgogICAgICAg - ICAgICAgICAgZiJFcnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBU - WV9PVVRQVVRfTElTVH0iCiAgICAgICAgICAgICkKICAgICAgICByZXR1cm4gc3RyKGpzb25fb3V0 - WzBdWyJrZXkiXSksIGYie2VudGl0eS5zcGxpdCgnLicsIDEpWzFdfSIKICAgICAgICAjIGVudGl0 - eS5zcGxpdCgnLicsMSlbMV0gdG8gcmVuYW1lIGVudGl0eShjbGllbnQuY3NpLXJiZC1ub2RlKSBh - cyBjc2ktcmJkLW5vZGUKCiAgICBkZWYgZ2V0X2NlcGhmc19kYXRhX3Bvb2xfZGV0YWlscyhzZWxm - KToKICAgICAgICBjbWRfanNvbiA9IHsicHJlZml4IjogImZzIGxzIiwgImZvcm1hdCI6ICJqc29u - In0KICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVy - biBzZWxmLmRyeV9ydW4oImNlcGggIiArIGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRf - dmFsLCBqc29uX291dCwgZXJyX21zZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pz - b24pCiAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwgcmVwb3J0 - IGFuIGVycm9yCiAgICAgICAgaWYgcmV0X3ZhbCAhPSAwOgogICAgICAgICAgICAjIGlmIGZzIGFu - ZCBkYXRhX3Bvb2wgYXJndW1lbnRzIGFyZSBub3Qgc2V0LCBzaWxlbnRseSByZXR1cm4KICAgICAg - ICAgICAgaWYgKAogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmlsZXN5 - c3RlbV9uYW1lID09ICIiCiAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5jZXBo - ZnNfZGF0YV9wb29sX25hbWUgPT0gIiIKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIHJl - dHVybgogICAgICAgICAgICAjIGlmIHVzZXIgaGFzIHByb3ZpZGVkIGFueSBvZiB0aGUKICAgICAg - ICAgICAgIyAnLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lJyBvciAnLS1jZXBoZnMtZGF0YS1wb29s - LW5hbWUnIGFyZ3VtZW50cywKICAgICAgICAgICAgIyByYWlzZSBhbiBleGNlcHRpb24gYXMgd2Ug - YXJlIHVuYWJsZSB0byB2ZXJpZnkgdGhlIGFyZ3MKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9u - RmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiJ2ZzIGxzJyBjZXBoIGNhbGwgZmFp - bGVkIHdpdGggZXJyb3I6IHtlcnJfbXNnfSIKICAgICAgICAgICAgKQoKICAgICAgICBtYXRjaGlu - Z19qc29uX291dCA9IHt9CiAgICAgICAgIyBpZiAnLS1jZXBoZnMtZmlsZXN5c3RlbS1uYW1lJyBh - cmd1bWVudCBpcyBwcm92aWRlZCwKICAgICAgICAjIGNoZWNrIHdoZXRoZXIgdGhlIHByb3ZpZGVk - IGZpbGVzeXN0ZW0tbmFtZSBleGlzdHMgb3Igbm90CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl - ci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lOgogICAgICAgICAgICAjIGdldCB0aGUgbWF0Y2hpbmcg - bGlzdAogICAgICAgICAgICBtYXRjaGluZ19qc29uX291dF9saXN0ID0gWwogICAgICAgICAgICAg - ICAgbWF0Y2hlZAogICAgICAgICAgICAgICAgZm9yIG1hdGNoZWQgaW4ganNvbl9vdXQKICAgICAg - ICAgICAgICAgIGlmIHN0cihtYXRjaGVkWyJuYW1lIl0pID09IHNlbGYuX2FyZ19wYXJzZXIuY2Vw - aGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgICAgICBdCiAgICAgICAgICAgICMgdW5hYmxlIHRv - IGZpbmQgYSBtYXRjaGluZyBmcy1uYW1lLCByYWlzZSBhbiBlcnJvcgogICAgICAgICAgICBpZiBs - ZW4obWF0Y2hpbmdfanNvbl9vdXRfbGlzdCkgPT0gMDoKICAgICAgICAgICAgICAgIHJhaXNlIEV4 - ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgZiJGaWxlc3lzdGVt - IHByb3ZpZGVkLCAne3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZX0nLCAi - CiAgICAgICAgICAgICAgICAgICAgZiJpcyBub3QgZm91bmQgaW4gdGhlIGZzLWxpc3Q6IHtbc3Ry - KHhbJ25hbWUnXSkgZm9yIHggaW4ganNvbl9vdXRdfSIKICAgICAgICAgICAgICAgICkKICAgICAg - ICAgICAgbWF0Y2hpbmdfanNvbl9vdXQgPSBtYXRjaGluZ19qc29uX291dF9saXN0WzBdCiAgICAg - ICAgIyBpZiBjZXBoZnMgZmlsZXN5c3RlbSBuYW1lIGlzIG5vdCBwcm92aWRlZCwKICAgICAgICAj - IHRyeSB0byBnZXQgYSBkZWZhdWx0IGZzIG5hbWUgYnkgZG9pbmcgdGhlIGZvbGxvd2luZwogICAg - ICAgIGVsc2U6CiAgICAgICAgICAgICMgYS4gY2hlY2sgaWYgdGhlcmUgaXMgb25seSBvbmUgZmls - ZXN5c3RlbSBpcyBwcmVzZW50CiAgICAgICAgICAgIGlmIGxlbihqc29uX291dCkgPT0gMToKICAg - ICAgICAgICAgICAgIG1hdGNoaW5nX2pzb25fb3V0ID0ganNvbl9vdXRbMF0KICAgICAgICAgICAg - IyBiLiBvciBlbHNlLCBjaGVjayBpZiBkYXRhX3Bvb2wgbmFtZSBpcyBwcm92aWRlZAogICAgICAg - ICAgICBlbGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lOgogICAgICAg - ICAgICAgICAgIyBhbmQgaWYgcHJlc2VudCwgY2hlY2sgd2hldGhlciB0aGVyZSBleGlzdHMgYSBm - cyB3aGljaCBoYXMgdGhlIGRhdGFfcG9vbAogICAgICAgICAgICAgICAgZm9yIGVhY2hKIGluIGpz - b25fb3V0OgogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2Rh - dGFfcG9vbF9uYW1lIGluIGVhY2hKWyJkYXRhX3Bvb2xzIl06CiAgICAgICAgICAgICAgICAgICAg - ICAgIG1hdGNoaW5nX2pzb25fb3V0ID0gZWFjaEoKICAgICAgICAgICAgICAgICAgICAgICAgYnJl - YWsKICAgICAgICAgICAgICAgICMgaWYgdGhlcmUgaXMgbm8gbWF0Y2hpbmcgZnMgZXhpc3RzLCB0 - aGF0IG1lYW5zIHByb3ZpZGVkIGRhdGFfcG9vbCBuYW1lIGlzIGludmFsaWQKICAgICAgICAgICAg - ICAgIGlmIG5vdCBtYXRjaGluZ19qc29uX291dDoKICAgICAgICAgICAgICAgICAgICByYWlzZSBF - eGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgICAgICBmIlByb3Zp - ZGVkIGRhdGFfcG9vbCBuYW1lLCB7c2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25h - bWV9LCIKICAgICAgICAgICAgICAgICAgICAgICAgIiBkb2VzIG5vdCBleGlzdHMiCiAgICAgICAg - ICAgICAgICAgICAgKQogICAgICAgICAgICAjIGMuIGlmIG5vdGhpbmcgaXMgc2V0IGFuZCBjb3Vs - ZG4ndCBmaW5kIGEgZGVmYXVsdCwKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICMg - anVzdCByZXR1cm4gc2lsZW50bHkKICAgICAgICAgICAgICAgIHJldHVybgoKICAgICAgICBpZiBt - YXRjaGluZ19qc29uX291dDoKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls - ZXN5c3RlbV9uYW1lID0gc3RyKG1hdGNoaW5nX2pzb25fb3V0WyJuYW1lIl0pCiAgICAgICAgICAg - IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX21ldGFkYXRhX3Bvb2xfbmFtZSA9IHN0cigKICAgICAg - ICAgICAgICAgIG1hdGNoaW5nX2pzb25fb3V0WyJtZXRhZGF0YV9wb29sIl0KICAgICAgICAgICAg - KQoKICAgICAgICBpZiBpc2luc3RhbmNlKG1hdGNoaW5nX2pzb25fb3V0WyJkYXRhX3Bvb2xzIl0s - IGxpc3QpOgogICAgICAgICAgICAjIGlmIHRoZSB1c2VyIGhhcyBhbHJlYWR5IHByb3ZpZGVkIGRh - dGEtcG9vbC1uYW1lLAogICAgICAgICAgICAjIHRocm91Z2ggLS1jZXBoZnMtZGF0YS1wb29sLW5h - bWUKICAgICAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWU6 - CiAgICAgICAgICAgICAgICAjIGlmIHRoZSBwcm92aWRlZCBuYW1lIGlzIG5vdCBtYXRjaGluZyB3 - aXRoIHRoZSBvbmUgaW4gdGhlIGxpc3QKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAg - ICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFtZQogICAgICAgICAg - ICAgICAgICAgIG5vdCBpbiBtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdCiAgICAgICAg - ICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl - cHRpb24oCiAgICAgICAgICAgICAgICAgICAgICAgIGYiUHJvdmlkZWQgZGF0YS1wb29sLW5hbWU6 - ICd7c2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWV9JywgIgogICAgICAgICAg - ICAgICAgICAgICAgICAiZG9lc24ndCBtYXRjaCBmcm9tIHRoZSBkYXRhLXBvb2xzIGxpc3Q6ICIK - ICAgICAgICAgICAgICAgICAgICAgICAgZiJ7W3N0cih4KSBmb3IgeCBpbiBtYXRjaGluZ19qc29u - X291dFsnZGF0YV9wb29scyddXX0iCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAj - IGlmIGRhdGFfcG9vbCBuYW1lIGlzIG5vdCBwcm92aWRlZCwKICAgICAgICAgICAgIyB0aGVuIHRy - eSB0byBmaW5kIGEgZGVmYXVsdCBkYXRhIHBvb2wgbmFtZQogICAgICAgICAgICBlbHNlOgogICAg - ICAgICAgICAgICAgIyBpZiBubyBkYXRhX3Bvb2xzIGV4aXN0LCBzaWxlbnRseSByZXR1cm4KICAg - ICAgICAgICAgICAgIGlmIGxlbihtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdKSA9PSAw - OgogICAgICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3Bh - cnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWUgPSBzdHIoCiAgICAgICAgICAgICAgICAgICAgbWF0 - Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXVswXQogICAgICAgICAgICAgICAgKQogICAgICAg - ICAgICAjIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lICdkYXRhX3Bvb2xzJyBleGlzdCwKICAg - ICAgICAgICAgIyB0aGVuIHdhcm4gdGhlIHVzZXIgdGhhdCB3ZSBhcmUgdXNpbmcgdGhlIHNlbGVj - dGVkIG5hbWUKICAgICAgICAgICAgaWYgbGVuKG1hdGNoaW5nX2pzb25fb3V0WyJkYXRhX3Bvb2xz - Il0pID4gMToKICAgICAgICAgICAgICAgIHByaW50KAogICAgICAgICAgICAgICAgICAgICJXQVJO - SU5HOiBNdWx0aXBsZSBkYXRhIHBvb2xzIGRldGVjdGVkOiAiCiAgICAgICAgICAgICAgICAgICAg - ZiJ7W3N0cih4KSBmb3IgeCBpbiBtYXRjaGluZ19qc29uX291dFsnZGF0YV9wb29scyddXX1cbiIK - ICAgICAgICAgICAgICAgICAgICBmIlVzaW5nIHRoZSBkYXRhLXBvb2w6ICd7c2VsZi5fYXJnX3Bh - cnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWV9J1xuIgogICAgICAgICAgICAgICAgKQoKICAgIGRl - ZiBjcmVhdGVfY2hlY2tlcktleShzZWxmLCB1c2VyKToKICAgICAgICBjYXBzLCBlbnRpdHkgPSBz - ZWxmLmdldF9jYXBzX2FuZF9lbnRpdHkodXNlcikKICAgICAgICBjbWRfanNvbiA9IHsKICAgICAg - ICAgICAgInByZWZpeCI6ICJhdXRoIGdldC1vci1jcmVhdGUiLAogICAgICAgICAgICAiZW50aXR5 - IjogZW50aXR5LAogICAgICAgICAgICAiY2FwcyI6IFtjYXAgZm9yIGNhcF9saXN0IGluIGxpc3Qo - Y2Fwcy5pdGVtcygpKSBmb3IgY2FwIGluIGNhcF9saXN0XSwKICAgICAgICAgICAgImZvcm1hdCI6 - ICJqc29uIiwKICAgICAgICB9CgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoK - ICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigKICAgICAgICAgICAgICAgICJjZXBoICIK - ICAgICAgICAgICAgICAgICsgY21kX2pzb25bInByZWZpeCJdCiAgICAgICAgICAgICAgICArICIg - IgogICAgICAgICAgICAgICAgKyBjbWRfanNvblsiZW50aXR5Il0KICAgICAgICAgICAgICAgICsg - IiAiCiAgICAgICAgICAgICAgICArICIgIi5qb2luKGNtZF9qc29uWyJjYXBzIl0pCiAgICAgICAg - ICAgICkKICAgICAgICAjIGNoZWNrIGlmIHVzZXIgYWxyZWFkeSBleGlzdAogICAgICAgIHVzZXJf - a2V5ID0gc2VsZi5jaGVja191c2VyX2V4aXN0KGVudGl0eSkKICAgICAgICBpZiB1c2VyX2tleSAh - PSAiIjoKICAgICAgICAgICAgcmV0dXJuIHVzZXJfa2V5CgogICAgICAgIHJldF92YWwsIGpzb25f - b3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAg - ICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgIGlmIHJldF92 - YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlv - bkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGdldC1vci1jcmVhdGUg - e3NlbGYucnVuX2FzX3VzZXJ9JyBjb21tYW5kIGZhaWxlZFxuIgogICAgICAgICAgICAgICAgZiJF - cnJvcjoge2Vycl9tc2cgaWYgcmV0X3ZhbCAhPSAwIGVsc2Ugc2VsZi5FTVBUWV9PVVRQVVRfTElT - VH0iCiAgICAgICAgICAgICkKICAgICAgICByZXR1cm4gc3RyKGpzb25fb3V0WzBdWyJrZXkiXSkK - CiAgICBkZWYgZ2V0X2NlcGhfZGFzaGJvYXJkX2xpbmsoc2VsZik6CiAgICAgICAgY21kX2pzb24g - PSB7InByZWZpeCI6ICJtZ3Igc2VydmljZXMiLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgIGlm - IHNlbGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1 - bigiY2VwaCAiICsgY21kX2pzb25bInByZWZpeCJdKQogICAgICAgIHJldF92YWwsIGpzb25fb3V0 - LCBfID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICAjIGlmIHRo - ZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAgICAgIGlmIHJldF92YWwgIT0gMCBv - ciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJldHVybiBOb25lCiAgICAgICAgaWYg - ImRhc2hib2FyZCIgbm90IGluIGpzb25fb3V0OgogICAgICAgICAgICByZXR1cm4gTm9uZQogICAg - ICAgIHJldHVybiBqc29uX291dFsiZGFzaGJvYXJkIl0KCiAgICBkZWYgY3JlYXRlX3Jnd19hZG1p - bl9vcHNfdXNlcihzZWxmKToKICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICJyYWRvc2d3LWFk - bWluIiwKICAgICAgICAgICAgInVzZXIiLAogICAgICAgICAgICAiY3JlYXRlIiwKICAgICAgICAg - ICAgIi0tdWlkIiwKICAgICAgICAgICAgc2VsZi5FWFRFUk5BTF9SR1dfQURNSU5fT1BTX1VTRVJf - TkFNRSwKICAgICAgICAgICAgIi0tZGlzcGxheS1uYW1lIiwKICAgICAgICAgICAgIlJvb2sgUkdX - IEFkbWluIE9wcyB1c2VyIiwKICAgICAgICAgICAgIi0tY2FwcyIsCiAgICAgICAgICAgICJidWNr - ZXRzPSo7dXNlcnM9Kjt1c2FnZT1yZWFkO21ldGFkYXRhPXJlYWQ7em9uZT1yZWFkIiwKICAgICAg - ICAgICAgIi0tcmd3LXJlYWxtIiwKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVh - bG1fbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAgICAgICAgIHNlbGYu - X2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lLAogICAgICAgICAgICAiLS1yZ3ctem9uZSIs - CiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwKICAgICAgICBdCiAg - ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2Vs - Zi5kcnlfcnVuKCJjZXBoICIgKyAiICIuam9pbihjbWQpKQogICAgICAgIHRyeToKICAgICAgICAg - ICAgb3V0cHV0ID0gc3VicHJvY2Vzcy5jaGVja19vdXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vz - cy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBl - eGVjRXJyOgogICAgICAgICAgICAjIGlmIHRoZSB1c2VyIGFscmVhZHkgZXhpc3RzLCB3ZSBqdXN0 - IHF1ZXJ5IGl0CiAgICAgICAgICAgIGlmIGV4ZWNFcnIucmV0dXJuY29kZSA9PSBlcnJuby5FRVhJ - U1Q6CiAgICAgICAgICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICAgICAgICAgInJhZG9zZ3ct - YWRtaW4iLAogICAgICAgICAgICAgICAgICAgICJ1c2VyIiwKICAgICAgICAgICAgICAgICAgICAi - aW5mbyIsCiAgICAgICAgICAgICAgICAgICAgIi0tdWlkIiwKICAgICAgICAgICAgICAgICAgICBz - ZWxmLkVYVEVSTkFMX1JHV19BRE1JTl9PUFNfVVNFUl9OQU1FLAogICAgICAgICAgICAgICAgICAg - ICItLXJndy1yZWFsbSIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3df - cmVhbG1fbmFtZSwKICAgICAgICAgICAgICAgICAgICAiLS1yZ3ctem9uZWdyb3VwIiwKICAgICAg - ICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAg - ICAgICAgICAgICAgICAiLS1yZ3ctem9uZSIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJn - X3BhcnNlci5yZ3dfem9uZV9uYW1lLAogICAgICAgICAgICAgICAgXQogICAgICAgICAgICAgICAg - dHJ5OgogICAgICAgICAgICAgICAgICAgIG91dHB1dCA9IHN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0 - KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICAgICAgICAgIGV4Y2VwdCBzdWJw - cm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAgICAgICAgICAg - IGVycl9tc2cgPSAoCiAgICAgICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUg - Y29tbWFuZCB7Y21kfS4gT3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAg - ICAgICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5z - dGRlcnJ9IgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICBzeXMuc3Rk - ZXJyLndyaXRlKGVycl9tc2cpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE5vbmUsIE5vbmUs - IEZhbHNlLCAiLTEiCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlcnJfbXNnID0g - KAogICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUgY29tbWFuZCB7Y21kfS4g - T3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAgICAgICAgZiJDb2RlOiB7 - ZXhlY0Vyci5yZXR1cm5jb2RlfS4gRXJyb3I6IHtleGVjRXJyLnN0ZGVycn0iCiAgICAgICAgICAg - ICAgICApCiAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycl9tc2cpCiAgICAgICAg - ICAgICAgICByZXR1cm4gTm9uZSwgTm9uZSwgRmFsc2UsICItMSIKCiAgICAgICAgIyBzZXBhcmF0 - ZWx5IGFkZCBpbmZvPXJlYWQgY2FwcyBmb3Igcmd3LWVuZHBvaW50IGlwIHZhbGlkYXRpb24KICAg - ICAgICBpbmZvX2NhcF9zdXBwb3J0ZWQgPSBUcnVlCiAgICAgICAgY21kID0gWwogICAgICAgICAg - ICAicmFkb3Nndy1hZG1pbiIsCiAgICAgICAgICAgICJjYXBzIiwKICAgICAgICAgICAgImFkZCIs - CiAgICAgICAgICAgICItLXVpZCIsCiAgICAgICAgICAgIHNlbGYuRVhURVJOQUxfUkdXX0FETUlO - X09QU19VU0VSX05BTUUsCiAgICAgICAgICAgICItLWNhcHMiLAogICAgICAgICAgICAiaW5mbz1y - ZWFkIiwKICAgICAgICAgICAgIi0tcmd3LXJlYWxtIiwKICAgICAgICAgICAgc2VsZi5fYXJnX3Bh - cnNlci5yZ3dfcmVhbG1fbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAg - ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lLAogICAgICAgICAgICAi - LS1yZ3ctem9uZSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwK - ICAgICAgICBdCiAgICAgICAgdHJ5OgogICAgICAgICAgICBvdXRwdXQgPSBzdWJwcm9jZXNzLmNo - ZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhjZXB0IHN1 - YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4ZWNFcnI6CiAgICAgICAgICAgICMgaWYg - dGhlIGNlcGggdmVyc2lvbiBub3Qgc3VwcG9ydGVkIGZvciBhZGRpbmcgYGluZm89cmVhZGAgY2Fw - KHJnd192YWxpZGF0aW9uKQogICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAiY291bGQg - bm90IGFkZCBjYXBzOiB1bmFibGUgdG8gYWRkIGNhcHM6IGluZm89cmVhZFxuIgogICAgICAgICAg - ICAgICAgaW4gZXhlY0Vyci5zdGRlcnIuZGVjb2RlKCJ1dGYtOCIpCiAgICAgICAgICAgICAgICBh - bmQgZXhlY0Vyci5yZXR1cm5jb2RlID09IDI0NAogICAgICAgICAgICApOgogICAgICAgICAgICAg - ICAgaW5mb19jYXBfc3VwcG9ydGVkID0gRmFsc2UKICAgICAgICAgICAgZWxzZToKICAgICAgICAg - ICAgICAgIGVycl9tc2cgPSAoCiAgICAgICAgICAgICAgICAgICAgZiJmYWlsZWQgdG8gZXhlY3V0 - ZSBjb21tYW5kIHtjbWR9LiBPdXRwdXQ6IHtleGVjRXJyLm91dHB1dH0uICIKICAgICAgICAgICAg - ICAgICAgICBmIkNvZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3Rk - ZXJyfSIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3JpdGUo - ZXJyX21zZykKICAgICAgICAgICAgICAgIHJldHVybiBOb25lLCBOb25lLCBGYWxzZSwgIi0xIgoK - ICAgICAgICBqc29ub3V0cHV0ID0ganNvbi5sb2FkcyhvdXRwdXQpCiAgICAgICAgcmV0dXJuICgK - ICAgICAgICAgICAganNvbm91dHB1dFsia2V5cyJdWzBdWyJhY2Nlc3Nfa2V5Il0sCiAgICAgICAg - ICAgIGpzb25vdXRwdXRbImtleXMiXVswXVsic2VjcmV0X2tleSJdLAogICAgICAgICAgICBpbmZv - X2NhcF9zdXBwb3J0ZWQsCiAgICAgICAgICAgICIiLAogICAgICAgICkKCiAgICBkZWYgdmFsaWRh - dGVfcmJkX3Bvb2woc2VsZiwgcG9vbF9uYW1lKToKICAgICAgICBpZiBub3Qgc2VsZi5jbHVzdGVy - LnBvb2xfZXhpc3RzKHBvb2xfbmFtZSk6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1 - cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCBwb29sLCAne3Bvb2xf - bmFtZX0nLCBkb2VzIG5vdCBleGlzdCIKICAgICAgICAgICAgKQoKICAgIGRlZiBpbml0X3JiZF9w - b29sKHNlbGYsIHJiZF9wb29sX25hbWUpOgogICAgICAgIGlmIGlzaW5zdGFuY2Uoc2VsZi5jbHVz - dGVyLCBEdW1teVJhZG9zKToKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgaW9jdHggPSBzZWxm - LmNsdXN0ZXIub3Blbl9pb2N0eChyYmRfcG9vbF9uYW1lKQogICAgICAgIHJiZF9pbnN0ID0gcmJk - LlJCRCgpCiAgICAgICAgcmJkX2luc3QucG9vbF9pbml0KGlvY3R4LCBUcnVlKQoKICAgIGRlZiB2 - YWxpZGF0ZV9yYWRvc19uYW1lc3BhY2Uoc2VsZik6CiAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNl - bGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh - cnNlci5yYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lOgogICAgICAgICAgICByYmRfcG9vbF9uYW1l - ID0gc2VsZi5fYXJnX3BhcnNlci5yYmRfbWV0YWRhdGFfZWNfcG9vbF9uYW1lCiAgICAgICAgcmFk - b3NfbmFtZXNwYWNlID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UKICAgICAgICBp - ZiByYWRvc19uYW1lc3BhY2UgPT0gIiI6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGlmIHJh - ZG9zX25hbWVzcGFjZS5pc2xvd2VyKCkgPT0gRmFsc2U6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1 - dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByYWRv - cyBOYW1lc3BhY2UsICd7cmFkb3NfbmFtZXNwYWNlfScsICIKICAgICAgICAgICAgICAgIGYiY29u - dGFpbnMgdXBwZXIgY2FzZSIKICAgICAgICAgICAgKQogICAgICAgIHJiZF9pbnN0ID0gcmJkLlJC - RCgpCiAgICAgICAgaW9jdHggPSBzZWxmLmNsdXN0ZXIub3Blbl9pb2N0eChyYmRfcG9vbF9uYW1l - KQogICAgICAgIGlmIHJiZF9pbnN0Lm5hbWVzcGFjZV9leGlzdHMoaW9jdHgsIHJhZG9zX25hbWVz - cGFjZSkgaXMgRmFsc2U6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRp - b24oCiAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByYWRvcyBOYW1lc3BhY2UsICd7cmFk - b3NfbmFtZXNwYWNlfScsICIKICAgICAgICAgICAgICAgIGYiaXMgbm90IGZvdW5kIGluIHRoZSBw - b29sICd7cmJkX3Bvb2xfbmFtZX0nIgogICAgICAgICAgICApCgogICAgZGVmIGdldF9vcl9jcmVh - dGVfc3Vidm9sdW1lX2dyb3VwKHNlbGYsIHN1YnZvbHVtZV9ncm91cCwgY2VwaGZzX2ZpbGVzeXN0 - ZW1fbmFtZSk6CiAgICAgICAgY21kID0gWwogICAgICAgICAgICAiY2VwaCIsCiAgICAgICAgICAg - ICJmcyIsCiAgICAgICAgICAgICJzdWJ2b2x1bWVncm91cCIsCiAgICAgICAgICAgICJnZXRwYXRo - IiwKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgc3Vidm9s - dW1lX2dyb3VwLAogICAgICAgIF0KICAgICAgICB0cnk6CiAgICAgICAgICAgIF8gPSBzdWJwcm9j - ZXNzLmNoZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhj - ZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICBjbWQgPSBbCiAg - ICAgICAgICAgICAgICAiY2VwaCIsCiAgICAgICAgICAgICAgICAiZnMiLAogICAgICAgICAgICAg - ICAgInN1YnZvbHVtZWdyb3VwIiwKICAgICAgICAgICAgICAgICJjcmVhdGUiLAogICAgICAgICAg - ICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgICAgIHN1YnZvbHVtZV9n - cm91cCwKICAgICAgICAgICAgXQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBfID0g - c3VicHJvY2Vzcy5jaGVja19vdXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAg - ICAgICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgICAg - ICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAg - IGYic3Vidm9sdW1lIGdyb3VwIHtzdWJ2b2x1bWVfZ3JvdXB9IGlzIG5vdCBhYmxlIHRvIGdldCBj - cmVhdGVkIgogICAgICAgICAgICAgICAgKQoKICAgIGRlZiBwaW5fc3Vidm9sdW1lKAogICAgICAg - IHNlbGYsIHN1YnZvbHVtZV9ncm91cCwgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwgcGluX3R5cGUs - IHBpbl9zZXR0aW5nCiAgICApOgogICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgImNlcGgiLAog - ICAgICAgICAgICAiZnMiLAogICAgICAgICAgICAic3Vidm9sdW1lZ3JvdXAiLAogICAgICAgICAg - ICAicGluIiwKICAgICAgICAgICAgY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAg - c3Vidm9sdW1lX2dyb3VwLAogICAgICAgICAgICBwaW5fdHlwZSwKICAgICAgICAgICAgcGluX3Nl - dHRpbmcsCiAgICAgICAgXQogICAgICAgIHRyeToKICAgICAgICAgICAgXyA9IHN1YnByb2Nlc3Mu - Y2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICBleGNlcHQg - c3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlv - bkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmInN1YnZvbHVtZSBncm91cCB7c3Vi - dm9sdW1lX2dyb3VwfSBpcyBub3QgYWJsZSB0byBnZXQgcGlubmVkIgogICAgICAgICAgICApCgog - ICAgZGVmIGdldF9yZ3dfZnNpZChzZWxmLCBiYXNlX3VybCwgdmVyaWZ5KToKICAgICAgICBhY2Nl - c3Nfa2V5ID0gc2VsZi5vdXRfbWFwWyJSR1dfQURNSU5fT1BTX1VTRVJfQUNDRVNTX0tFWSJdCiAg - ICAgICAgc2VjcmV0X2tleSA9IHNlbGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JF - VF9LRVkiXQogICAgICAgIHJnd19lbmRwb2ludCA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBv - aW50CiAgICAgICAgYmFzZV91cmwgPSBiYXNlX3VybCArICI6Ly8iICsgcmd3X2VuZHBvaW50ICsg - Ii9hZG1pbi9pbmZvPyIKICAgICAgICBwYXJhbXMgPSB7ImZvcm1hdCI6ICJqc29uIn0KICAgICAg - ICByZXF1ZXN0X3VybCA9IGJhc2VfdXJsICsgdXJsZW5jb2RlKHBhcmFtcykKCiAgICAgICAgdHJ5 - OgogICAgICAgICAgICByID0gcmVxdWVzdHMuZ2V0KAogICAgICAgICAgICAgICAgcmVxdWVzdF91 - cmwsCiAgICAgICAgICAgICAgICBhdXRoPVMzQXV0aChhY2Nlc3Nfa2V5LCBzZWNyZXRfa2V5LCBy - Z3dfZW5kcG9pbnQpLAogICAgICAgICAgICAgICAgdmVyaWZ5PXZlcmlmeSwKICAgICAgICAgICAg - KQogICAgICAgIGV4Y2VwdCByZXF1ZXN0cy5leGNlcHRpb25zLlRpbWVvdXQ6CiAgICAgICAgICAg - IHN5cy5zdGRlcnIud3JpdGUoCiAgICAgICAgICAgICAgICBmImludmFsaWQgZW5kcG9pbnQ6LCBu - b3QgYWJsZSB0byBjYWxsIGFkbWluLW9wcyBhcGl7cmd3X2VuZHBvaW50fSIKICAgICAgICAgICAg - KQogICAgICAgICAgICByZXR1cm4gIiIsICItMSIKICAgICAgICByMSA9IHIuanNvbigpCiAgICAg - ICAgaWYgcjEgaXMgTm9uZSBvciByMS5nZXQoImluZm8iKSBpcyBOb25lOgogICAgICAgICAgICBz - eXMuc3RkZXJyLndyaXRlKAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmd3IEVuZHBv - aW50LCAne3NlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50fScsIGlzIGludmFsaWQuIgogICAg - ICAgICAgICApCiAgICAgICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICAgICAiIiwKICAgICAg - ICAgICAgICAgICItMSIsCiAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIHIxWyJpbmZvIl1b - InN0b3JhZ2VfYmFja2VuZHMiXVswXVsiY2x1c3Rlcl9pZCJdLCAiIgoKICAgIGRlZiB2YWxpZGF0 - ZV9yZ3dfZW5kcG9pbnQoc2VsZiwgaW5mb19jYXBfc3VwcG9ydGVkKToKICAgICAgICAjIGlmIHRo - ZSAnY2x1c3RlcicgaW5zdGFuY2UgaXMgYSBkdW1teSBvbmUsCiAgICAgICAgIyBkb24ndCB0cnkg - dG8gcmVhY2ggb3V0IHRvIHRoZSBlbmRwb2ludAogICAgICAgIGlmIGlzaW5zdGFuY2Uoc2VsZi5j - bHVzdGVyLCBEdW1teVJhZG9zKToKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgIHJnd19lbmRw - b2ludCA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50CgogICAgICAgICMgdmFsaWRhdGUg - cmd3IGVuZHBvaW50IG9ubHkgaWYgaXAgYWRkcmVzcyBpcyBwYXNzZWQKICAgICAgICBpcF90eXBl - ID0gc2VsZi5faW52YWxpZF9lbmRwb2ludChyZ3dfZW5kcG9pbnQpCgogICAgICAgICMgY2hlY2sg - aWYgdGhlIHJndyBlbmRwb2ludCBpcyByZWFjaGFibGUKICAgICAgICBjZXJ0ID0gTm9uZQogICAg - ICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2VyLnJnd19za2lwX3RscyBhbmQgc2VsZi52YWxpZGF0 - ZV9yZ3dfZW5kcG9pbnRfdGxzX2NlcnQoKToKICAgICAgICAgICAgY2VydCA9IHNlbGYuX2FyZ19w - YXJzZXIucmd3X3Rsc19jZXJ0X3BhdGgKICAgICAgICBiYXNlX3VybCwgdmVyaWZ5LCBlcnIgPSBz - ZWxmLmVuZHBvaW50X2RpYWwocmd3X2VuZHBvaW50LCBpcF90eXBlLCBjZXJ0PWNlcnQpCiAgICAg - ICAgaWYgZXJyICE9ICIiOgogICAgICAgICAgICByZXR1cm4gIi0xIgoKICAgICAgICAjIGNoZWNr - IGlmIHRoZSByZ3cgZW5kcG9pbnQgYmVsb25ncyB0byB0aGUgc2FtZSBjbHVzdGVyCiAgICAgICAg - IyBvbmx5IGNoZWNrIGlmIGBpbmZvYCBjYXAgaXMgc3VwcG9ydGVkCiAgICAgICAgaWYgaW5mb19j - YXBfc3VwcG9ydGVkOgogICAgICAgICAgICBmc2lkID0gc2VsZi5nZXRfZnNpZCgpCiAgICAgICAg - ICAgIHJnd19mc2lkLCBlcnIgPSBzZWxmLmdldF9yZ3dfZnNpZChiYXNlX3VybCwgdmVyaWZ5KQog - ICAgICAgICAgICBpZiBlcnIgPT0gIi0xIjoKICAgICAgICAgICAgICAgIHJldHVybiAiLTEiCiAg - ICAgICAgICAgIGlmIGZzaWQgIT0gcmd3X2ZzaWQ6CiAgICAgICAgICAgICAgICBzeXMuc3RkZXJy - LndyaXRlKAogICAgICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHJndyBFbmRwb2ludCwg - J3tzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludH0nLCBpcyBpbnZhbGlkLiBXZSBhcmUgdmFs - aWRhdGluZyBieSBjYWxsaW5nIHRoZSBhZG1pbm9wcyBhcGkgdGhyb3VnaCByZ3ctZW5kcG9pbnQg - YW5kIHZhbGlkYXRpbmcgdGhlIGNsdXN0ZXJfaWQgJ3tyZ3dfZnNpZH0nIGlzIGVxdWFsIHRvIHRo - ZSBjZXBoIGNsdXN0ZXIgZnNpZCAne2ZzaWR9JyIKICAgICAgICAgICAgICAgICkKICAgICAgICAg - ICAgICAgIHJldHVybiAiLTEiCgogICAgICAgICMgY2hlY2sgaWYgdGhlIHJndyBlbmRwb2ludCBw - b29sIGV4aXN0CiAgICAgICAgIyBvbmx5IHZhbGlkYXRlIGlmIHJnd19wb29sX3ByZWZpeCBpcyBw - YXNzZWQgZWxzZSBpdCB3aWxsIHRha2UgZGVmYXVsdCB2YWx1ZSBhbmQgd2UgZG9uJ3QgY3JlYXRl - IHRoZXNlIGRlZmF1bHQgcG9vbHMKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29s - X3ByZWZpeCAhPSAiZGVmYXVsdCI6CiAgICAgICAgICAgIHJnd19wb29sc190b192YWxpZGF0ZSA9 - IFsKICAgICAgICAgICAgICAgIGYie3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5y - Z3cubWV0YSIsCiAgICAgICAgICAgICAgICAiLnJndy5yb290IiwKICAgICAgICAgICAgICAgIGYi - e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuY29udHJvbCIsCiAgICAgICAg - ICAgICAgICBmIntzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmxvZyIsCiAg - ICAgICAgICAgIF0KICAgICAgICAgICAgZm9yIF9yZ3dfcG9vbF90b192YWxpZGF0ZSBpbiByZ3df - cG9vbHNfdG9fdmFsaWRhdGU6CiAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5jbHVzdGVyLnBv - b2xfZXhpc3RzKF9yZ3dfcG9vbF90b192YWxpZGF0ZSk6CiAgICAgICAgICAgICAgICAgICAgc3lz - LnN0ZGVyci53cml0ZSgKICAgICAgICAgICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcG9v - bCwgJ3tfcmd3X3Bvb2xfdG9fdmFsaWRhdGV9JywgZG9lcyBub3QgZXhpc3QiCiAgICAgICAgICAg - ICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgIHJldHVybiAiLTEiCgogICAgICAgIHJldHVy - biAiIgoKICAgIGRlZiB2YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKHNlbGYsIHJnd19tdWx0aXNpdGVf - Y29uZmlnX25hbWUsIHJnd19tdWx0aXNpdGVfY29uZmlnKToKICAgICAgICBpZiByZ3dfbXVsdGlz - aXRlX2NvbmZpZyAhPSAiIjoKICAgICAgICAgICAgY21kID0gWwogICAgICAgICAgICAgICAgInJh - ZG9zZ3ctYWRtaW4iLAogICAgICAgICAgICAgICAgcmd3X211bHRpc2l0ZV9jb25maWcsCiAgICAg - ICAgICAgICAgICAiZ2V0IiwKICAgICAgICAgICAgICAgICItLXJndy0iICsgcmd3X211bHRpc2l0 - ZV9jb25maWcsCiAgICAgICAgICAgICAgICByZ3dfbXVsdGlzaXRlX2NvbmZpZ19uYW1lLAogICAg - ICAgICAgICBdCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIF8gPSBzdWJwcm9jZXNz - LmNoZWNrX291dHB1dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgICAgIGV4 - Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAg - ICAgICAgZXJyX21zZyA9ICgKICAgICAgICAgICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRl - IGNvbW1hbmQge2NtZH0uIE91dHB1dDoge2V4ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAg - ICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5zdGRl - cnJ9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShl - cnJfbXNnKQogICAgICAgICAgICAgICAgcmV0dXJuICItMSIKICAgICAgICByZXR1cm4gIiIKCiAg - ICBkZWYgY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoc2VsZiwgdmFsdWUpOgogICAg - ICAgIHJldHVybiB2YWx1ZS5zcGxpdCgiLCIpCgogICAgZGVmIHJhaXNlX2V4Y2VwdGlvbl9pZl9h - bnlfdG9wb2xvZ3lfZmxhZ19pc19taXNzaW5nKHNlbGYpOgogICAgICAgIGlmICgKICAgICAgICAg - ICAgKAogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9wb29scyAhPSAi - IgogICAgICAgICAgICAgICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFy - c2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsID09ICIiCiAgICAgICAgICAgICAgICAg - ICAgb3Igc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMgPT0g - IiIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgKQogICAgICAgICAgICBvciAoCiAgICAg - ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVs - ICE9ICIiCiAgICAgICAgICAgICAgICBhbmQgKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2Fy - Z19wYXJzZXIudG9wb2xvZ3lfcG9vbHMgPT0gIiIKICAgICAgICAgICAgICAgICAgICBvciBzZWxm - Ll9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX3ZhbHVlcyA9PSAiIgogICAgICAg - ICAgICAgICAgKQogICAgICAgICAgICApCiAgICAgICAgICAgIG9yICgKICAgICAgICAgICAgICAg - IHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFpbHVyZV9kb21haW5fdmFsdWVzICE9ICIiCiAg - ICAgICAgICAgICAgICBhbmQgKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIu - dG9wb2xvZ3lfcG9vbHMgPT0gIiIKICAgICAgICAgICAgICAgICAgICBvciBzZWxmLl9hcmdfcGFy - c2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsID09ICIiCiAgICAgICAgICAgICAgICAp - CiAgICAgICAgICAgICkKICAgICAgICApOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls - dXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgInByb3ZpZGUgYWxsIHRoZSB0b3BvbG9neSBm - bGFncyAtLXRvcG9sb2d5LXBvb2xzLCAtLXRvcG9sb2d5LWZhaWx1cmUtZG9tYWluLWxhYmVsLCAt - LXRvcG9sb2d5LWZhaWx1cmUtZG9tYWluLXZhbHVlcyIKICAgICAgICAgICAgKQoKICAgIGRlZiB2 - YWxpZGF0ZV90b3BvbG9neV92YWx1ZXMoc2VsZiwgdG9wb2xvZ3lfcG9vbHMsIHRvcG9sb2d5X2Zk - KToKICAgICAgICBpZiBsZW4odG9wb2xvZ3lfcG9vbHMpICE9IGxlbih0b3BvbG9neV9mZCk6CiAg - ICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAg - ICBmIlRoZSBwcm92aWRlZCB0b3BvbG9neSBwb29scywgJ3t0b3BvbG9neV9wb29sc30nLCBhbmQg - IgogICAgICAgICAgICAgICAgZiJ0b3BvbG9neSBmYWlsdXJlIGRvbWFpbiwgJ3t0b3BvbG9neV9m - ZH0nLCIKICAgICAgICAgICAgICAgIGYiYXJlIG9mIGRpZmZlcmVudCBsZW5ndGgsICd7bGVuKHRv - cG9sb2d5X3Bvb2xzKX0nIGFuZCAne2xlbih0b3BvbG9neV9mZCl9JyByZXNwY3RpdmVseSIKICAg - ICAgICAgICAgKQogICAgICAgIHJldHVybgoKICAgIGRlZiB2YWxpZGF0ZV90b3BvbG9neV9yYmRf - cG9vbHMoc2VsZiwgdG9wb2xvZ3lfcmJkX3Bvb2xzKToKICAgICAgICBmb3IgcG9vbCBpbiB0b3Bv - bG9neV9yYmRfcG9vbHM6CiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfcmJkX3Bvb2wocG9vbCkK - CiAgICBkZWYgaW5pdF90b3BvbG9neV9yYmRfcG9vbHMoc2VsZiwgdG9wb2xvZ3lfcmJkX3Bvb2xz - KToKICAgICAgICBmb3IgcG9vbCBpbiB0b3BvbG9neV9yYmRfcG9vbHM6CiAgICAgICAgICAgIHNl - bGYuaW5pdF9yYmRfcG9vbChwb29sKQoKICAgICMgdGhpcyB3aWxsIHJldHVybiB0aGUgZmluYWwg - YXJncyB0aGF0IHNjcmlwdCB1c2VzIHRvIHByb2Nlc3MKICAgICMgdGhlIHByaW9yaXR5IHRvIHNl - dCBhIHBhcnRpY3VsYXIgdmFsdWUgaXMsCiAgICAjIGNvbW1hbmQtbGluZS1hcmdzID4gY29uZmln - LmluaSBmaWxlIHZhbHVlcyA+IGRlZmF1bHQgdmFsdWVzCiAgICBkZWYgZ2V0RmluYWxVc2VkQXJn - cyhzZWxmKToKICAgICAgICBhcmd1bWVudCA9IGYiW0NvbmZpZ3VyYXRpb25zXVxuIgogICAgICAg - IGZvciBhcmcgaW4gdmFycyhzZWxmLl9hcmdfcGFyc2VyKToKICAgICAgICAgICAgaWYgc3RyKGdl - dGF0dHIoc2VsZi5fYXJnX3BhcnNlciwgYXJnKSk6CiAgICAgICAgICAgICAgICAjIHB5dGhvbiB0 - cmVhdHMgZmxhZy1uYW1lIGFzIGZsYWdfbmFtZSBpbnRlcm5hbGx5LCBzbyBjb252ZXJ0aW5nIGJh - Y2sgdG8gZmxhZy1uYW1lLAogICAgICAgICAgICAgICAgIyBzbyB3ZSBjYW4gZ2V0IHRob3NlIHZh - bHVlcyBmcm9tIGNvbmZpZyBmaWxlCiAgICAgICAgICAgICAgICBhcmdWYWx1ZSA9IGFyZy5yZXBs - YWNlKCJfIiwgIi0iKQogICAgICAgICAgICAgICAgIyBkbyBub3QgYWRkIHRoZSBjb25maWctZmls - ZSBmbGFnIGFuZCBhbHNvIG5vdCBhZGQgdGhlIGJvb2xlYW4gZmxhZ3Mgd2hpY2ggYXJlIHNldCB0 - byBGYWxzZQogICAgICAgICAgICAgICAgIyBiZWNhdXNlIGNvbmZpZy5pbmkgZmlsZSB0cmVhdHMg - Ym9vbGVhbiBmbGFncyBhcyBUcnVlIGFsd2F5cwogICAgICAgICAgICAgICAgaWYgKAogICAgICAg - ICAgICAgICAgICAgIGFyZ1ZhbHVlICE9ICJjb25maWctZmlsZSIKICAgICAgICAgICAgICAgICAg - ICBhbmQgZ2V0YXR0cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpICE9IEZhbHNlCiAgICAgICAgICAg - ICAgICApOgogICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50ICs9IGYie2FyZ1ZhbHVlfSA9IHtz - dHIoZ2V0YXR0cihzZWxmLl9hcmdfcGFyc2VyLCBhcmcpKX1cbiIKICAgICAgICByZXR1cm4gYXJn - dW1lbnQKCiAgICBkZWYgX2dlbl9vdXRwdXRfbWFwKHNlbGYpOgogICAgICAgIGlmIHNlbGYub3V0 - X21hcDoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgIyBzdXBwb3J0IGxlZ2FjeSBmbGFnIHdp - dGggdXBncmFkZXMKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmNsdXN0ZXJfbmFtZToKICAg - ICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3Bh - cnNlci5jbHVzdGVyX25hbWUKICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25h - bWUgPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZS5sb3dl - cigpCiAgICAgICAgKSAgIyBhbHdheXMgY29udmVydCBjbHVzdGVyIG5hbWUgdG8gbG93ZXJjYXNl - IGNoYXJhY3RlcnMKICAgICAgICBzZWxmLnZhbGlkYXRlX3JiZF9wb29sKHNlbGYuX2FyZ19wYXJz - ZXIucmJkX2RhdGFfcG9vbF9uYW1lKQogICAgICAgIHNlbGYuaW5pdF9yYmRfcG9vbChzZWxmLl9h - cmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZSkKICAgICAgICBzZWxmLnZhbGlkYXRlX3JhZG9z - X25hbWVzcGFjZSgpCiAgICAgICAgc2VsZi5fZXhjbHVkZWRfa2V5cy5hZGQoIks4U19DTFVTVEVS - X05BTUUiKQogICAgICAgIHNlbGYuZ2V0X2NlcGhmc19kYXRhX3Bvb2xfZGV0YWlscygpCiAgICAg - ICAgIyBkb3VibGUgc3RyaW5nIG5lZWRlZCBmb3IgdXBzdHJlYW0gZXhwb3J0cyBvZiBmbGFncwog - ICAgICAgIHNlbGYub3V0X21hcFsiQVJHUyJdID0gZicie3NlbGYuZ2V0RmluYWxVc2VkQXJncygp - fSInCiAgICAgICAgc2VsZi5vdXRfbWFwWyJOQU1FU1BBQ0UiXSA9IHNlbGYuX2FyZ19wYXJzZXIu - bmFtZXNwYWNlCiAgICAgICAgc2VsZi5vdXRfbWFwWyJLOFNfQ0xVU1RFUl9OQU1FIl0gPSBzZWxm - Ll9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tf - RVhURVJOQUxfRlNJRCJdID0gc2VsZi5nZXRfZnNpZCgpCiAgICAgICAgc2VsZi5vdXRfbWFwWyJS - T09LX0VYVEVSTkFMX1VTRVJOQU1FIl0gPSBzZWxmLnJ1bl9hc191c2VyCiAgICAgICAgc2VsZi5v - dXRfbWFwWyJST09LX0VYVEVSTkFMX0NFUEhfTU9OX0RBVEEiXSA9IHNlbGYuZ2V0X2NlcGhfZXh0 - ZXJuYWxfbW9uX2RhdGEoKQogICAgICAgIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5BTF9VU0VS - X1NFQ1JFVCJdID0gc2VsZi5jcmVhdGVfY2hlY2tlcktleSgKICAgICAgICAgICAgImNsaWVudC5o - ZWFsdGhjaGVja2VyIgogICAgICAgICkKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJO - QUxfREFTSEJPQVJEX0xJTksiXSA9IHNlbGYuZ2V0X2NlcGhfZGFzaGJvYXJkX2xpbmsoKQogICAg - ICAgICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX05PREVfU0VDUkVUIl0sCiAg - ICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FIl0sCiAgICAg - ICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNsaWVudC5jc2ktcmJkLW5v - ZGUiKQogICAgICAgICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lP - TkVSX1NFQ1JFVCJdLAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9SQkRfUFJPVklTSU9O - RVJfU0VDUkVUX05BTUUiXSwKICAgICAgICApID0gc2VsZi5jcmVhdGVfY2VwaENTSUtleXJpbmdf - dXNlcigiY2xpZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiKQogICAgICAgIHNlbGYub3V0X21hcFsi - Q0VQSEZTX1BPT0xfTkFNRSJdID0gc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25h - bWUKICAgICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19NRVRBREFUQV9QT09MX05BTUUiXSA9ICgK - ICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfbWV0YWRhdGFfcG9vbF9uYW1lCiAg - ICAgICAgKQogICAgICAgIHNlbGYub3V0X21hcFsiQ0VQSEZTX0ZTX05BTUUiXSA9IHNlbGYuX2Fy - Z19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZQogICAgICAgIHNlbGYub3V0X21hcFsiUkVT - VFJJQ1RFRF9BVVRIX1BFUk1JU1NJT04iXSA9ICgKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl - ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbgogICAgICAgICkKICAgICAgICBzZWxmLm91dF9t - YXBbIlJBRE9TX05BTUVTUEFDRSJdID0gc2VsZi5fYXJnX3BhcnNlci5yYWRvc19uYW1lc3BhY2UK - ICAgICAgICBzZWxmLm91dF9tYXBbIlNVQlZPTFVNRV9HUk9VUCJdID0gc2VsZi5fYXJnX3BhcnNl - ci5zdWJ2b2x1bWVfZ3JvdXAKICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9T - RUNSRVQiXSA9ICIiCiAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVS - X1NFQ1JFVCJdID0gIiIKICAgICAgICAjIGNyZWF0ZSBDZXBoRlMgbm9kZSBhbmQgcHJvdmlzaW9u - ZXIga2V5cmluZyBvbmx5IHdoZW4gTURTIGV4aXN0cwogICAgICAgIGlmIHNlbGYub3V0X21hcFsi - Q0VQSEZTX0ZTX05BTUUiXSBhbmQgc2VsZi5vdXRfbWFwWyJDRVBIRlNfUE9PTF9OQU1FIl06CiAg - ICAgICAgICAgICgKICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RF - X1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVf - U0VDUkVUX05BTUUiXSwKICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5n - X3VzZXIoImNsaWVudC5jc2ktY2VwaGZzLW5vZGUiKQogICAgICAgICAgICAoCiAgICAgICAgICAg - ICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUIl0sCiAgICAg - ICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05B - TUUiXSwKICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNs - aWVudC5jc2ktY2VwaGZzLXByb3Zpc2lvbmVyIikKICAgICAgICAgICAgIyBjcmVhdGUgdGhlIGRl - ZmF1bHQgImNzaSIgc3Vidm9sdW1lZ3JvdXAKICAgICAgICAgICAgc2VsZi5nZXRfb3JfY3JlYXRl - X3N1YnZvbHVtZV9ncm91cCgKICAgICAgICAgICAgICAgICJjc2kiLCBzZWxmLl9hcmdfcGFyc2Vy - LmNlcGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICAgICAgKQogICAgICAgICAgICAjIHBpbiB0 - aGUgZGVmYXVsdCAiY3NpIiBzdWJ2b2x1bWVncm91cAogICAgICAgICAgICBzZWxmLnBpbl9zdWJ2 - b2x1bWUoCiAgICAgICAgICAgICAgICAiY3NpIiwgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls - ZXN5c3RlbV9uYW1lLCAiZGlzdHJpYnV0ZWQiLCAiMSIKICAgICAgICAgICAgKQogICAgICAgICAg - ICBpZiBzZWxmLm91dF9tYXBbIlNVQlZPTFVNRV9HUk9VUCJdOgogICAgICAgICAgICAgICAgc2Vs - Zi5nZXRfb3JfY3JlYXRlX3N1YnZvbHVtZV9ncm91cCgKICAgICAgICAgICAgICAgICAgICBzZWxm - Ll9hcmdfcGFyc2VyLnN1YnZvbHVtZV9ncm91cCwKICAgICAgICAgICAgICAgICAgICBzZWxmLl9h - cmdfcGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgICAgICApCiAgICAg - ICAgICAgICAgICBzZWxmLnBpbl9zdWJ2b2x1bWUoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5f - YXJnX3BhcnNlci5zdWJ2b2x1bWVfZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJn - X3BhcnNlci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lLAogICAgICAgICAgICAgICAgICAgICJkaXN0 - cmlidXRlZCIsCiAgICAgICAgICAgICAgICAgICAgIjEiLAogICAgICAgICAgICAgICAgKQogICAg - ICAgIHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl0gPSAiIgogICAgICAgIHNlbGYub3V0X21h - cFsiTU9OSVRPUklOR19FTkRQT0lOVCJdID0gIiIKICAgICAgICBzZWxmLm91dF9tYXBbIk1PTklU - T1JJTkdfRU5EUE9JTlRfUE9SVCJdID0gIiIKICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNl - ci5za2lwX21vbml0b3JpbmdfZW5kcG9pbnQ6CiAgICAgICAgICAgICgKICAgICAgICAgICAgICAg - IHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVCJdLAogICAgICAgICAgICAgICAgc2Vs - Zi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UX1BPUlQiXSwKICAgICAgICAgICAgKSA9IHNl - bGYuZ2V0X2FjdGl2ZV9hbmRfc3RhbmRieV9tZ3JzKCkKICAgICAgICBzZWxmLm91dF9tYXBbIlJC - RF9QT09MX05BTUUiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAg - ICAgc2VsZi5vdXRfbWFwWyJSQkRfTUVUQURBVEFfRUNfUE9PTF9OQU1FIl0gPSAoCiAgICAgICAg - ICAgIHNlbGYudmFsaWRhdGVfcmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZSgpCiAgICAgICAgKQog - ICAgICAgIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfUE9PTFMiXSA9IHNlbGYuX2FyZ19wYXJzZXIu - dG9wb2xvZ3lfcG9vbHMKICAgICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9N - QUlOX0xBQkVMIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFp - bHVyZV9kb21haW5fbGFiZWwKICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9H - WV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXSA9ICgKICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl - ci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMKICAgICAgICApCiAgICAgICAgaWYgKAog - ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bvb2xzICE9ICIiCiAgICAgICAg - ICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX2xhYmVsICE9 - ICIiCiAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9t - YWluX3ZhbHVlcyAhPSAiIgogICAgICAgICk6CiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfdG9w - b2xvZ3lfdmFsdWVzKAogICAgICAgICAgICAgICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFyYXRl - ZF90b19hcnJheShzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0pLAogICAgICAgICAgICAg - ICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFyYXRlZF90b19hcnJheSgKICAgICAgICAgICAgICAg - ICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlOX1ZBTFVFUyJdCiAgICAg - ICAgICAgICAgICApLAogICAgICAgICAgICApCiAgICAgICAgICAgIHNlbGYudmFsaWRhdGVfdG9w - b2xvZ3lfcmJkX3Bvb2xzKAogICAgICAgICAgICAgICAgc2VsZi5jb252ZXJ0X2NvbW1hX3NlcGFy - YXRlZF90b19hcnJheShzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0pCiAgICAgICAgICAg - ICkKICAgICAgICAgICAgc2VsZi5pbml0X3RvcG9sb2d5X3JiZF9wb29scygKICAgICAgICAgICAg - ICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoc2VsZi5vdXRfbWFwWyJU - T1BPTE9HWV9QT09MUyJdKQogICAgICAgICAgICApCiAgICAgICAgZWxzZToKICAgICAgICAgICAg - c2VsZi5yYWlzZV9leGNlcHRpb25faWZfYW55X3RvcG9sb2d5X2ZsYWdfaXNfbWlzc2luZygpCgog - ICAgICAgIHNlbGYub3V0X21hcFsiUkdXX1BPT0xfUFJFRklYIl0gPSBzZWxmLl9hcmdfcGFyc2Vy - LnJnd19wb29sX3ByZWZpeAogICAgICAgIHNlbGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl0gPSAi - IgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50OgogICAgICAgICAgICBp - ZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgICAgICBzZWxmLmNyZWF0ZV9y - Z3dfYWRtaW5fb3BzX3VzZXIoKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgaWYg + IGNlcGhmcyAqPSoiLAogICAgICAgICAgICAibWRzIjogImFsbG93IHJ3IiwKICAgICAgICB9CiAg + ICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAg + ICAgICAgICAgazhzX2NsdXN0ZXJfbmFtZSA9IHNlbGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJf + bmFtZQogICAgICAgICAgICBpZiBrOHNfY2x1c3Rlcl9uYW1lID09ICIiOgogICAgICAgICAgICAg + ICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAi + azhzX2NsdXN0ZXJfbmFtZSBub3QgZm91bmQsIHBsZWFzZSBzZXQgdGhlICctLWs4cy1jbHVzdGVy + LW5hbWUnIGZsYWciCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGNlcGhmc19maWxlc3lz + dGVtID0gc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmlsZXN5c3RlbV9uYW1lCiAgICAgICAgICAg + IGlmIGNlcGhmc19maWxlc3lzdGVtID09ICIiOgogICAgICAgICAgICAgICAgZW50aXR5ID0gZiJ7 + ZW50aXR5fS17azhzX2NsdXN0ZXJfbmFtZX0iCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAg + ICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1c3Rlcl9uYW1lfS17Y2VwaGZzX2ZpbGVz + eXN0ZW19IgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSBmImFsbG93IHJ3IHRhZyBjZXBo + ZnMgKj17Y2VwaGZzX2ZpbGVzeXN0ZW19IgoKICAgICAgICByZXR1cm4gY2FwcywgZW50aXR5Cgog + ICAgZGVmIGdldF9lbnRpdHkoCiAgICAgICAgc2VsZiwKICAgICAgICBlbnRpdHksCiAgICAgICAg + cmJkX3Bvb2xfbmFtZSwKICAgICAgICBhbGlhc19yYmRfcG9vbF9uYW1lLAogICAgICAgIGs4c19j + bHVzdGVyX25hbWUsCiAgICAgICAgcmFkb3NfbmFtZXNwYWNlLAogICAgKToKICAgICAgICBpZiAo + CiAgICAgICAgICAgIHJiZF9wb29sX25hbWUuY291bnQoIi4iKSAhPSAwCiAgICAgICAgICAgIG9y + IHJiZF9wb29sX25hbWUuY291bnQoIl8iKSAhPSAwCiAgICAgICAgICAgIG9yIGFsaWFzX3JiZF9w + b29sX25hbWUgIT0gIiIKICAgICAgICAgICAgIyBjaGVja2luZyBhbGlhc19yYmRfcG9vbF9uYW1l + IGlzIG5vdCBlbXB0eSBhcyB0aGVyZSBtYXliZSBhIHNwZWNpYWwgY2hhcmFjdGVyIHVzZWQgb3Ro + ZXIgdGhhbiAuIG9yIF8KICAgICAgICApOgogICAgICAgICAgICBpZiBhbGlhc19yYmRfcG9vbF9u + YW1lID09ICIiOgogICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv + bigKICAgICAgICAgICAgICAgICAgICAicGxlYXNlIHNldCB0aGUgJy0tYWxpYXMtcmJkLWRhdGEt + cG9vbC1uYW1lJyBmbGFnIGFzIHRoZSByYmQgZGF0YSBwb29sIG5hbWUgY29udGFpbnMgJy4nIG9y + ICdfJyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAg + YWxpYXNfcmJkX3Bvb2xfbmFtZS5jb3VudCgiLiIpICE9IDAKICAgICAgICAgICAgICAgIG9yIGFs + aWFzX3JiZF9wb29sX25hbWUuY291bnQoIl8iKSAhPSAwCiAgICAgICAgICAgICk6CiAgICAgICAg + ICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAg + ICAgICInLS1hbGlhcy1yYmQtZGF0YS1wb29sLW5hbWUnIGZsYWcgdmFsdWUgc2hvdWxkIG5vdCBj + b250YWluICcuJyBvciAnXyciCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVudGl0eSA9 + IGYie2VudGl0eX0te2s4c19jbHVzdGVyX25hbWV9LXthbGlhc19yYmRfcG9vbF9uYW1lfSIKICAg + ICAgICBlbHNlOgogICAgICAgICAgICBlbnRpdHkgPSBmIntlbnRpdHl9LXtrOHNfY2x1c3Rlcl9u + YW1lfS17cmJkX3Bvb2xfbmFtZX0iCgogICAgICAgIGlmIHJhZG9zX25hbWVzcGFjZToKICAgICAg + ICAgICAgZW50aXR5ID0gZiJ7ZW50aXR5fS17cmFkb3NfbmFtZXNwYWNlfSIKICAgICAgICByZXR1 + cm4gZW50aXR5CgogICAgZGVmIGdldF9yYmRfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KHNl + bGYpOgogICAgICAgIGVudGl0eSA9ICJjbGllbnQuY3NpLXJiZC1wcm92aXNpb25lciIKICAgICAg + ICBjYXBzID0gewogICAgICAgICAgICAibW9uIjogInByb2ZpbGUgcmJkLCBhbGxvdyBjb21tYW5k + ICdvc2QgYmxvY2tsaXN0JyIsCiAgICAgICAgICAgICJtZ3IiOiAiYWxsb3cgcnciLAogICAgICAg + ICAgICAib3NkIjogInByb2ZpbGUgcmJkIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJn + X3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgcmJkX3Bvb2xf + bmFtZSA9IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGFs + aWFzX3JiZF9wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLmFsaWFzX3JiZF9kYXRhX3Bvb2xf + bmFtZQogICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNf + Y2x1c3Rlcl9uYW1lCiAgICAgICAgICAgIHJhZG9zX25hbWVzcGFjZSA9IHNlbGYuX2FyZ19wYXJz + ZXIucmFkb3NfbmFtZXNwYWNlCiAgICAgICAgICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAg + ICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAg + ICAgICAgICAgICJtYW5kYXRvcnkgZmxhZyBub3QgZm91bmQsIHBsZWFzZSBzZXQgdGhlICctLXJi + ZC1kYXRhLXBvb2wtbmFtZScgZmxhZyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYg + azhzX2NsdXN0ZXJfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBmbGFnIG5vdCBm + b3VuZCwgcGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAgICAgICAg + ICAgICAgICkKICAgICAgICAgICAgZW50aXR5ID0gc2VsZi5nZXRfZW50aXR5KAogICAgICAgICAg + ICAgICAgZW50aXR5LAogICAgICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSwKICAgICAgICAgICAg + ICAgIGFsaWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1l + LAogICAgICAgICAgICAgICAgcmFkb3NfbmFtZXNwYWNlLAogICAgICAgICAgICApCiAgICAgICAg + ICAgIGlmIHJhZG9zX25hbWVzcGFjZSAhPSAiIjoKICAgICAgICAgICAgICAgIGNhcHNbIm9zZCJd + ID0gKAogICAgICAgICAgICAgICAgICAgIGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFt + ZX0gbmFtZXNwYWNlPXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgICAgICAgICAgKQogICAgICAg + ICAgICBlbHNlOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSBmInByb2ZpbGUgcmJkIHBv + b2w9e3JiZF9wb29sX25hbWV9IgoKICAgICAgICByZXR1cm4gY2FwcywgZW50aXR5CgogICAgZGVm + IGdldF9yYmRfbm9kZV9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50aXR5ID0gImNs + aWVudC5jc2ktcmJkLW5vZGUiCiAgICAgICAgY2FwcyA9IHsKICAgICAgICAgICAgIm1vbiI6ICJw + cm9maWxlIHJiZCwgYWxsb3cgY29tbWFuZCAnb3NkIGJsb2NrbGlzdCciLAogICAgICAgICAgICAi + b3NkIjogInByb2ZpbGUgcmJkIiwKICAgICAgICB9CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNl + ci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbjoKICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSA9 + IHNlbGYuX2FyZ19wYXJzZXIucmJkX2RhdGFfcG9vbF9uYW1lCiAgICAgICAgICAgIGFsaWFzX3Ji + ZF9wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFyc2VyLmFsaWFzX3JiZF9kYXRhX3Bvb2xfbmFtZQog + ICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1lID0gc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rl + cl9uYW1lCiAgICAgICAgICAgIHJhZG9zX25hbWVzcGFjZSA9IHNlbGYuX2FyZ19wYXJzZXIucmFk + b3NfbmFtZXNwYWNlCiAgICAgICAgICAgIGlmIHJiZF9wb29sX25hbWUgPT0gIiI6CiAgICAgICAg + ICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAg + ICAgICJtYW5kYXRvcnkgZmxhZyBub3QgZm91bmQsIHBsZWFzZSBzZXQgdGhlICctLXJiZC1kYXRh + LXBvb2wtbmFtZScgZmxhZyIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgazhzX2Ns + dXN0ZXJfbmFtZSA9PSAiIjoKICAgICAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVF + eGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgIm1hbmRhdG9yeSBmbGFnIG5vdCBmb3VuZCwg + cGxlYXNlIHNldCB0aGUgJy0tazhzLWNsdXN0ZXItbmFtZScgZmxhZyIKICAgICAgICAgICAgICAg + ICkKICAgICAgICAgICAgZW50aXR5ID0gc2VsZi5nZXRfZW50aXR5KAogICAgICAgICAgICAgICAg + ZW50aXR5LAogICAgICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSwKICAgICAgICAgICAgICAgIGFs + aWFzX3JiZF9wb29sX25hbWUsCiAgICAgICAgICAgICAgICBrOHNfY2x1c3Rlcl9uYW1lLAogICAg + ICAgICAgICAgICAgcmFkb3NfbmFtZXNwYWNlLAogICAgICAgICAgICApCiAgICAgICAgICAgIGlm + IHJhZG9zX25hbWVzcGFjZSAhPSAiIjoKICAgICAgICAgICAgICAgIGNhcHNbIm9zZCJdID0gKAog + ICAgICAgICAgICAgICAgICAgIGYicHJvZmlsZSByYmQgcG9vbD17cmJkX3Bvb2xfbmFtZX0gbmFt + ZXNwYWNlPXtyYWRvc19uYW1lc3BhY2V9IgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBl + bHNlOgogICAgICAgICAgICAgICAgY2Fwc1sib3NkIl0gPSBmInByb2ZpbGUgcmJkIHBvb2w9e3Ji + ZF9wb29sX25hbWV9IgoKICAgICAgICByZXR1cm4gY2FwcywgZW50aXR5CgogICAgZGVmIGdldF9k + ZWZhdWx0VXNlcl9jYXBzX2FuZF9lbnRpdHkoc2VsZik6CiAgICAgICAgZW50aXR5ID0gc2VsZi5y + dW5fYXNfdXNlcgogICAgICAgIGNhcHMgPSB7CiAgICAgICAgICAgICJtb24iOiAiYWxsb3cgciwg + YWxsb3cgY29tbWFuZCBxdW9ydW1fc3RhdHVzLCBhbGxvdyBjb21tYW5kIHZlcnNpb24iLAogICAg + ICAgICAgICAibWdyIjogImFsbG93IGNvbW1hbmQgY29uZmlnIiwKICAgICAgICAgICAgIm9zZCI6 + IGYicHJvZmlsZSByYmQtcmVhZC1vbmx5LCBhbGxvdyByd3ggcG9vbD17c2VsZi5fYXJnX3BhcnNl + ci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5tZXRhLCBhbGxvdyByIHBvb2w9LnJndy5yb290LCBhbGxv + dyBydyBwb29sPXtzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmNvbnRyb2ws + IGFsbG93IHJ4IHBvb2w9e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cubG9n + LCBhbGxvdyB4IHBvb2w9e3NlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJlZml4fS5yZ3cuYnVj + a2V0cy5pbmRleCIsCiAgICAgICAgICAgICJtZHMiOiAiYWxsb3cgKiIsCiAgICAgICAgfQoKICAg + ICAgICByZXR1cm4gY2FwcywgZW50aXR5CgogICAgZGVmIGdldF9jYXBzX2FuZF9lbnRpdHkoc2Vs + ZiwgdXNlcl9uYW1lKToKICAgICAgICBpZiAiY2xpZW50LmNzaS1jZXBoZnMtcHJvdmlzaW9uZXIi + IGluIHVzZXJfbmFtZToKICAgICAgICAgICAgaWYgImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv + bmVyIiAhPSB1c2VyX25hbWU6CiAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJlc3Ry + aWN0ZWRfYXV0aF9wZXJtaXNzaW9uID0gVHJ1ZQogICAgICAgICAgICByZXR1cm4gc2VsZi5nZXRf + Y2VwaGZzX3Byb3Zpc2lvbmVyX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAgaWYgImNsaWVudC5j + c2ktY2VwaGZzLW5vZGUiIGluIHVzZXJfbmFtZToKICAgICAgICAgICAgaWYgImNsaWVudC5jc2kt + Y2VwaGZzLW5vZGUiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJz + ZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAgIHJldHVybiBz + ZWxmLmdldF9jZXBoZnNfbm9kZV9jYXBzX2FuZF9lbnRpdHkoKQogICAgICAgIGlmICJjbGllbnQu + Y3NpLXJiZC1wcm92aXNpb25lciIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAiY2xpZW50 + LmNzaS1yYmQtcHJvdmlzaW9uZXIiICE9IHVzZXJfbmFtZToKICAgICAgICAgICAgICAgIHNlbGYu + X2FyZ19wYXJzZXIucmVzdHJpY3RlZF9hdXRoX3Blcm1pc3Npb24gPSBUcnVlCiAgICAgICAgICAg + IHJldHVybiBzZWxmLmdldF9yYmRfcHJvdmlzaW9uZXJfY2Fwc19hbmRfZW50aXR5KCkKICAgICAg + ICBpZiAiY2xpZW50LmNzaS1yYmQtbm9kZSIgaW4gdXNlcl9uYW1lOgogICAgICAgICAgICBpZiAi + Y2xpZW50LmNzaS1yYmQtbm9kZSIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2VsZi5f + YXJnX3BhcnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAgICAg + cmV0dXJuIHNlbGYuZ2V0X3JiZF9ub2RlX2NhcHNfYW5kX2VudGl0eSgpCiAgICAgICAgaWYgImNs + aWVudC5oZWFsdGhjaGVja2VyIiBpbiB1c2VyX25hbWU6CiAgICAgICAgICAgIGlmICJjbGllbnQu + aGVhbHRoY2hlY2tlciIgIT0gdXNlcl9uYW1lOgogICAgICAgICAgICAgICAgc2VsZi5fYXJnX3Bh + cnNlci5yZXN0cmljdGVkX2F1dGhfcGVybWlzc2lvbiA9IFRydWUKICAgICAgICAgICAgcmV0dXJu + IHNlbGYuZ2V0X2RlZmF1bHRVc2VyX2NhcHNfYW5kX2VudGl0eSgpCgogICAgICAgIHJhaXNlIEV4 + ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgIGYibm8gdXNlciBmb3VuZCB3aXRo + IHVzZXJfbmFtZToge3VzZXJfbmFtZX0sICIKICAgICAgICAgICAgImdldF9jYXBzX2FuZF9lbnRp + dHkgY29tbWFuZCBmYWlsZWQuXG4iCiAgICAgICAgKQoKICAgIGRlZiBjcmVhdGVfY2VwaENTSUtl + eXJpbmdfdXNlcihzZWxmLCB1c2VyKToKICAgICAgICAiIiIKICAgICAgICBjb21tYW5kOiBjZXBo + IGF1dGggZ2V0LW9yLWNyZWF0ZSBjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciBtb24gJ2Fs + bG93IHInIG1nciAnYWxsb3cgcncnIG9zZCAnYWxsb3cgcncgdGFnIGNlcGhmcyBtZXRhZGF0YT0q + JwogICAgICAgICIiIgogICAgICAgIGNhcHMsIGVudGl0eSA9IHNlbGYuZ2V0X2NhcHNfYW5kX2Vu + dGl0eSh1c2VyKQogICAgICAgIGNtZF9qc29uID0gewogICAgICAgICAgICAicHJlZml4IjogImF1 + dGggZ2V0LW9yLWNyZWF0ZSIsCiAgICAgICAgICAgICJlbnRpdHkiOiBlbnRpdHksCiAgICAgICAg + ICAgICJjYXBzIjogW2NhcCBmb3IgY2FwX2xpc3QgaW4gbGlzdChjYXBzLml0ZW1zKCkpIGZvciBj + YXAgaW4gY2FwX2xpc3RdLAogICAgICAgICAgICAiZm9ybWF0IjogImpzb24iLAogICAgICAgIH0K + CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4g + KAogICAgICAgICAgICAgICAgc2VsZi5kcnlfcnVuKAogICAgICAgICAgICAgICAgICAgICJjZXBo + ICIKICAgICAgICAgICAgICAgICAgICArIGNtZF9qc29uWyJwcmVmaXgiXQogICAgICAgICAgICAg + ICAgICAgICsgIiAiCiAgICAgICAgICAgICAgICAgICAgKyBjbWRfanNvblsiZW50aXR5Il0KICAg + ICAgICAgICAgICAgICAgICArICIgIgogICAgICAgICAgICAgICAgICAgICsgIiAiLmpvaW4oY21k + X2pzb25bImNhcHMiXSkKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAiIiwKICAg + ICAgICAgICAgKQogICAgICAgICMgY2hlY2sgaWYgdXNlciBhbHJlYWR5IGV4aXN0CiAgICAgICAg + dXNlcl9rZXkgPSBzZWxmLmNoZWNrX3VzZXJfZXhpc3QoZW50aXR5KQogICAgICAgIGlmIHVzZXJf + a2V5ICE9ICIiOgogICAgICAgICAgICByZXR1cm4gdXNlcl9rZXksIGYie2VudGl0eS5zcGxpdCgn + LicsIDEpWzFdfSIKICAgICAgICAgICAgIyBlbnRpdHkuc3BsaXQoJy4nLDEpWzFdIHRvIHJlbmFt + ZSBlbnRpdHkoY2xpZW50LmNzaS1yYmQtbm9kZSkgYXMgY3NpLXJiZC1ub2RlCgogICAgICAgIHJl + dF92YWwsIGpzb25fb3V0LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRf + anNvbikKICAgICAgICAjIGlmIHRoZXJlIGlzIGFuIHVuc3VjY2Vzc2Z1bCBhdHRlbXB0LAogICAg + ICAgIGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHJh + aXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRpb24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGdl + dC1vci1jcmVhdGUge3VzZXJ9JyBjb21tYW5kIGZhaWxlZC5cbiIKICAgICAgICAgICAgICAgIGYi + RXJyb3I6IHtlcnJfbXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJ + U1R9IgogICAgICAgICAgICApCiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0p + LCBmIntlbnRpdHkuc3BsaXQoJy4nLCAxKVsxXX0iCiAgICAgICAgIyBlbnRpdHkuc3BsaXQoJy4n + LDEpWzFdIHRvIHJlbmFtZSBlbnRpdHkoY2xpZW50LmNzaS1yYmQtbm9kZSkgYXMgY3NpLXJiZC1u + b2RlCgogICAgZGVmIGdldF9jZXBoZnNfZGF0YV9wb29sX2RldGFpbHMoc2VsZik6CiAgICAgICAg + Y21kX2pzb24gPSB7InByZWZpeCI6ICJmcyBscyIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAg + aWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICByZXR1cm4gc2VsZi5kcnlf + cnVuKCJjZXBoICIgKyBjbWRfanNvblsicHJlZml4Il0pCiAgICAgICAgcmV0X3ZhbCwganNvbl9v + dXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAg + ICMgaWYgdGhlcmUgaXMgYW4gdW5zdWNjZXNzZnVsIGF0dGVtcHQsIHJlcG9ydCBhbiBlcnJvcgog + ICAgICAgIGlmIHJldF92YWwgIT0gMDoKICAgICAgICAgICAgIyBpZiBmcyBhbmQgZGF0YV9wb29s + IGFyZ3VtZW50cyBhcmUgbm90IHNldCwgc2lsZW50bHkgcmV0dXJuCiAgICAgICAgICAgIGlmICgK + ICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFtZSA9 + PSAiIgogICAgICAgICAgICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9v + bF9uYW1lID09ICIiCiAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICByZXR1cm4KICAgICAg + ICAgICAgIyBpZiB1c2VyIGhhcyBwcm92aWRlZCBhbnkgb2YgdGhlCiAgICAgICAgICAgICMgJy0t + Y2VwaGZzLWZpbGVzeXN0ZW0tbmFtZScgb3IgJy0tY2VwaGZzLWRhdGEtcG9vbC1uYW1lJyBhcmd1 + bWVudHMsCiAgICAgICAgICAgICMgcmFpc2UgYW4gZXhjZXB0aW9uIGFzIHdlIGFyZSB1bmFibGUg + dG8gdmVyaWZ5IHRoZSBhcmdzCiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNl + cHRpb24oCiAgICAgICAgICAgICAgICBmIidmcyBscycgY2VwaCBjYWxsIGZhaWxlZCB3aXRoIGVy + cm9yOiB7ZXJyX21zZ30iCiAgICAgICAgICAgICkKCiAgICAgICAgbWF0Y2hpbmdfanNvbl9vdXQg + PSB7fQogICAgICAgICMgaWYgJy0tY2VwaGZzLWZpbGVzeXN0ZW0tbmFtZScgYXJndW1lbnQgaXMg + cHJvdmlkZWQsCiAgICAgICAgIyBjaGVjayB3aGV0aGVyIHRoZSBwcm92aWRlZCBmaWxlc3lzdGVt + LW5hbWUgZXhpc3RzIG9yIG5vdAogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2Zp + bGVzeXN0ZW1fbmFtZToKICAgICAgICAgICAgIyBnZXQgdGhlIG1hdGNoaW5nIGxpc3QKICAgICAg + ICAgICAgbWF0Y2hpbmdfanNvbl9vdXRfbGlzdCA9IFsKICAgICAgICAgICAgICAgIG1hdGNoZWQK + ICAgICAgICAgICAgICAgIGZvciBtYXRjaGVkIGluIGpzb25fb3V0CiAgICAgICAgICAgICAgICBp + ZiBzdHIobWF0Y2hlZFsibmFtZSJdKSA9PSBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19maWxlc3lz + dGVtX25hbWUKICAgICAgICAgICAgXQogICAgICAgICAgICAjIHVuYWJsZSB0byBmaW5kIGEgbWF0 + Y2hpbmcgZnMtbmFtZSwgcmFpc2UgYW4gZXJyb3IKICAgICAgICAgICAgaWYgbGVuKG1hdGNoaW5n + X2pzb25fb3V0X2xpc3QpID09IDA6CiAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWls + dXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgICAgIGYiRmlsZXN5c3RlbSBwcm92aWRlZCwg + J3tzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19maWxlc3lzdGVtX25hbWV9JywgIgogICAgICAgICAg + ICAgICAgICAgIGYiaXMgbm90IGZvdW5kIGluIHRoZSBmcy1saXN0OiB7W3N0cih4WyduYW1lJ10p + IGZvciB4IGluIGpzb25fb3V0XX0iCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIG1hdGNo + aW5nX2pzb25fb3V0ID0gbWF0Y2hpbmdfanNvbl9vdXRfbGlzdFswXQogICAgICAgICMgaWYgY2Vw + aGZzIGZpbGVzeXN0ZW0gbmFtZSBpcyBub3QgcHJvdmlkZWQsCiAgICAgICAgIyB0cnkgdG8gZ2V0 + IGEgZGVmYXVsdCBmcyBuYW1lIGJ5IGRvaW5nIHRoZSBmb2xsb3dpbmcKICAgICAgICBlbHNlOgog + ICAgICAgICAgICAjIGEuIGNoZWNrIGlmIHRoZXJlIGlzIG9ubHkgb25lIGZpbGVzeXN0ZW0gaXMg + cHJlc2VudAogICAgICAgICAgICBpZiBsZW4oanNvbl9vdXQpID09IDE6CiAgICAgICAgICAgICAg + ICBtYXRjaGluZ19qc29uX291dCA9IGpzb25fb3V0WzBdCiAgICAgICAgICAgICMgYi4gb3IgZWxz + ZSwgY2hlY2sgaWYgZGF0YV9wb29sIG5hbWUgaXMgcHJvdmlkZWQKICAgICAgICAgICAgZWxpZiBz + ZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFtZToKICAgICAgICAgICAgICAgICMg + YW5kIGlmIHByZXNlbnQsIGNoZWNrIHdoZXRoZXIgdGhlcmUgZXhpc3RzIGEgZnMgd2hpY2ggaGFz + IHRoZSBkYXRhX3Bvb2wKICAgICAgICAgICAgICAgIGZvciBlYWNoSiBpbiBqc29uX291dDoKICAg + ICAgICAgICAgICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmNlcGhmc19kYXRhX3Bvb2xfbmFt + ZSBpbiBlYWNoSlsiZGF0YV9wb29scyJdOgogICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGlu + Z19qc29uX291dCA9IGVhY2hKCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAg + ICAgICAgICAjIGlmIHRoZXJlIGlzIG5vIG1hdGNoaW5nIGZzIGV4aXN0cywgdGhhdCBtZWFucyBw + cm92aWRlZCBkYXRhX3Bvb2wgbmFtZSBpcyBpbnZhbGlkCiAgICAgICAgICAgICAgICBpZiBub3Qg + bWF0Y2hpbmdfanNvbl9vdXQ6CiAgICAgICAgICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFp + bHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICAgICAgZiJQcm92aWRlZCBkYXRhX3Bv + b2wgbmFtZSwge3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lfSwiCiAgICAg + ICAgICAgICAgICAgICAgICAgICIgZG9lcyBub3QgZXhpc3RzIgogICAgICAgICAgICAgICAgICAg + ICkKICAgICAgICAgICAgIyBjLiBpZiBub3RoaW5nIGlzIHNldCBhbmQgY291bGRuJ3QgZmluZCBh + IGRlZmF1bHQsCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAjIGp1c3QgcmV0dXJu + IHNpbGVudGx5CiAgICAgICAgICAgICAgICByZXR1cm4KCiAgICAgICAgaWYgbWF0Y2hpbmdfanNv + bl9vdXQ6CiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFt + ZSA9IHN0cihtYXRjaGluZ19qc29uX291dFsibmFtZSJdKQogICAgICAgICAgICBzZWxmLl9hcmdf + cGFyc2VyLmNlcGhmc19tZXRhZGF0YV9wb29sX25hbWUgPSBzdHIoCiAgICAgICAgICAgICAgICBt + YXRjaGluZ19qc29uX291dFsibWV0YWRhdGFfcG9vbCJdCiAgICAgICAgICAgICkKCiAgICAgICAg + aWYgaXNpbnN0YW5jZShtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdLCBsaXN0KToKICAg + ICAgICAgICAgIyBpZiB0aGUgdXNlciBoYXMgYWxyZWFkeSBwcm92aWRlZCBkYXRhLXBvb2wtbmFt + ZSwKICAgICAgICAgICAgIyB0aHJvdWdoIC0tY2VwaGZzLWRhdGEtcG9vbC1uYW1lCiAgICAgICAg + ICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lOgogICAgICAgICAg + ICAgICAgIyBpZiB0aGUgcHJvdmlkZWQgbmFtZSBpcyBub3QgbWF0Y2hpbmcgd2l0aCB0aGUgb25l + IGluIHRoZSBsaXN0CiAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICAgc2Vs + Zi5fYXJnX3BhcnNlci5jZXBoZnNfZGF0YV9wb29sX25hbWUKICAgICAgICAgICAgICAgICAgICBu + b3QgaW4gbWF0Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXQogICAgICAgICAgICAgICAgKToK + ICAgICAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAg + ICAgICAgICAgICAgICAgICAgICBmIlByb3ZpZGVkIGRhdGEtcG9vbC1uYW1lOiAne3NlbGYuX2Fy + Z19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lfScsICIKICAgICAgICAgICAgICAgICAgICAg + ICAgImRvZXNuJ3QgbWF0Y2ggZnJvbSB0aGUgZGF0YS1wb29scyBsaXN0OiAiCiAgICAgICAgICAg + ICAgICAgICAgICAgIGYie1tzdHIoeCkgZm9yIHggaW4gbWF0Y2hpbmdfanNvbl9vdXRbJ2RhdGFf + cG9vbHMnXV19IgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIyBpZiBkYXRhX3Bv + b2wgbmFtZSBpcyBub3QgcHJvdmlkZWQsCiAgICAgICAgICAgICMgdGhlbiB0cnkgdG8gZmluZCBh + IGRlZmF1bHQgZGF0YSBwb29sIG5hbWUKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAg + ICMgaWYgbm8gZGF0YV9wb29scyBleGlzdCwgc2lsZW50bHkgcmV0dXJuCiAgICAgICAgICAgICAg + ICBpZiBsZW4obWF0Y2hpbmdfanNvbl9vdXRbImRhdGFfcG9vbHMiXSkgPT0gMDoKICAgICAgICAg + ICAgICAgICAgICByZXR1cm4KICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZz + X2RhdGFfcG9vbF9uYW1lID0gc3RyKAogICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nX2pzb25f + b3V0WyJkYXRhX3Bvb2xzIl1bMF0KICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIyBpZiB0 + aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSAnZGF0YV9wb29scycgZXhpc3QsCiAgICAgICAgICAgICMg + dGhlbiB3YXJuIHRoZSB1c2VyIHRoYXQgd2UgYXJlIHVzaW5nIHRoZSBzZWxlY3RlZCBuYW1lCiAg + ICAgICAgICAgIGlmIGxlbihtYXRjaGluZ19qc29uX291dFsiZGF0YV9wb29scyJdKSA+IDE6CiAg + ICAgICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgICAgICAiV0FSTklORzogTXVsdGlw + bGUgZGF0YSBwb29scyBkZXRlY3RlZDogIgogICAgICAgICAgICAgICAgICAgIGYie1tzdHIoeCkg + Zm9yIHggaW4gbWF0Y2hpbmdfanNvbl9vdXRbJ2RhdGFfcG9vbHMnXV19XG4iCiAgICAgICAgICAg + ICAgICAgICAgZiJVc2luZyB0aGUgZGF0YS1wb29sOiAne3NlbGYuX2FyZ19wYXJzZXIuY2VwaGZz + X2RhdGFfcG9vbF9uYW1lfSdcbiIKICAgICAgICAgICAgICAgICkKCiAgICBkZWYgY3JlYXRlX2No + ZWNrZXJLZXkoc2VsZiwgdXNlcik6CiAgICAgICAgY2FwcywgZW50aXR5ID0gc2VsZi5nZXRfY2Fw + c19hbmRfZW50aXR5KHVzZXIpCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJwcmVm + aXgiOiAiYXV0aCBnZXQtb3ItY3JlYXRlIiwKICAgICAgICAgICAgImVudGl0eSI6IGVudGl0eSwK + ICAgICAgICAgICAgImNhcHMiOiBbY2FwIGZvciBjYXBfbGlzdCBpbiBsaXN0KGNhcHMuaXRlbXMo + KSkgZm9yIGNhcCBpbiBjYXBfbGlzdF0sCiAgICAgICAgICAgICJmb3JtYXQiOiAianNvbiIsCiAg + ICAgICAgfQoKICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAg + IHJldHVybiBzZWxmLmRyeV9ydW4oCiAgICAgICAgICAgICAgICAiY2VwaCAiCiAgICAgICAgICAg + ICAgICArIGNtZF9qc29uWyJwcmVmaXgiXQogICAgICAgICAgICAgICAgKyAiICIKICAgICAgICAg + ICAgICAgICsgY21kX2pzb25bImVudGl0eSJdCiAgICAgICAgICAgICAgICArICIgIgogICAgICAg + ICAgICAgICAgKyAiICIuam9pbihjbWRfanNvblsiY2FwcyJdKQogICAgICAgICAgICApCiAgICAg + ICAgIyBjaGVjayBpZiB1c2VyIGFscmVhZHkgZXhpc3QKICAgICAgICB1c2VyX2tleSA9IHNlbGYu + Y2hlY2tfdXNlcl9leGlzdChlbnRpdHkpCiAgICAgICAgaWYgdXNlcl9rZXkgIT0gIiI6CiAgICAg + ICAgICAgIHJldHVybiB1c2VyX2tleQoKICAgICAgICByZXRfdmFsLCBqc29uX291dCwgZXJyX21z + ZyA9IHNlbGYuX2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgIyBpZiB0aGVy + ZSBpcyBhbiB1bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwKICAgICAgICBpZiByZXRfdmFsICE9IDAgb3Ig + bGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj + ZXB0aW9uKAogICAgICAgICAgICAgICAgZiInYXV0aCBnZXQtb3ItY3JlYXRlIHtzZWxmLnJ1bl9h + c191c2VyfScgY29tbWFuZCBmYWlsZWRcbiIKICAgICAgICAgICAgICAgIGYiRXJyb3I6IHtlcnJf + bXNnIGlmIHJldF92YWwgIT0gMCBlbHNlIHNlbGYuRU1QVFlfT1VUUFVUX0xJU1R9IgogICAgICAg + ICAgICApCiAgICAgICAgcmV0dXJuIHN0cihqc29uX291dFswXVsia2V5Il0pCgogICAgZGVmIGdl + dF9jZXBoX2Rhc2hib2FyZF9saW5rKHNlbGYpOgogICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgi + OiAibWdyIHNlcnZpY2VzIiwgImZvcm1hdCI6ICJqc29uIn0KICAgICAgICBpZiBzZWxmLl9hcmdf + cGFyc2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiBzZWxmLmRyeV9ydW4oImNlcGggIiAr + IGNtZF9qc29uWyJwcmVmaXgiXSkKICAgICAgICByZXRfdmFsLCBqc29uX291dCwgXyA9IHNlbGYu + X2NvbW1vbl9jbWRfanNvbl9nZW4oY21kX2pzb24pCiAgICAgICAgIyBpZiB0aGVyZSBpcyBhbiB1 + bnN1Y2Nlc3NmdWwgYXR0ZW1wdCwKICAgICAgICBpZiByZXRfdmFsICE9IDAgb3IgbGVuKGpzb25f + b3V0KSA9PSAwOgogICAgICAgICAgICByZXR1cm4gTm9uZQogICAgICAgIGlmICJkYXNoYm9hcmQi + IG5vdCBpbiBqc29uX291dDoKICAgICAgICAgICAgcmV0dXJuIE5vbmUKICAgICAgICByZXR1cm4g + anNvbl9vdXRbImRhc2hib2FyZCJdCgogICAgZGVmIGNyZWF0ZV9yZ3dfYWRtaW5fb3BzX3VzZXIo + c2VsZik6CiAgICAgICAgY21kID0gWwogICAgICAgICAgICAicmFkb3Nndy1hZG1pbiIsCiAgICAg + ICAgICAgICJ1c2VyIiwKICAgICAgICAgICAgImNyZWF0ZSIsCiAgICAgICAgICAgICItLXVpZCIs + CiAgICAgICAgICAgIHNlbGYuRVhURVJOQUxfUkdXX0FETUlOX09QU19VU0VSX05BTUUsCiAgICAg + ICAgICAgICItLWRpc3BsYXktbmFtZSIsCiAgICAgICAgICAgICJSb29rIFJHVyBBZG1pbiBPcHMg + dXNlciIsCiAgICAgICAgICAgICItLWNhcHMiLAogICAgICAgICAgICAiYnVja2V0cz0qO3VzZXJz + PSo7dXNhZ2U9cmVhZDttZXRhZGF0YT1yZWFkO3pvbmU9cmVhZCIsCiAgICAgICAgICAgICItLXJn + dy1yZWFsbSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUsCiAg + ICAgICAgICAgICItLXJndy16b25lZ3JvdXAiLAogICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2Vy + LnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmUiLAogICAgICAgICAg + ICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lX25hbWUsCiAgICAgICAgXQogICAgICAgIGlmIHNl + bGYuX2FyZ19wYXJzZXIuZHJ5X3J1bjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuZHJ5X3J1bigi + Y2VwaCAiICsgIiAiLmpvaW4oY21kKSkKICAgICAgICB0cnk6CiAgICAgICAgICAgIG91dHB1dCA9 + IHN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAg + ICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhlY0VycjoKICAg + ICAgICAgICAgIyBpZiB0aGUgdXNlciBhbHJlYWR5IGV4aXN0cywgd2UganVzdCBxdWVyeSBpdAog + ICAgICAgICAgICBpZiBleGVjRXJyLnJldHVybmNvZGUgPT0gZXJybm8uRUVYSVNUOgogICAgICAg + ICAgICAgICAgY21kID0gWwogICAgICAgICAgICAgICAgICAgICJyYWRvc2d3LWFkbWluIiwKICAg + ICAgICAgICAgICAgICAgICAidXNlciIsCiAgICAgICAgICAgICAgICAgICAgImluZm8iLAogICAg + ICAgICAgICAgICAgICAgICItLXVpZCIsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5FWFRFUk5B + TF9SR1dfQURNSU5fT1BTX1VTRVJfTkFNRSwKICAgICAgICAgICAgICAgICAgICAiLS1yZ3ctcmVh + bG0iLAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUs + CiAgICAgICAgICAgICAgICAgICAgIi0tcmd3LXpvbmVncm91cCIsCiAgICAgICAgICAgICAgICAg + ICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfem9uZWdyb3VwX25hbWUsCiAgICAgICAgICAgICAgICAg + ICAgIi0tcmd3LXpvbmUiLAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3 + X3pvbmVfbmFtZSwKICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICAgIHRyeToKICAgICAg + ICAgICAgICAgICAgICBvdXRwdXQgPSBzdWJwcm9jZXNzLmNoZWNrX291dHB1dChjbWQsIHN0ZGVy + cj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgICAgICAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxs + ZWRQcm9jZXNzRXJyb3IgYXMgZXhlY0VycjoKICAgICAgICAgICAgICAgICAgICBlcnJfbXNnID0g + KAogICAgICAgICAgICAgICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRlIGNvbW1hbmQge2Nt + ZH0uIE91dHB1dDoge2V4ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAgICAgICAgICAgICBm + IkNvZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3RkZXJyfSIKICAg + ICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShl + cnJfbXNnKQogICAgICAgICAgICAgICAgICAgIHJldHVybiBOb25lLCBOb25lLCBGYWxzZSwgIi0x + IgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZXJyX21zZyA9ICgKICAgICAgICAg + ICAgICAgICAgICBmImZhaWxlZCB0byBleGVjdXRlIGNvbW1hbmQge2NtZH0uIE91dHB1dDoge2V4 + ZWNFcnIub3V0cHV0fS4gIgogICAgICAgICAgICAgICAgICAgIGYiQ29kZToge2V4ZWNFcnIucmV0 + dXJuY29kZX0uIEVycm9yOiB7ZXhlY0Vyci5zdGRlcnJ9IgogICAgICAgICAgICAgICAgKQogICAg + ICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShlcnJfbXNnKQogICAgICAgICAgICAgICAgcmV0 + dXJuIE5vbmUsIE5vbmUsIEZhbHNlLCAiLTEiCgogICAgICAgICMgc2VwYXJhdGVseSBhZGQgaW5m + bz1yZWFkIGNhcHMgZm9yIHJndy1lbmRwb2ludCBpcCB2YWxpZGF0aW9uCiAgICAgICAgaW5mb19j + YXBfc3VwcG9ydGVkID0gVHJ1ZQogICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgInJhZG9zZ3ct + YWRtaW4iLAogICAgICAgICAgICAiY2FwcyIsCiAgICAgICAgICAgICJhZGQiLAogICAgICAgICAg + ICAiLS11aWQiLAogICAgICAgICAgICBzZWxmLkVYVEVSTkFMX1JHV19BRE1JTl9PUFNfVVNFUl9O + QU1FLAogICAgICAgICAgICAiLS1jYXBzIiwKICAgICAgICAgICAgImluZm89cmVhZCIsCiAgICAg + ICAgICAgICItLXJndy1yZWFsbSIsCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Jl + YWxtX25hbWUsCiAgICAgICAgICAgICItLXJndy16b25lZ3JvdXAiLAogICAgICAgICAgICBzZWxm + Ll9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwKICAgICAgICAgICAgIi0tcmd3LXpvbmUi + LAogICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lX25hbWUsCiAgICAgICAgXQog + ICAgICAgIHRyeToKICAgICAgICAgICAgb3V0cHV0ID0gc3VicHJvY2Vzcy5jaGVja19vdXRwdXQo + Y21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9jZXNzLkNh + bGxlZFByb2Nlc3NFcnJvciBhcyBleGVjRXJyOgogICAgICAgICAgICAjIGlmIHRoZSBjZXBoIHZl + cnNpb24gbm90IHN1cHBvcnRlZCBmb3IgYWRkaW5nIGBpbmZvPXJlYWRgIGNhcChyZ3dfdmFsaWRh + dGlvbikKICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAgImNvdWxkIG5vdCBhZGQgY2Fw + czogdW5hYmxlIHRvIGFkZCBjYXBzOiBpbmZvPXJlYWRcbiIKICAgICAgICAgICAgICAgIGluIGV4 + ZWNFcnIuc3RkZXJyLmRlY29kZSgidXRmLTgiKQogICAgICAgICAgICAgICAgYW5kIGV4ZWNFcnIu + cmV0dXJuY29kZSA9PSAyNDQKICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgIGluZm9fY2Fw + X3N1cHBvcnRlZCA9IEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBlcnJf + bXNnID0gKAogICAgICAgICAgICAgICAgICAgIGYiZmFpbGVkIHRvIGV4ZWN1dGUgY29tbWFuZCB7 + Y21kfS4gT3V0cHV0OiB7ZXhlY0Vyci5vdXRwdXR9LiAiCiAgICAgICAgICAgICAgICAgICAgZiJD + b2RlOiB7ZXhlY0Vyci5yZXR1cm5jb2RlfS4gRXJyb3I6IHtleGVjRXJyLnN0ZGVycn0iCiAgICAg + ICAgICAgICAgICApCiAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycl9tc2cpCiAg + ICAgICAgICAgICAgICByZXR1cm4gTm9uZSwgTm9uZSwgRmFsc2UsICItMSIKCiAgICAgICAganNv + bm91dHB1dCA9IGpzb24ubG9hZHMob3V0cHV0KQogICAgICAgIHJldHVybiAoCiAgICAgICAgICAg + IGpzb25vdXRwdXRbImtleXMiXVswXVsiYWNjZXNzX2tleSJdLAogICAgICAgICAgICBqc29ub3V0 + cHV0WyJrZXlzIl1bMF1bInNlY3JldF9rZXkiXSwKICAgICAgICAgICAgaW5mb19jYXBfc3VwcG9y + dGVkLAogICAgICAgICAgICAiIiwKICAgICAgICApCgogICAgZGVmIHZhbGlkYXRlX3JiZF9wb29s + KHNlbGYsIHBvb2xfbmFtZSk6CiAgICAgICAgaWYgbm90IHNlbGYuY2x1c3Rlci5wb29sX2V4aXN0 + cyhwb29sX25hbWUpOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9u + KAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcG9vbCwgJ3twb29sX25hbWV9JywgZG9l + cyBub3QgZXhpc3QiCiAgICAgICAgICAgICkKCiAgICBkZWYgaW5pdF9yYmRfcG9vbChzZWxmLCBy + YmRfcG9vbF9uYW1lKToKICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVtbXlS + YWRvcyk6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGlvY3R4ID0gc2VsZi5jbHVzdGVyLm9w + ZW5faW9jdHgocmJkX3Bvb2xfbmFtZSkKICAgICAgICByYmRfaW5zdCA9IHJiZC5SQkQoKQogICAg + ICAgIHJiZF9pbnN0LnBvb2xfaW5pdChpb2N0eCwgVHJ1ZSkKCiAgICBkZWYgdmFsaWRhdGVfcmFk + b3NfbmFtZXNwYWNlKHNlbGYpOgogICAgICAgIHJiZF9wb29sX25hbWUgPSBzZWxmLl9hcmdfcGFy + c2VyLnJiZF9kYXRhX3Bvb2xfbmFtZQogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmJkX21l + dGFkYXRhX2VjX3Bvb2xfbmFtZToKICAgICAgICAgICAgcmJkX3Bvb2xfbmFtZSA9IHNlbGYuX2Fy + Z19wYXJzZXIucmJkX21ldGFkYXRhX2VjX3Bvb2xfbmFtZQogICAgICAgIHJhZG9zX25hbWVzcGFj + ZSA9IHNlbGYuX2FyZ19wYXJzZXIucmFkb3NfbmFtZXNwYWNlCiAgICAgICAgaWYgcmFkb3NfbmFt + ZXNwYWNlID09ICIiOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiByYWRvc19uYW1lc3Bh + Y2UuaXNsb3dlcigpID09IEZhbHNlOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJl + RXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmFkb3MgTmFtZXNwYWNl + LCAne3JhZG9zX25hbWVzcGFjZX0nLCAiCiAgICAgICAgICAgICAgICBmImNvbnRhaW5zIHVwcGVy + IGNhc2UiCiAgICAgICAgICAgICkKICAgICAgICByYmRfaW5zdCA9IHJiZC5SQkQoKQogICAgICAg + IGlvY3R4ID0gc2VsZi5jbHVzdGVyLm9wZW5faW9jdHgocmJkX3Bvb2xfbmFtZSkKICAgICAgICBp + ZiByYmRfaW5zdC5uYW1lc3BhY2VfZXhpc3RzKGlvY3R4LCByYWRvc19uYW1lc3BhY2UpIGlzIEZh + bHNlOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg + ICAgICAgICAgZiJUaGUgcHJvdmlkZWQgcmFkb3MgTmFtZXNwYWNlLCAne3JhZG9zX25hbWVzcGFj + ZX0nLCAiCiAgICAgICAgICAgICAgICBmImlzIG5vdCBmb3VuZCBpbiB0aGUgcG9vbCAne3JiZF9w + b29sX25hbWV9JyIKICAgICAgICAgICAgKQoKICAgIGRlZiBnZXRfb3JfY3JlYXRlX3N1YnZvbHVt + ZV9ncm91cChzZWxmLCBzdWJ2b2x1bWVfZ3JvdXAsIGNlcGhmc19maWxlc3lzdGVtX25hbWUpOgog + ICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgImNlcGgiLAogICAgICAgICAgICAiZnMiLAogICAg + ICAgICAgICAic3Vidm9sdW1lZ3JvdXAiLAogICAgICAgICAgICAiZ2V0cGF0aCIsCiAgICAgICAg + ICAgIGNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgIHN1YnZvbHVtZV9ncm91cCwK + ICAgICAgICBdCiAgICAgICAgdHJ5OgogICAgICAgICAgICBfID0gc3VicHJvY2Vzcy5jaGVja19v + dXRwdXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAgICAgIGV4Y2VwdCBzdWJwcm9j + ZXNzLkNhbGxlZFByb2Nlc3NFcnJvcjoKICAgICAgICAgICAgY21kID0gWwogICAgICAgICAgICAg + ICAgImNlcGgiLAogICAgICAgICAgICAgICAgImZzIiwKICAgICAgICAgICAgICAgICJzdWJ2b2x1 + bWVncm91cCIsCiAgICAgICAgICAgICAgICAiY3JlYXRlIiwKICAgICAgICAgICAgICAgIGNlcGhm + c19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgICAgICBzdWJ2b2x1bWVfZ3JvdXAsCiAgICAg + ICAgICAgIF0KICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgXyA9IHN1YnByb2Nlc3Mu + Y2hlY2tfb3V0cHV0KGNtZCwgc3RkZXJyPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICAgICAgZXhj + ZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICAgICAgcmFpc2Ug + RXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAgICBmInN1YnZvbHVt + ZSBncm91cCB7c3Vidm9sdW1lX2dyb3VwfSBpcyBub3QgYWJsZSB0byBnZXQgY3JlYXRlZCIKICAg + ICAgICAgICAgICAgICkKCiAgICBkZWYgcGluX3N1YnZvbHVtZSgKICAgICAgICBzZWxmLCBzdWJ2 + b2x1bWVfZ3JvdXAsIGNlcGhmc19maWxlc3lzdGVtX25hbWUsIHBpbl90eXBlLCBwaW5fc2V0dGlu + ZwogICAgKToKICAgICAgICBjbWQgPSBbCiAgICAgICAgICAgICJjZXBoIiwKICAgICAgICAgICAg + ImZzIiwKICAgICAgICAgICAgInN1YnZvbHVtZWdyb3VwIiwKICAgICAgICAgICAgInBpbiIsCiAg + ICAgICAgICAgIGNlcGhmc19maWxlc3lzdGVtX25hbWUsCiAgICAgICAgICAgIHN1YnZvbHVtZV9n + cm91cCwKICAgICAgICAgICAgcGluX3R5cGUsCiAgICAgICAgICAgIHBpbl9zZXR0aW5nLAogICAg + ICAgIF0KICAgICAgICB0cnk6CiAgICAgICAgICAgIF8gPSBzdWJwcm9jZXNzLmNoZWNrX291dHB1 + dChjbWQsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpCiAgICAgICAgZXhjZXB0IHN1YnByb2Nlc3Mu + Q2FsbGVkUHJvY2Vzc0Vycm9yOgogICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhj + ZXB0aW9uKAogICAgICAgICAgICAgICAgZiJzdWJ2b2x1bWUgZ3JvdXAge3N1YnZvbHVtZV9ncm91 + cH0gaXMgbm90IGFibGUgdG8gZ2V0IHBpbm5lZCIKICAgICAgICAgICAgKQoKICAgIGRlZiBnZXRf + cmd3X2ZzaWQoc2VsZiwgYmFzZV91cmwsIHZlcmlmeSk6CiAgICAgICAgYWNjZXNzX2tleSA9IHNl + bGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX0FDQ0VTU19LRVkiXQogICAgICAgIHNlY3Jl + dF9rZXkgPSBzZWxmLm91dF9tYXBbIlJHV19BRE1JTl9PUFNfVVNFUl9TRUNSRVRfS0VZIl0KICAg + ICAgICByZ3dfZW5kcG9pbnQgPSBzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludAogICAgICAg + IGJhc2VfdXJsID0gYmFzZV91cmwgKyAiOi8vIiArIHJnd19lbmRwb2ludCArICIvYWRtaW4vaW5m + bz8iCiAgICAgICAgcGFyYW1zID0geyJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmVxdWVzdF91 + cmwgPSBiYXNlX3VybCArIHVybGVuY29kZShwYXJhbXMpCgogICAgICAgIHRyeToKICAgICAgICAg + ICAgciA9IHJlcXVlc3RzLmdldCgKICAgICAgICAgICAgICAgIHJlcXVlc3RfdXJsLAogICAgICAg + ICAgICAgICAgYXV0aD1TM0F1dGgoYWNjZXNzX2tleSwgc2VjcmV0X2tleSwgcmd3X2VuZHBvaW50 + KSwKICAgICAgICAgICAgICAgIHZlcmlmeT12ZXJpZnksCiAgICAgICAgICAgICkKICAgICAgICBl + eGNlcHQgcmVxdWVzdHMuZXhjZXB0aW9ucy5UaW1lb3V0OgogICAgICAgICAgICBzeXMuc3RkZXJy + LndyaXRlKAogICAgICAgICAgICAgICAgZiJpbnZhbGlkIGVuZHBvaW50Oiwgbm90IGFibGUgdG8g + Y2FsbCBhZG1pbi1vcHMgYXBpe3Jnd19lbmRwb2ludH0iCiAgICAgICAgICAgICkKICAgICAgICAg + ICAgcmV0dXJuICIiLCAiLTEiCiAgICAgICAgcjEgPSByLmpzb24oKQogICAgICAgIGlmIHIxIGlz + IE5vbmUgb3IgcjEuZ2V0KCJpbmZvIikgaXMgTm9uZToKICAgICAgICAgICAgc3lzLnN0ZGVyci53 + cml0ZSgKICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHJndyBFbmRwb2ludCwgJ3tzZWxm + Ll9hcmdfcGFyc2VyLnJnd19lbmRwb2ludH0nLCBpcyBpbnZhbGlkLiIKICAgICAgICAgICAgKQog + ICAgICAgICAgICByZXR1cm4gKAogICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAi + LTEiLAogICAgICAgICAgICApCgogICAgICAgIHJldHVybiByMVsiaW5mbyJdWyJzdG9yYWdlX2Jh + Y2tlbmRzIl1bMF1bImNsdXN0ZXJfaWQiXSwgIiIKCiAgICBkZWYgdmFsaWRhdGVfcmd3X2VuZHBv + aW50KHNlbGYsIGluZm9fY2FwX3N1cHBvcnRlZCk6CiAgICAgICAgIyBpZiB0aGUgJ2NsdXN0ZXIn + IGluc3RhbmNlIGlzIGEgZHVtbXkgb25lLAogICAgICAgICMgZG9uJ3QgdHJ5IHRvIHJlYWNoIG91 + dCB0byB0aGUgZW5kcG9pbnQKICAgICAgICBpZiBpc2luc3RhbmNlKHNlbGYuY2x1c3RlciwgRHVt + bXlSYWRvcyk6CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICByZ3dfZW5kcG9pbnQgPSBzZWxm + Ll9hcmdfcGFyc2VyLnJnd19lbmRwb2ludAoKICAgICAgICAjIHZhbGlkYXRlIHJndyBlbmRwb2lu + dCBvbmx5IGlmIGlwIGFkZHJlc3MgaXMgcGFzc2VkCiAgICAgICAgaXBfdHlwZSA9IHNlbGYuX2lu + dmFsaWRfZW5kcG9pbnQocmd3X2VuZHBvaW50KQoKICAgICAgICAjIGNoZWNrIGlmIHRoZSByZ3cg + ZW5kcG9pbnQgaXMgcmVhY2hhYmxlCiAgICAgICAgY2VydCA9IE5vbmUKICAgICAgICBpZiBub3Qg + c2VsZi5fYXJnX3BhcnNlci5yZ3dfc2tpcF90bHMgYW5kIHNlbGYudmFsaWRhdGVfcmd3X2VuZHBv + aW50X3Rsc19jZXJ0KCk6CiAgICAgICAgICAgIGNlcnQgPSBzZWxmLl9hcmdfcGFyc2VyLnJnd190 + bHNfY2VydF9wYXRoCiAgICAgICAgYmFzZV91cmwsIHZlcmlmeSwgZXJyID0gc2VsZi5lbmRwb2lu + dF9kaWFsKHJnd19lbmRwb2ludCwgaXBfdHlwZSwgY2VydD1jZXJ0KQogICAgICAgIGlmIGVyciAh + PSAiIjoKICAgICAgICAgICAgcmV0dXJuICItMSIKCiAgICAgICAgIyBjaGVjayBpZiB0aGUgcmd3 + IGVuZHBvaW50IGJlbG9uZ3MgdG8gdGhlIHNhbWUgY2x1c3RlcgogICAgICAgICMgb25seSBjaGVj + ayBpZiBgaW5mb2AgY2FwIGlzIHN1cHBvcnRlZAogICAgICAgIGlmIGluZm9fY2FwX3N1cHBvcnRl + ZDoKICAgICAgICAgICAgZnNpZCA9IHNlbGYuZ2V0X2ZzaWQoKQogICAgICAgICAgICByZ3dfZnNp + ZCwgZXJyID0gc2VsZi5nZXRfcmd3X2ZzaWQoYmFzZV91cmwsIHZlcmlmeSkKICAgICAgICAgICAg + aWYgZXJyID09ICItMSI6CiAgICAgICAgICAgICAgICByZXR1cm4gIi0xIgogICAgICAgICAgICBp + ZiBmc2lkICE9IHJnd19mc2lkOgogICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZSgKICAg + ICAgICAgICAgICAgICAgICBmIlRoZSBwcm92aWRlZCByZ3cgRW5kcG9pbnQsICd7c2VsZi5fYXJn + X3BhcnNlci5yZ3dfZW5kcG9pbnR9JywgaXMgaW52YWxpZC4gV2UgYXJlIHZhbGlkYXRpbmcgYnkg + Y2FsbGluZyB0aGUgYWRtaW5vcHMgYXBpIHRocm91Z2ggcmd3LWVuZHBvaW50IGFuZCB2YWxpZGF0 + aW5nIHRoZSBjbHVzdGVyX2lkICd7cmd3X2ZzaWR9JyBpcyBlcXVhbCB0byB0aGUgY2VwaCBjbHVz + dGVyIGZzaWQgJ3tmc2lkfSciCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICByZXR1 + cm4gIi0xIgoKICAgICAgICAjIGNoZWNrIGlmIHRoZSByZ3cgZW5kcG9pbnQgcG9vbCBleGlzdAog + ICAgICAgICMgb25seSB2YWxpZGF0ZSBpZiByZ3dfcG9vbF9wcmVmaXggaXMgcGFzc2VkIGVsc2Ug + aXQgd2lsbCB0YWtlIGRlZmF1bHQgdmFsdWUgYW5kIHdlIGRvbid0IGNyZWF0ZSB0aGVzZSBkZWZh + dWx0IHBvb2xzCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXggIT0g + ImRlZmF1bHQiOgogICAgICAgICAgICByZ3dfcG9vbHNfdG9fdmFsaWRhdGUgPSBbCiAgICAgICAg + ICAgICAgICBmIntzZWxmLl9hcmdfcGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3Lm1ldGEiLAog + ICAgICAgICAgICAgICAgIi5yZ3cucm9vdCIsCiAgICAgICAgICAgICAgICBmIntzZWxmLl9hcmdf + cGFyc2VyLnJnd19wb29sX3ByZWZpeH0ucmd3LmNvbnRyb2wiLAogICAgICAgICAgICAgICAgZiJ7 + c2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9wcmVmaXh9LnJndy5sb2ciLAogICAgICAgICAgICBd + CiAgICAgICAgICAgIGZvciBfcmd3X3Bvb2xfdG9fdmFsaWRhdGUgaW4gcmd3X3Bvb2xzX3RvX3Zh + bGlkYXRlOgogICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuY2x1c3Rlci5wb29sX2V4aXN0cyhf + cmd3X3Bvb2xfdG9fdmFsaWRhdGUpOgogICAgICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3Jp + dGUoCiAgICAgICAgICAgICAgICAgICAgICAgIGYiVGhlIHByb3ZpZGVkIHBvb2wsICd7X3Jnd19w + b29sX3RvX3ZhbGlkYXRlfScsIGRvZXMgbm90IGV4aXN0IgogICAgICAgICAgICAgICAgICAgICkK + ICAgICAgICAgICAgICAgICAgICByZXR1cm4gIi0xIgoKICAgICAgICByZXR1cm4gIiIKCiAgICBk + ZWYgdmFsaWRhdGVfcmd3X211bHRpc2l0ZShzZWxmLCByZ3dfbXVsdGlzaXRlX2NvbmZpZ19uYW1l + LCByZ3dfbXVsdGlzaXRlX2NvbmZpZyk6CiAgICAgICAgaWYgcmd3X211bHRpc2l0ZV9jb25maWcg + IT0gIiI6CiAgICAgICAgICAgIGNtZCA9IFsKICAgICAgICAgICAgICAgICJyYWRvc2d3LWFkbWlu + IiwKICAgICAgICAgICAgICAgIHJnd19tdWx0aXNpdGVfY29uZmlnLAogICAgICAgICAgICAgICAg + ImdldCIsCiAgICAgICAgICAgICAgICAiLS1yZ3ctIiArIHJnd19tdWx0aXNpdGVfY29uZmlnLAog + ICAgICAgICAgICAgICAgcmd3X211bHRpc2l0ZV9jb25maWdfbmFtZSwKICAgICAgICAgICAgXQog + ICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBfID0gc3VicHJvY2Vzcy5jaGVja19vdXRw + dXQoY21kLCBzdGRlcnI9c3VicHJvY2Vzcy5QSVBFKQogICAgICAgICAgICBleGNlcHQgc3VicHJv + Y2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhlY0VycjoKICAgICAgICAgICAgICAgIGVycl9t + c2cgPSAoCiAgICAgICAgICAgICAgICAgICAgZiJmYWlsZWQgdG8gZXhlY3V0ZSBjb21tYW5kIHtj + bWR9LiBPdXRwdXQ6IHtleGVjRXJyLm91dHB1dH0uICIKICAgICAgICAgICAgICAgICAgICBmIkNv + ZGU6IHtleGVjRXJyLnJldHVybmNvZGV9LiBFcnJvcjoge2V4ZWNFcnIuc3RkZXJyfSIKICAgICAg + ICAgICAgICAgICkKICAgICAgICAgICAgICAgIHN5cy5zdGRlcnIud3JpdGUoZXJyX21zZykKICAg + ICAgICAgICAgICAgIHJldHVybiAiLTEiCiAgICAgICAgcmV0dXJuICIiCgogICAgZGVmIGNvbnZl + cnRfY29tbWFfc2VwYXJhdGVkX3RvX2FycmF5KHNlbGYsIHZhbHVlKToKICAgICAgICByZXR1cm4g + dmFsdWUuc3BsaXQoIiwiKQoKICAgIGRlZiByYWlzZV9leGNlcHRpb25faWZfYW55X3RvcG9sb2d5 + X2ZsYWdfaXNfbWlzc2luZyhzZWxmKToKICAgICAgICBpZiAoCiAgICAgICAgICAgICgKICAgICAg + ICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lfcG9vbHMgIT0gIiIKICAgICAgICAg + ICAgICAgIGFuZCAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9n + eV9mYWlsdXJlX2RvbWFpbl9sYWJlbCA9PSAiIgogICAgICAgICAgICAgICAgICAgIG9yIHNlbGYu + X2FyZ19wYXJzZXIudG9wb2xvZ3lfZmFpbHVyZV9kb21haW5fdmFsdWVzID09ICIiCiAgICAgICAg + ICAgICAgICApCiAgICAgICAgICAgICkKICAgICAgICAgICAgb3IgKAogICAgICAgICAgICAgICAg + c2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl9sYWJlbCAhPSAiIgogICAg + ICAgICAgICAgICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRv + cG9sb2d5X3Bvb2xzID09ICIiCiAgICAgICAgICAgICAgICAgICAgb3Igc2VsZi5fYXJnX3BhcnNl + ci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMgPT0gIiIKICAgICAgICAgICAgICAgICkK + ICAgICAgICAgICAgKQogICAgICAgICAgICBvciAoCiAgICAgICAgICAgICAgICBzZWxmLl9hcmdf + cGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWluX3ZhbHVlcyAhPSAiIgogICAgICAgICAgICAg + ICAgYW5kICgKICAgICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bv + b2xzID09ICIiCiAgICAgICAgICAgICAgICAgICAgb3Igc2VsZi5fYXJnX3BhcnNlci50b3BvbG9n + eV9mYWlsdXJlX2RvbWFpbl9sYWJlbCA9PSAiIgogICAgICAgICAgICAgICAgKQogICAgICAgICAg + ICApCiAgICAgICAgKToKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlv + bigKICAgICAgICAgICAgICAgICJwcm92aWRlIGFsbCB0aGUgdG9wb2xvZ3kgZmxhZ3MgLS10b3Bv + bG9neS1wb29scywgLS10b3BvbG9neS1mYWlsdXJlLWRvbWFpbi1sYWJlbCwgLS10b3BvbG9neS1m + YWlsdXJlLWRvbWFpbi12YWx1ZXMiCiAgICAgICAgICAgICkKCiAgICBkZWYgdmFsaWRhdGVfdG9w + b2xvZ3lfdmFsdWVzKHNlbGYsIHRvcG9sb2d5X3Bvb2xzLCB0b3BvbG9neV9mZCk6CiAgICAgICAg + aWYgbGVuKHRvcG9sb2d5X3Bvb2xzKSAhPSBsZW4odG9wb2xvZ3lfZmQpOgogICAgICAgICAgICBy + YWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJUaGUgcHJv + dmlkZWQgdG9wb2xvZ3kgcG9vbHMsICd7dG9wb2xvZ3lfcG9vbHN9JywgYW5kICIKICAgICAgICAg + ICAgICAgIGYidG9wb2xvZ3kgZmFpbHVyZSBkb21haW4sICd7dG9wb2xvZ3lfZmR9JywiCiAgICAg + ICAgICAgICAgICBmImFyZSBvZiBkaWZmZXJlbnQgbGVuZ3RoLCAne2xlbih0b3BvbG9neV9wb29s + cyl9JyBhbmQgJ3tsZW4odG9wb2xvZ3lfZmQpfScgcmVzcGN0aXZlbHkiCiAgICAgICAgICAgICkK + ICAgICAgICByZXR1cm4KCiAgICBkZWYgdmFsaWRhdGVfdG9wb2xvZ3lfcmJkX3Bvb2xzKHNlbGYs + IHRvcG9sb2d5X3JiZF9wb29scyk6CiAgICAgICAgZm9yIHBvb2wgaW4gdG9wb2xvZ3lfcmJkX3Bv + b2xzOgogICAgICAgICAgICBzZWxmLnZhbGlkYXRlX3JiZF9wb29sKHBvb2wpCgogICAgZGVmIGlu + aXRfdG9wb2xvZ3lfcmJkX3Bvb2xzKHNlbGYsIHRvcG9sb2d5X3JiZF9wb29scyk6CiAgICAgICAg + Zm9yIHBvb2wgaW4gdG9wb2xvZ3lfcmJkX3Bvb2xzOgogICAgICAgICAgICBzZWxmLmluaXRfcmJk + X3Bvb2wocG9vbCkKCiAgICAjIHRoaXMgd2lsbCByZXR1cm4gdGhlIGZpbmFsIGFyZ3MgdGhhdCBz + Y3JpcHQgdXNlcyB0byBwcm9jZXNzCiAgICAjIHRoZSBwcmlvcml0eSB0byBzZXQgYSBwYXJ0aWN1 + bGFyIHZhbHVlIGlzLAogICAgIyBjb21tYW5kLWxpbmUtYXJncyA+IGNvbmZpZy5pbmkgZmlsZSB2 + YWx1ZXMgPiBkZWZhdWx0IHZhbHVlcwogICAgZGVmIGdldEZpbmFsVXNlZEFyZ3Moc2VsZik6CiAg + ICAgICAgYXJndW1lbnQgPSBmIltDb25maWd1cmF0aW9uc11cbiIKICAgICAgICBmb3IgYXJnIGlu + IHZhcnMoc2VsZi5fYXJnX3BhcnNlcik6CiAgICAgICAgICAgIGlmIHN0cihnZXRhdHRyKHNlbGYu + X2FyZ19wYXJzZXIsIGFyZykpOgogICAgICAgICAgICAgICAgIyBweXRob24gdHJlYXRzIGZsYWct + bmFtZSBhcyBmbGFnX25hbWUgaW50ZXJuYWxseSwgc28gY29udmVydGluZyBiYWNrIHRvIGZsYWct + bmFtZSwKICAgICAgICAgICAgICAgICMgc28gd2UgY2FuIGdldCB0aG9zZSB2YWx1ZXMgZnJvbSBj + b25maWcgZmlsZQogICAgICAgICAgICAgICAgYXJnVmFsdWUgPSBhcmcucmVwbGFjZSgiXyIsICIt + IikKICAgICAgICAgICAgICAgICMgZG8gbm90IGFkZCB0aGUgY29uZmlnLWZpbGUgZmxhZyBhbmQg + YWxzbyBub3QgYWRkIHRoZSBib29sZWFuIGZsYWdzIHdoaWNoIGFyZSBzZXQgdG8gRmFsc2UKICAg + ICAgICAgICAgICAgICMgYmVjYXVzZSBjb25maWcuaW5pIGZpbGUgdHJlYXRzIGJvb2xlYW4gZmxh + Z3MgYXMgVHJ1ZSBhbHdheXMKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAg + ICBhcmdWYWx1ZSAhPSAiY29uZmlnLWZpbGUiCiAgICAgICAgICAgICAgICAgICAgYW5kIGdldGF0 + dHIoc2VsZi5fYXJnX3BhcnNlciwgYXJnKSAhPSBGYWxzZQogICAgICAgICAgICAgICAgKToKICAg + ICAgICAgICAgICAgICAgICBhcmd1bWVudCArPSBmInthcmdWYWx1ZX0gPSB7c3RyKGdldGF0dHIo + c2VsZi5fYXJnX3BhcnNlciwgYXJnKSl9XG4iCiAgICAgICAgcmV0dXJuIGFyZ3VtZW50CgogICAg + ZGVmIF9nZW5fb3V0cHV0X21hcChzZWxmKToKICAgICAgICBpZiBzZWxmLm91dF9tYXA6CiAgICAg + ICAgICAgIHJldHVybgogICAgICAgICMgc3VwcG9ydCBsZWdhY3kgZmxhZyB3aXRoIHVwZ3JhZGVz + CiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5jbHVzdGVyX25hbWU6CiAgICAgICAgICAgIHNl + bGYuX2FyZ19wYXJzZXIuazhzX2NsdXN0ZXJfbmFtZSA9IHNlbGYuX2FyZ19wYXJzZXIuY2x1c3Rl + cl9uYW1lCiAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5rOHNfY2x1c3Rlcl9uYW1lID0gKAogICAg + ICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLms4c19jbHVzdGVyX25hbWUubG93ZXIoKQogICAgICAg + ICkgICMgYWx3YXlzIGNvbnZlcnQgY2x1c3RlciBuYW1lIHRvIGxvd2VyY2FzZSBjaGFyYWN0ZXJz + CiAgICAgICAgc2VsZi52YWxpZGF0ZV9yYmRfcG9vbChzZWxmLl9hcmdfcGFyc2VyLnJiZF9kYXRh + X3Bvb2xfbmFtZSkKICAgICAgICBzZWxmLmluaXRfcmJkX3Bvb2woc2VsZi5fYXJnX3BhcnNlci5y + YmRfZGF0YV9wb29sX25hbWUpCiAgICAgICAgc2VsZi52YWxpZGF0ZV9yYWRvc19uYW1lc3BhY2Uo + KQogICAgICAgIHNlbGYuX2V4Y2x1ZGVkX2tleXMuYWRkKCJLOFNfQ0xVU1RFUl9OQU1FIikKICAg + ICAgICBzZWxmLmdldF9jZXBoZnNfZGF0YV9wb29sX2RldGFpbHMoKQogICAgICAgICMgZG91Ymxl + IHN0cmluZyBuZWVkZWQgZm9yIHVwc3RyZWFtIGV4cG9ydHMgb2YgZmxhZ3MKICAgICAgICBzZWxm + Lm91dF9tYXBbIkFSR1MiXSA9IGYnIntzZWxmLmdldEZpbmFsVXNlZEFyZ3MoKX0iJwogICAgICAg + IHNlbGYub3V0X21hcFsiTkFNRVNQQUNFIl0gPSBzZWxmLl9hcmdfcGFyc2VyLm5hbWVzcGFjZQog + ICAgICAgIHNlbGYub3V0X21hcFsiSzhTX0NMVVNURVJfTkFNRSJdID0gc2VsZi5fYXJnX3BhcnNl + ci5rOHNfY2x1c3Rlcl9uYW1lCiAgICAgICAgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0ZT + SUQiXSA9IHNlbGYuZ2V0X2ZzaWQoKQogICAgICAgIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5B + TF9VU0VSTkFNRSJdID0gc2VsZi5ydW5fYXNfdXNlcgogICAgICAgIHNlbGYub3V0X21hcFsiUk9P + S19FWFRFUk5BTF9DRVBIX01PTl9EQVRBIl0gPSBzZWxmLmdldF9jZXBoX2V4dGVybmFsX21vbl9k + YXRhKCkKICAgICAgICBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfVVNFUl9TRUNSRVQiXSA9 + IHNlbGYuY3JlYXRlX2NoZWNrZXJLZXkoCiAgICAgICAgICAgICJjbGllbnQuaGVhbHRoY2hlY2tl + ciIKICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0RBU0hCT0FS + RF9MSU5LIl0gPSBzZWxmLmdldF9jZXBoX2Rhc2hib2FyZF9saW5rKCkKICAgICAgICAoCiAgICAg + ICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVCJdLAogICAgICAgICAgICBz + ZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSJdLAogICAgICAgICkgPSBzZWxm + LmNyZWF0ZV9jZXBoQ1NJS2V5cmluZ191c2VyKCJjbGllbnQuY3NpLXJiZC1ub2RlIikKICAgICAg + ICAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVQi + XSwKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9O + QU1FIl0sCiAgICAgICAgKSA9IHNlbGYuY3JlYXRlX2NlcGhDU0lLZXlyaW5nX3VzZXIoImNsaWVu + dC5jc2ktcmJkLXByb3Zpc2lvbmVyIikKICAgICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19QT09M + X05BTUUiXSA9IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2RhdGFfcG9vbF9uYW1lCiAgICAgICAg + c2VsZi5vdXRfbWFwWyJDRVBIRlNfTUVUQURBVEFfUE9PTF9OQU1FIl0gPSAoCiAgICAgICAgICAg + IHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX21ldGFkYXRhX3Bvb2xfbmFtZQogICAgICAgICkKICAg + ICAgICBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl0gPSBzZWxmLl9hcmdfcGFyc2VyLmNl + cGhmc19maWxlc3lzdGVtX25hbWUKICAgICAgICBzZWxmLm91dF9tYXBbIlJFU1RSSUNURURfQVVU + SF9QRVJNSVNTSU9OIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmVzdHJpY3Rl + ZF9hdXRoX3Blcm1pc3Npb24KICAgICAgICApCiAgICAgICAgc2VsZi5vdXRfbWFwWyJSQURPU19O + QU1FU1BBQ0UiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmFkb3NfbmFtZXNwYWNlCiAgICAgICAgc2Vs + Zi5vdXRfbWFwWyJTVUJWT0xVTUVfR1JPVVAiXSA9IHNlbGYuX2FyZ19wYXJzZXIuc3Vidm9sdW1l + X2dyb3VwCiAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVfU0VDUkVUIl0gPSAi + IgogICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVQiXSA9 + ICIiCiAgICAgICAgIyBjcmVhdGUgQ2VwaEZTIG5vZGUgYW5kIHByb3Zpc2lvbmVyIGtleXJpbmcg + b25seSB3aGVuIE1EUyBleGlzdHMKICAgICAgICBpZiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19O + QU1FIl0gYW5kIHNlbGYub3V0X21hcFsiQ0VQSEZTX1BPT0xfTkFNRSJdOgogICAgICAgICAgICAo + CiAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9TRUNSRVQiXSwK + ICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1F + Il0sCiAgICAgICAgICAgICkgPSBzZWxmLmNyZWF0ZV9jZXBoQ1NJS2V5cmluZ191c2VyKCJjbGll + bnQuY3NpLWNlcGhmcy1ub2RlIikKICAgICAgICAgICAgKAogICAgICAgICAgICAgICAgc2VsZi5v + dXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAg + c2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FIl0sCiAgICAg + ICAgICAgICkgPSBzZWxmLmNyZWF0ZV9jZXBoQ1NJS2V5cmluZ191c2VyKCJjbGllbnQuY3NpLWNl + cGhmcy1wcm92aXNpb25lciIpCiAgICAgICAgICAgICMgY3JlYXRlIHRoZSBkZWZhdWx0ICJjc2ki + IHN1YnZvbHVtZWdyb3VwCiAgICAgICAgICAgIHNlbGYuZ2V0X29yX2NyZWF0ZV9zdWJ2b2x1bWVf + Z3JvdXAoCiAgICAgICAgICAgICAgICAiY3NpIiwgc2VsZi5fYXJnX3BhcnNlci5jZXBoZnNfZmls + ZXN5c3RlbV9uYW1lCiAgICAgICAgICAgICkKICAgICAgICAgICAgIyBwaW4gdGhlIGRlZmF1bHQg + ImNzaSIgc3Vidm9sdW1lZ3JvdXAKICAgICAgICAgICAgc2VsZi5waW5fc3Vidm9sdW1lKAogICAg + ICAgICAgICAgICAgImNzaSIsIHNlbGYuX2FyZ19wYXJzZXIuY2VwaGZzX2ZpbGVzeXN0ZW1fbmFt + ZSwgImRpc3RyaWJ1dGVkIiwgIjEiCiAgICAgICAgICAgICkKICAgICAgICAgICAgaWYgc2VsZi5v + dXRfbWFwWyJTVUJWT0xVTUVfR1JPVVAiXToKICAgICAgICAgICAgICAgIHNlbGYuZ2V0X29yX2Ny + ZWF0ZV9zdWJ2b2x1bWVfZ3JvdXAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl + ci5zdWJ2b2x1bWVfZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5j + ZXBoZnNfZmlsZXN5c3RlbV9uYW1lLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAg + c2VsZi5waW5fc3Vidm9sdW1lKAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIu + c3Vidm9sdW1lX2dyb3VwLAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIuY2Vw + aGZzX2ZpbGVzeXN0ZW1fbmFtZSwKICAgICAgICAgICAgICAgICAgICAiZGlzdHJpYnV0ZWQiLAog + ICAgICAgICAgICAgICAgICAgICIxIiwKICAgICAgICAgICAgICAgICkKICAgICAgICBzZWxmLm91 + dF9tYXBbIlJHV19UTFNfQ0VSVCJdID0gIiIKICAgICAgICBzZWxmLm91dF9tYXBbIk1PTklUT1JJ + TkdfRU5EUE9JTlQiXSA9ICIiCiAgICAgICAgc2VsZi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBP + SU5UX1BPUlQiXSA9ICIiCiAgICAgICAgaWYgbm90IHNlbGYuX2FyZ19wYXJzZXIuc2tpcF9tb25p + dG9yaW5nX2VuZHBvaW50OgogICAgICAgICAgICAoCiAgICAgICAgICAgICAgICBzZWxmLm91dF9t + YXBbIk1PTklUT1JJTkdfRU5EUE9JTlQiXSwKICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsi + TU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0sCiAgICAgICAgICAgICkgPSBzZWxmLmdldF9hY3Rp + dmVfYW5kX3N0YW5kYnlfbWdycygpCiAgICAgICAgc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1F + Il0gPSBzZWxmLl9hcmdfcGFyc2VyLnJiZF9kYXRhX3Bvb2xfbmFtZQogICAgICAgIHNlbGYub3V0 + X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xfTkFNRSJdID0gKAogICAgICAgICAgICBzZWxmLnZh + bGlkYXRlX3JiZF9tZXRhZGF0YV9lY19wb29sX25hbWUoKQogICAgICAgICkKICAgICAgICBzZWxm + Lm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0gPSBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X3Bv + b2xzCiAgICAgICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9MQUJFTCJd + ID0gKAogICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnRvcG9sb2d5X2ZhaWx1cmVfZG9tYWlu + X2xhYmVsCiAgICAgICAgKQogICAgICAgIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9E + T01BSU5fVkFMVUVTIl0gPSAoCiAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIudG9wb2xvZ3lf + ZmFpbHVyZV9kb21haW5fdmFsdWVzCiAgICAgICAgKQogICAgICAgIGlmICgKICAgICAgICAgICAg + c2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9wb29scyAhPSAiIgogICAgICAgICAgICBhbmQgc2Vs + Zi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl9sYWJlbCAhPSAiIgogICAgICAg + ICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci50b3BvbG9neV9mYWlsdXJlX2RvbWFpbl92YWx1ZXMg + IT0gIiIKICAgICAgICApOgogICAgICAgICAgICBzZWxmLnZhbGlkYXRlX3RvcG9sb2d5X3ZhbHVl + cygKICAgICAgICAgICAgICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXko + c2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdKSwKICAgICAgICAgICAgICAgIHNlbGYuY29u + dmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJyYXkoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5v + dXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXQogICAgICAgICAgICAgICAg + KSwKICAgICAgICAgICAgKQogICAgICAgICAgICBzZWxmLnZhbGlkYXRlX3RvcG9sb2d5X3JiZF9w + b29scygKICAgICAgICAgICAgICAgIHNlbGYuY29udmVydF9jb21tYV9zZXBhcmF0ZWRfdG9fYXJy + YXkoc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdKQogICAgICAgICAgICApCiAgICAgICAg + ICAgIHNlbGYuaW5pdF90b3BvbG9neV9yYmRfcG9vbHMoCiAgICAgICAgICAgICAgICBzZWxmLmNv + bnZlcnRfY29tbWFfc2VwYXJhdGVkX3RvX2FycmF5KHNlbGYub3V0X21hcFsiVE9QT0xPR1lfUE9P + TFMiXSkKICAgICAgICAgICAgKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYucmFpc2Vf + ZXhjZXB0aW9uX2lmX2FueV90b3BvbG9neV9mbGFnX2lzX21pc3NpbmcoKQoKICAgICAgICBzZWxm + Lm91dF9tYXBbIlJHV19QT09MX1BSRUZJWCJdID0gc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9w + cmVmaXgKICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdID0gIiIKICAgICAgICBp + ZiBzZWxmLl9hcmdfcGFyc2VyLnJnd19lbmRwb2ludDoKICAgICAgICAgICAgaWYgc2VsZi5fYXJn + X3BhcnNlci5kcnlfcnVuOgogICAgICAgICAgICAgICAgc2VsZi5jcmVhdGVfcmd3X2FkbWluX29w + c191c2VyKCkKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAg + ICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd19yZWFsbV9uYW1lICE9ICIiCiAgICAgICAg + ICAgICAgICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lICE9ICIi + CiAgICAgICAgICAgICAgICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSAh + PSAiIgogICAgICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgICAgICBlcnIgPSBzZWxmLnZh + bGlkYXRlX3Jnd19tdWx0aXNpdGUoCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19w + YXJzZXIucmd3X3JlYWxtX25hbWUsICJyZWFsbSIKICAgICAgICAgICAgICAgICAgICApCiAgICAg + ICAgICAgICAgICAgICAgZXJyID0gc2VsZi52YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKAogICAgICAg + ICAgICAgICAgICAgICAgICBzZWxmLl9hcmdfcGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSwgInpv + bmVncm91cCIKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgZXJyID0g + c2VsZi52YWxpZGF0ZV9yZ3dfbXVsdGlzaXRlKAogICAgICAgICAgICAgICAgICAgICAgICBzZWxm + Ll9hcmdfcGFyc2VyLnJnd196b25lX25hbWUsICJ6b25lIgogICAgICAgICAgICAgICAgICAgICkK + CiAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNl + ci5yZ3dfcmVhbG1fbmFtZSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdf + cGFyc2VyLnJnd196b25lZ3JvdXBfbmFtZSA9PSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBz + ZWxmLl9hcmdfcGFyc2VyLnJnd196b25lX25hbWUgPT0gIiIKICAgICAgICAgICAgICAgICkgb3Ig KAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3JlYWxtX25hbWUgIT0g IiIKICAgICAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5yZ3dfem9uZWdyb3Vw X25hbWUgIT0gIiIKICAgICAgICAgICAgICAgICAgICBhbmQgc2VsZi5fYXJnX3BhcnNlci5yZ3df - em9uZV9uYW1lICE9ICIiCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgIGVy - ciA9IHNlbGYudmFsaWRhdGVfcmd3X211bHRpc2l0ZSgKICAgICAgICAgICAgICAgICAgICAgICAg - c2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVhbG1fbmFtZSwgInJlYWxtIgogICAgICAgICAgICAgICAg - ICAgICkKICAgICAgICAgICAgICAgICAgICBlcnIgPSBzZWxmLnZhbGlkYXRlX3Jnd19tdWx0aXNp - dGUoCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91 - cF9uYW1lLCAiem9uZWdyb3VwIgogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAg - ICAgICBlcnIgPSBzZWxmLnZhbGlkYXRlX3Jnd19tdWx0aXNpdGUoCiAgICAgICAgICAgICAgICAg - ICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSwgInpvbmUiCiAgICAgICAgICAg - ICAgICAgICAgKQoKICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAgICBzZWxm - Ll9hcmdfcGFyc2VyLnJnd19yZWFsbV9uYW1lID09ICIiCiAgICAgICAgICAgICAgICAgICAgYW5k - IHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVncm91cF9uYW1lID09ICIiCiAgICAgICAgICAgICAg - ICAgICAgYW5kIHNlbGYuX2FyZ19wYXJzZXIucmd3X3pvbmVfbmFtZSA9PSAiIgogICAgICAgICAg - ICAgICAgKSBvciAoCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcmVh - bG1fbmFtZSAhPSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdfcGFyc2VyLnJn - d196b25lZ3JvdXBfbmFtZSAhPSAiIgogICAgICAgICAgICAgICAgICAgIGFuZCBzZWxmLl9hcmdf - cGFyc2VyLnJnd196b25lX25hbWUgIT0gIiIKICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAg - ICAgICAgICAgKAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19BRE1J - Tl9PUFNfVVNFUl9BQ0NFU1NfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYub3V0 - X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JFVF9LRVkiXSwKICAgICAgICAgICAgICAgICAg - ICAgICAgaW5mb19jYXBfc3VwcG9ydGVkLAogICAgICAgICAgICAgICAgICAgICAgICBlcnIsCiAg - ICAgICAgICAgICAgICAgICAgKSA9IHNlbGYuY3JlYXRlX3Jnd19hZG1pbl9vcHNfdXNlcigpCiAg - ICAgICAgICAgICAgICAgICAgZXJyID0gc2VsZi52YWxpZGF0ZV9yZ3dfZW5kcG9pbnQoaW5mb19j - YXBfc3VwcG9ydGVkKQogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIucmd3 - X3Rsc19jZXJ0X3BhdGg6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYub3V0X21hcFsiUkdX - X1RMU19DRVJUIl0gPSAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnZhbGlkYXRl - X3Jnd19lbmRwb2ludF90bHNfY2VydCgpCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAg - ICAgICAgICAgICAgICAjIGlmIHRoZXJlIGlzIG5vIGVycm9yLCBzZXQgdGhlIFJHV19FTkRQT0lO - VAogICAgICAgICAgICAgICAgICAgIGlmIGVyciAhPSAiLTEiOgogICAgICAgICAgICAgICAgICAg - ICAgICBzZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdID0gc2VsZi5fYXJnX3BhcnNlci5yZ3df - ZW5kcG9pbnQKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgZXJyID0g - IlBsZWFzZSBwcm92aWRlIGFsbCB0aGUgUkdXIG11bHRpc2l0ZSBwYXJhbWV0ZXJzIG9yIG5vbmUg - b2YgdGhlbSIKICAgICAgICAgICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGVycikKCiAgICBk - ZWYgZ2VuX3NoZWxsX291dChzZWxmKToKICAgICAgICBzZWxmLl9nZW5fb3V0cHV0X21hcCgpCiAg - ICAgICAgc2hPdXRJTyA9IFN0cmluZ0lPKCkKICAgICAgICBmb3IgaywgdiBpbiBzZWxmLm91dF9t - YXAuaXRlbXMoKToKICAgICAgICAgICAgaWYgdiBhbmQgayBub3QgaW4gc2VsZi5fZXhjbHVkZWRf - a2V5czoKICAgICAgICAgICAgICAgIHNoT3V0SU8ud3JpdGUoZiJleHBvcnQge2t9PXt2fXtMSU5F - U0VQfSIpCiAgICAgICAgc2hPdXQgPSBzaE91dElPLmdldHZhbHVlKCkKICAgICAgICBzaE91dElP - LmNsb3NlKCkKICAgICAgICByZXR1cm4gc2hPdXQKCiAgICBkZWYgZ2VuX2pzb25fb3V0KHNlbGYp - OgogICAgICAgIHNlbGYuX2dlbl9vdXRwdXRfbWFwKCkKICAgICAgICBpZiBzZWxmLl9hcmdfcGFy - c2VyLmRyeV9ydW46CiAgICAgICAgICAgIHJldHVybiAiIgogICAgICAgIGpzb25fb3V0ID0gWwog - ICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJleHRlcm5hbC1jbHVzdGVyLXVz - ZXItY29tbWFuZCIsCiAgICAgICAgICAgICAgICAia2luZCI6ICJDb25maWdNYXAiLAogICAgICAg - ICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgImFyZ3MiOiBzZWxmLm91dF9t - YXBbIkFSR1MiXSwKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAgICAg - IHsKICAgICAgICAgICAgICAgICJuYW1lIjogInJvb2stY2VwaC1tb24tZW5kcG9pbnRzIiwKICAg - ICAgICAgICAgICAgICJraW5kIjogIkNvbmZpZ01hcCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6 - IHsKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5B - TF9DRVBIX01PTl9EQVRBIl0sCiAgICAgICAgICAgICAgICAgICAgIm1heE1vbklkIjogIjAiLAog - ICAgICAgICAgICAgICAgICAgICJtYXBwaW5nIjogInt9IiwKICAgICAgICAgICAgICAgIH0sCiAg - ICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogInJvb2st - Y2VwaC1tb24iLAogICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAg - ICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICJhZG1pbi1zZWNyZXQiOiAiYWRtaW4t - c2VjcmV0IiwKICAgICAgICAgICAgICAgICAgICAiZnNpZCI6IHNlbGYub3V0X21hcFsiUk9PS19F - WFRFUk5BTF9GU0lEIl0sCiAgICAgICAgICAgICAgICAgICAgIm1vbi1zZWNyZXQiOiAibW9uLXNl - Y3JldCIsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAg - ICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtb3BlcmF0b3ItY3JlZHMiLAogICAgICAg - ICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAgICJkYXRhIjogewogICAg - ICAgICAgICAgICAgICAgICJ1c2VySUQiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfVVNF - Uk5BTUUiXSwKICAgICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiUk9P - S19FWFRFUk5BTF9VU0VSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAg - fSwKICAgICAgICBdCgogICAgICAgICMgaWYgJ01PTklUT1JJTkdfRU5EUE9JTlQnIGV4aXN0cywg - dGhlbiBvbmx5IGFkZCAnbW9uaXRvcmluZy1lbmRwb2ludCcgdG8gQ2x1c3RlcgogICAgICAgIGlm - ICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UIl0KICAgICAg - ICAgICAgYW5kIHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0KICAgICAg - ICApOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAg - ICAgICAgICAgICAgICAgIm5hbWUiOiAibW9uaXRvcmluZy1lbmRwb2ludCIsCiAgICAgICAgICAg - ICAgICAgICAgImtpbmQiOiAiQ2VwaENsdXN0ZXIiLAogICAgICAgICAgICAgICAgICAgICJkYXRh - IjogewogICAgICAgICAgICAgICAgICAgICAgICAiTW9uaXRvcmluZ0VuZHBvaW50Ijogc2VsZi5v - dXRfbWFwWyJNT05JVE9SSU5HX0VORFBPSU5UIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJN - b25pdG9yaW5nUG9ydCI6IHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVF9QT1JUIl0s - CiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQoK - ICAgICAgICAjIGlmICdDU0lfUkJEX05PREVfU0VDUkVUJyBleGlzdHMsIHRoZW4gb25seSBhZGQg - J3Jvb2stY3NpLXJiZC1wcm92aXNpb25lcicgU2VjcmV0CiAgICAgICAgaWYgKAogICAgICAgICAg - ICBzZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2Vs - Zi5vdXRfbWFwWyJDU0lfUkJEX05PREVfU0VDUkVUX05BTUUiXQogICAgICAgICk6CiAgICAgICAg - ICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAg - ICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUn - XX0iLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAg - ICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VySUQiOiBzZWxmLm91 - dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAg - ICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9OT0RFX1NFQ1JFVCJdLAogICAgICAg - ICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAj - IGlmICdDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdy - b29rLWNzaS1yYmQtcHJvdmlzaW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAg - c2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCJdCiAgICAgICAgICAgIGFu - ZCBzZWxmLm91dF9tYXBbIkNTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXQogICAgICAg - ICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAg - ICAgICAgICAgICAgICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BST1ZJ - U0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTZWNy - ZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAg - ICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1F - Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VyS2V5Ijogc2VsZi5vdXRfbWFwWyJDU0lf - UkJEX1BST1ZJU0lPTkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAg - ICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdDU0lfQ0VQSEZTX1BST1ZJU0lP - TkVSX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNzaS1jZXBoZnMtcHJvdmlz - aW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lf - Q0VQSEZTX1BST1ZJU0lPTkVSX1NFQ1JFVCJdCiAgICAgICAgICAgIGFuZCBzZWxmLm91dF9tYXBb - IkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXQogICAgICAgICk6CiAgICAgICAg - ICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAg - ICAibmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfQ0VQSEZTX1BST1ZJU0lPTkVSX1NF - Q1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAg - ICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5J - RCI6IHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSJdLAog - ICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5LZXkiOiBzZWxmLm91dF9tYXBbIkNTSV9DRVBI - RlNfUFJPVklTSU9ORVJfU0VDUkVUIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAg - ICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ0NTSV9DRVBIRlNfTk9ERV9TRUNS - RVQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktY2VwaGZzLW5vZGUnIFNlY3JldAog - ICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX05PREVfU0VD - UkVUIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JF - VF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAg - ICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBmInJvb2ste3NlbGYub3V0X21h - cFsnQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAi - a2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAg - ICAgICAgICAgICAgICAiYWRtaW5JRCI6IHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NF - Q1JFVF9OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pbktleSI6IHNlbGYub3V0 - X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAg - ICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdST09LX0VYVEVSTkFM - X0RBU0hCT0FSRF9MSU5LJyBleGlzdHMsIHRoZW4gb25seSBhZGQgJ3Jvb2stY2VwaC1kYXNoYm9h - cmQtbGluaycgU2VjcmV0CiAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX0RB - U0hCT0FSRF9MSU5LIl06CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAg - ICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtZGFzaGJvYXJkLWxp - bmsiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAg - ICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VySUQiOiAiY2VwaC1k - YXNoYm9hcmQtbGluayIsCiAgICAgICAgICAgICAgICAgICAgICAgICJ1c2VyS2V5Ijogc2VsZi5v - dXRfbWFwWyJST09LX0VYVEVSTkFMX0RBU0hCT0FSRF9MSU5LIl0sCiAgICAgICAgICAgICAgICAg - ICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ1JBRE9T - X05BTUVTUEFDRScgZXhpc3RzLCB0aGVuIG9ubHkgYWRkIHRoZSAiUkFET1NfTkFNRVNQQUNFIiBu - YW1lc3BhY2UKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiUkFET1NfTkFN - RVNQQUNFIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsiUkVTVFJJQ1RFRF9BVVRIX1BF - Uk1JU1NJT04iXQogICAgICAgICAgICBhbmQgbm90IHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRB - X0VDX1BPT0xfTkFNRSJdCiAgICAgICAgKToKICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAog - ICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICJuYW1lIjogInJhZG9zLW5hbWVz - cGFjZSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiQ2VwaEJsb2NrUG9vbFJhZG9zTmFt - ZXNwYWNlIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAg - ICAgICAgInJhZG9zTmFtZXNwYWNlTmFtZSI6IHNlbGYub3V0X21hcFsiUkFET1NfTkFNRVNQQUNF - Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9P - TF9OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAg - ICAgICAgKQogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAg - ICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQtcmFkb3MtbmFtZXNwYWNlIiwKICAg + em9uZV9uYW1lICE9ICIiCiAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgICgK + ICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5vdXRfbWFwWyJSR1dfQURNSU5fT1BTX1VTRVJf + QUNDRVNTX0tFWSJdLAogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19B + RE1JTl9PUFNfVVNFUl9TRUNSRVRfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgICAgIGluZm9f + Y2FwX3N1cHBvcnRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgZXJyLAogICAgICAgICAgICAg + ICAgICAgICkgPSBzZWxmLmNyZWF0ZV9yZ3dfYWRtaW5fb3BzX3VzZXIoKQogICAgICAgICAgICAg + ICAgICAgIGVyciA9IHNlbGYudmFsaWRhdGVfcmd3X2VuZHBvaW50KGluZm9fY2FwX3N1cHBvcnRl + ZCkKICAgICAgICAgICAgICAgICAgICBpZiBzZWxmLl9hcmdfcGFyc2VyLnJnd190bHNfY2VydF9w + YXRoOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJHV19UTFNfQ0VSVCJd + ID0gKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi52YWxpZGF0ZV9yZ3dfZW5kcG9p + bnRfdGxzX2NlcnQoKQogICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAg + ICAgIyBpZiB0aGVyZSBpcyBubyBlcnJvciwgc2V0IHRoZSBSR1dfRU5EUE9JTlQKICAgICAgICAg + ICAgICAgICAgICBpZiBlcnIgIT0gIi0xIjoKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5v + dXRfbWFwWyJSR1dfRU5EUE9JTlQiXSA9IHNlbGYuX2FyZ19wYXJzZXIucmd3X2VuZHBvaW50CiAg + ICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIGVyciA9ICJQbGVhc2UgcHJv + dmlkZSBhbGwgdGhlIFJHVyBtdWx0aXNpdGUgcGFyYW1ldGVycyBvciBub25lIG9mIHRoZW0iCiAg + ICAgICAgICAgICAgICAgICAgc3lzLnN0ZGVyci53cml0ZShlcnIpCgogICAgZGVmIGdlbl9zaGVs + bF9vdXQoc2VsZik6CiAgICAgICAgc2VsZi5fZ2VuX291dHB1dF9tYXAoKQogICAgICAgIHNoT3V0 + SU8gPSBTdHJpbmdJTygpCiAgICAgICAgZm9yIGssIHYgaW4gc2VsZi5vdXRfbWFwLml0ZW1zKCk6 + CiAgICAgICAgICAgIGlmIHYgYW5kIGsgbm90IGluIHNlbGYuX2V4Y2x1ZGVkX2tleXM6CiAgICAg + ICAgICAgICAgICBzaE91dElPLndyaXRlKGYiZXhwb3J0IHtrfT17dn17TElORVNFUH0iKQogICAg + ICAgIHNoT3V0ID0gc2hPdXRJTy5nZXR2YWx1ZSgpCiAgICAgICAgc2hPdXRJTy5jbG9zZSgpCiAg + ICAgICAgcmV0dXJuIHNoT3V0CgogICAgZGVmIGdlbl9qc29uX291dChzZWxmKToKICAgICAgICBz + ZWxmLl9nZW5fb3V0cHV0X21hcCgpCiAgICAgICAgaWYgc2VsZi5fYXJnX3BhcnNlci5kcnlfcnVu + OgogICAgICAgICAgICByZXR1cm4gIiIKICAgICAgICBqc29uX291dCA9IFsKICAgICAgICAgICAg + ewogICAgICAgICAgICAgICAgIm5hbWUiOiAiZXh0ZXJuYWwtY2x1c3Rlci11c2VyLWNvbW1hbmQi + LAogICAgICAgICAgICAgICAgImtpbmQiOiAiQ29uZmlnTWFwIiwKICAgICAgICAgICAgICAgICJk + YXRhIjogewogICAgICAgICAgICAgICAgICAgICJhcmdzIjogc2VsZi5vdXRfbWFwWyJBUkdTIl0s + CiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAg + ICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtbW9uLWVuZHBvaW50cyIsCiAgICAgICAgICAgICAg + ICAia2luZCI6ICJDb25maWdNYXAiLAogICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAg + ICAgICAgICAgICAgImRhdGEiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfQ0VQSF9NT05f + REFUQSJdLAogICAgICAgICAgICAgICAgICAgICJtYXhNb25JZCI6ICIwIiwKICAgICAgICAgICAg + ICAgICAgICAibWFwcGluZyI6ICJ7fSIsCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICB9 + LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6ICJyb29rLWNlcGgtbW9uIiwK + ICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6 + IHsKICAgICAgICAgICAgICAgICAgICAiYWRtaW4tc2VjcmV0IjogImFkbWluLXNlY3JldCIsCiAg + ICAgICAgICAgICAgICAgICAgImZzaWQiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxfRlNJ + RCJdLAogICAgICAgICAgICAgICAgICAgICJtb24tc2VjcmV0IjogIm1vbi1zZWNyZXQiLAogICAg + ICAgICAgICAgICAgfSwKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAg + ICAgIm5hbWUiOiAicm9vay1jZXBoLW9wZXJhdG9yLWNyZWRzIiwKICAgICAgICAgICAgICAgICJr + aW5kIjogIlNlY3JldCIsCiAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAg + ICAgICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJST09LX0VYVEVSTkFMX1VTRVJOQU1FIl0sCiAg + ICAgICAgICAgICAgICAgICAgInVzZXJLZXkiOiBzZWxmLm91dF9tYXBbIlJPT0tfRVhURVJOQUxf + VVNFUl9TRUNSRVQiXSwKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIH0sCiAgICAgICAg + XQoKICAgICAgICAjIGlmICdNT05JVE9SSU5HX0VORFBPSU5UJyBleGlzdHMsIHRoZW4gb25seSBh + ZGQgJ21vbml0b3JpbmctZW5kcG9pbnQnIHRvIENsdXN0ZXIKICAgICAgICBpZiAoCiAgICAgICAg + ICAgIHNlbGYub3V0X21hcFsiTU9OSVRPUklOR19FTkRQT0lOVCJdCiAgICAgICAgICAgIGFuZCBz + ZWxmLm91dF9tYXBbIk1PTklUT1JJTkdfRU5EUE9JTlRfUE9SVCJdCiAgICAgICAgKToKICAgICAg + ICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAg + ICAgICJuYW1lIjogIm1vbml0b3JpbmctZW5kcG9pbnQiLAogICAgICAgICAgICAgICAgICAgICJr + aW5kIjogIkNlcGhDbHVzdGVyIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAg + ICAgICAgICAgICAgICAgICAgIk1vbml0b3JpbmdFbmRwb2ludCI6IHNlbGYub3V0X21hcFsiTU9O + SVRPUklOR19FTkRQT0lOVCJdLAogICAgICAgICAgICAgICAgICAgICAgICAiTW9uaXRvcmluZ1Bv + cnQiOiBzZWxmLm91dF9tYXBbIk1PTklUT1JJTkdfRU5EUE9JTlRfUE9SVCJdLAogICAgICAgICAg + ICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgIyBp + ZiAnQ1NJX1JCRF9OT0RFX1NFQ1JFVCcgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNzaS1y + YmQtcHJvdmlzaW9uZXInIFNlY3JldAogICAgICAgIGlmICgKICAgICAgICAgICAgc2VsZi5vdXRf + bWFwWyJDU0lfUkJEX05PREVfU0VDUkVUIl0KICAgICAgICAgICAgYW5kIHNlbGYub3V0X21hcFsi + Q1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291 + dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBm + InJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAg + ICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRh + IjogewogICAgICAgICAgICAgICAgICAgICAgICAidXNlcklEIjogc2VsZi5vdXRfbWFwWyJDU0lf + UkJEX05PREVfU0VDUkVUX05BTUUiXSwKICAgICAgICAgICAgICAgICAgICAgICAgInVzZXJLZXki + OiBzZWxmLm91dF9tYXBbIkNTSV9SQkRfTk9ERV9TRUNSRVQiXSwKICAgICAgICAgICAgICAgICAg + ICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnQ1NJX1JC + RF9QUk9WSVNJT05FUl9TRUNSRVQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktcmJk + LXByb3Zpc2lvbmVyJyBTZWNyZXQKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21h + cFsiQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2VsZi5vdXRf + bWFwWyJDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FIl0KICAgICAgICApOgogICAgICAg + ICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAg + ICAgIm5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNS + RVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAg + ICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgInVzZXJJRCI6 + IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSJdLAogICAgICAg + ICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiQ1NJX1JCRF9QUk9WSVNJ + T05FUl9TRUNSRVQiXSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgfQog + ICAgICAgICAgICApCiAgICAgICAgIyBpZiAnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVQn + IGV4aXN0cywgdGhlbiBvbmx5IGFkZCAncm9vay1jc2ktY2VwaGZzLXByb3Zpc2lvbmVyJyBTZWNy + ZXQKICAgICAgICBpZiAoCiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19QUk9W + SVNJT05FUl9TRUNSRVQiXQogICAgICAgICAgICBhbmQgc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZT + X1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FIl0KICAgICAgICApOgogICAgICAgICAgICBqc29uX291 + dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiBm + InJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSdd + fSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAg + ICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImFkbWluSUQiOiBzZWxmLm91 + dF9tYXBbIkNTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUiXSwKICAgICAgICAgICAg + ICAgICAgICAgICAgImFkbWluS2V5Ijogc2VsZi5vdXRfbWFwWyJDU0lfQ0VQSEZTX1BST1ZJU0lP + TkVSX1NFQ1JFVCJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAg + ICAgICAgICAgICkKICAgICAgICAjIGlmICdDU0lfQ0VQSEZTX05PREVfU0VDUkVUJyBleGlzdHMs + IHRoZW4gb25seSBhZGQgJ3Jvb2stY3NpLWNlcGhmcy1ub2RlJyBTZWNyZXQKICAgICAgICBpZiAo + CiAgICAgICAgICAgIHNlbGYub3V0X21hcFsiQ1NJX0NFUEhGU19OT0RFX1NFQ1JFVCJdCiAgICAg + ICAgICAgIGFuZCBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9TRUNSRVRfTkFNRSJdCiAg + ICAgICAgKToKICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewog + ICAgICAgICAgICAgICAgICAgICJuYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9DRVBI + RlNfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2Vj + cmV0IiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAg + ICAgImFkbWluSUQiOiBzZWxmLm91dF9tYXBbIkNTSV9DRVBIRlNfTk9ERV9TRUNSRVRfTkFNRSJd + LAogICAgICAgICAgICAgICAgICAgICAgICAiYWRtaW5LZXkiOiBzZWxmLm91dF9tYXBbIkNTSV9D + RVBIRlNfTk9ERV9TRUNSRVQiXSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAg + ICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUk9PS19FWFRFUk5BTF9EQVNIQk9BUkRf + TElOSycgZXhpc3RzLCB0aGVuIG9ubHkgYWRkICdyb29rLWNlcGgtZGFzaGJvYXJkLWxpbmsnIFNl + Y3JldAogICAgICAgIGlmIHNlbGYub3V0X21hcFsiUk9PS19FWFRFUk5BTF9EQVNIQk9BUkRfTElO + SyJdOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAg + ICAgICAgICAgICAgICAgIm5hbWUiOiAicm9vay1jZXBoLWRhc2hib2FyZC1saW5rIiwKICAgICAg + ICAgICAgICAgICAgICAia2luZCI6ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRh + IjogewogICAgICAgICAgICAgICAgICAgICAgICAidXNlcklEIjogImNlcGgtZGFzaGJvYXJkLWxp + bmsiLAogICAgICAgICAgICAgICAgICAgICAgICAidXNlcktleSI6IHNlbGYub3V0X21hcFsiUk9P + S19FWFRFUk5BTF9EQVNIQk9BUkRfTElOSyJdLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAg + ICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdSQURPU19OQU1FU1BBQ0Un + IGV4aXN0cywgdGhlbiBvbmx5IGFkZCB0aGUgIlJBRE9TX05BTUVTUEFDRSIgbmFtZXNwYWNlCiAg + ICAgICAgaWYgKAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIlJBRE9TX05BTUVTUEFDRSJdCiAg + ICAgICAgICAgIGFuZCBzZWxmLm91dF9tYXBbIlJFU1RSSUNURURfQVVUSF9QRVJNSVNTSU9OIl0K + ICAgICAgICAgICAgYW5kIG5vdCBzZWxmLm91dF9tYXBbIlJCRF9NRVRBREFUQV9FQ19QT09MX05B + TUUiXQogICAgICAgICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAg + ICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyYWRvcy1uYW1lc3BhY2UiLAogICAg + ICAgICAgICAgICAgICAgICJraW5kIjogIkNlcGhCbG9ja1Bvb2xSYWRvc05hbWVzcGFjZSIsCiAg + ICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJyYWRv + c05hbWVzcGFjZU5hbWUiOiBzZWxmLm91dF9tYXBbIlJBRE9TX05BTUVTUEFDRSJdLAogICAgICAg + ICAgICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21hcFsiUkJEX1BPT0xfTkFNRSJdLAog + ICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAg + ICAgICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAg + ICAgICAgICJuYW1lIjogImNlcGgtcmJkLXJhZG9zLW5hbWVzcGFjZSIsCiAgICAgICAgICAgICAg + ICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6 + IHsKICAgICAgICAgICAgICAgICAgICAgICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9QT09M + X05BTUUiXSwKICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9wcm92 + aXNpb25lci1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BST1ZJ + U0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9y + YWdlLms4cy5pby9jb250cm9sbGVyLWV4cGFuZC1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v + dXRfbWFwWydDU0lfUkJEX1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAg + ICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9ub2RlLXN0YWdlLXNlY3JldC1uYW1lIjog + ZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAg + ICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAg + IGVsc2U6CiAgICAgICAgICAgIGlmIHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xf + TkFNRSJdOgogICAgICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAg + ICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQiLAogICAgICAg ICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAogICAgICAgICAgICAgICAg - ICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21h - cFsiUkJEX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu - azhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NT - SV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAg - ICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhwYW5kLXNlY3JldC1uYW1lIjogZiJy - b29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAog - ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL25vZGUtc3RhZ2Utc2Vj - cmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1F - J119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAg - ICApCiAgICAgICAgZWxzZToKICAgICAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJSQkRfTUVUQURB - VEFfRUNfUE9PTF9OQU1FIl06CiAgICAgICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAg - ICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJjZXBoLXJi - ZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAg - ICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAgICAg - ImRhdGFQb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1FIl0sCiAgICAgICAgICAgICAg - ICAgICAgICAgICAgICAicG9vbCI6IHNlbGYub3V0X21hcFsiUkJEX01FVEFEQVRBX0VDX1BPT0xf - TkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9w - cm92aXNpb25lci1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJEX1BS - T1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJj - c2kuc3RvcmFnZS5rOHMuaW8vY29udHJvbGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2st - e3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAg - ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL25vZGUtc3RhZ2Utc2Vj - cmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9OT0RFX1NFQ1JFVF9OQU1F - J119IiwKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICB9CiAg - ICAgICAgICAgICAgICApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBqc29uX291 - dC5hcHBlbmQoCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAi - bmFtZSI6ICJjZXBoLXJiZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3Jh - Z2VDbGFzcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAg - ICAgICAgICAgICAgICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9QT09MX05BTUUiXSwKICAg + ICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkYXRhUG9vbCI6 + IHNlbGYub3V0X21hcFsiUkJEX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAg + ICAgInBvb2wiOiBzZWxmLm91dF9tYXBbIlJCRF9NRVRBREFUQV9FQ19QT09MX05BTUUiXSwKICAg ICAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXIt c2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9T RUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu @@ -1752,147 +1745,159 @@ metadata: ICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9ub2RlLXN0YWdlLXNlY3JldC1uYW1lIjog ZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfTk9ERV9TRUNSRVRfTkFNRSddfSIsCiAgICAg ICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAg - ICAgKQoKICAgICAgICAjIGlmICdUT1BPTE9HWV9QT09MUycsICdUT1BPTE9HWV9GQUlMVVJFX0RP - TUFJTl9MQUJFTCcsICdUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMnICBleGlzdHMsCiAg - ICAgICAgIyB0aGVuIG9ubHkgYWRkICd0b3BvbG9neScgU3RvcmFnZUNsYXNzCiAgICAgICAgaWYg - KAogICAgICAgICAgICBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0KICAgICAgICAgICAg - YW5kIHNlbGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fTEFCRUwiXQogICAgICAg - ICAgICBhbmQgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiXQog - ICAgICAgICk6CiAgICAgICAgICAgIGpzb25fb3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsK - ICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJjZXBoLXJiZC10b3BvbG9neSIsCiAgICAgICAg - ICAgICAgICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwKICAgICAgICAgICAgICAgICAgICAi - ZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgInRvcG9sb2d5RmFpbHVyZURvbWFpbkxh - YmVsIjogc2VsZi5vdXRfbWFwWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRPUE9MT0dZ - X0ZBSUxVUkVfRE9NQUlOX0xBQkVMIgogICAgICAgICAgICAgICAgICAgICAgICBdLAogICAgICAg - ICAgICAgICAgICAgICAgICAidG9wb2xvZ3lGYWlsdXJlRG9tYWluVmFsdWVzIjogc2VsZi5vdXRf - bWFwWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlO - X1ZBTFVFUyIKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgICAg - ICAgInRvcG9sb2d5UG9vbHMiOiBzZWxmLm91dF9tYXBbIlRPUE9MT0dZX1BPT0xTIl0sCiAgICAg - ICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXItc2VjcmV0 - LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JCRF9QUk9WSVNJT05FUl9TRUNSRVRf - TkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vY29u - dHJvbGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX1JC - RF9QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJj - c2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v - dXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAg - IH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgIyBpZiAnQ0VQSEZT - X0ZTX05BTUUnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAnY2VwaGZzJyBTdG9yYWdlQ2xhc3MKICAg - ICAgICBpZiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl06CiAgICAgICAgICAgIGpzb25f - b3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6 - ICJjZXBoZnMiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAg - ICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJmc05h - bWUiOiBzZWxmLm91dF9tYXBbIkNFUEhGU19GU19OQU1FIl0sCiAgICAgICAgICAgICAgICAgICAg - ICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJDRVBIRlNfUE9PTF9OQU1FIl0sCiAgICAgICAgICAg - ICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vcHJvdmlzaW9uZXItc2VjcmV0LW5hbWUi - OiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhGU19QUk9WSVNJT05FUl9TRUNSRVRfTkFN - RSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJjc2kuc3RvcmFnZS5rOHMuaW8vY29udHJv - bGxlci1leHBhbmQtc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJX0NFUEhG - U19QUk9WSVNJT05FUl9TRUNSRVRfTkFNRSddfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJj - c2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5v - dXRfbWFwWydDU0lfQ0VQSEZTX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAg - ICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAgICAjIGlmICdSR1df - RU5EUE9JTlQnIGV4aXN0cywgdGhlbiBvbmx5IGFkZCAnY2VwaC1yZ3cnIFN0b3JhZ2VDbGFzcwog - ICAgICAgIGlmIHNlbGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl06CiAgICAgICAgICAgIGpzb25f + ICAgKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAganNvbl9vdXQuYXBwZW5kKAog + ICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2Vw + aC1yYmQiLAogICAgICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAog + ICAgICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAg + ICAgICJwb29sIjogc2VsZi5vdXRfbWFwWyJSQkRfUE9PTF9OQU1FIl0sCiAgICAgICAgICAgICAg + ICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1l + IjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUn + XX0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgImNzaS5zdG9yYWdlLms4cy5pby9jb250 + cm9sbGVyLWV4cGFuZC1zZWNyZXQtbmFtZSI6IGYicm9vay17c2VsZi5vdXRfbWFwWydDU0lfUkJE + X1BST1ZJU0lPTkVSX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAg + ICJjc2kuc3RvcmFnZS5rOHMuaW8vbm9kZS1zdGFnZS1zZWNyZXQtbmFtZSI6IGYicm9vay17c2Vs + Zi5vdXRfbWFwWydDU0lfUkJEX05PREVfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAg + ICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkKCiAgICAg + ICAgIyBpZiAnVE9QT0xPR1lfUE9PTFMnLCAnVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fTEFCRUwn + LCAnVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fVkFMVUVTJyAgZXhpc3RzLAogICAgICAgICMgdGhl + biBvbmx5IGFkZCAndG9wb2xvZ3knIFN0b3JhZ2VDbGFzcwogICAgICAgIGlmICgKICAgICAgICAg + ICAgc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdCiAgICAgICAgICAgIGFuZCBzZWxmLm91 + dF9tYXBbIlRPUE9MT0dZX0ZBSUxVUkVfRE9NQUlOX0xBQkVMIl0KICAgICAgICAgICAgYW5kIHNl + bGYub3V0X21hcFsiVE9QT0xPR1lfRkFJTFVSRV9ET01BSU5fVkFMVUVTIl0KICAgICAgICApOgog + ICAgICAgICAgICBqc29uX291dC5hcHBlbmQoCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAg + ICAgICAgICAgIm5hbWUiOiAiY2VwaC1yYmQtdG9wb2xvZ3kiLAogICAgICAgICAgICAgICAgICAg + ICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAg + ICAgICAgICAgICAgICAgICAgICAgICJ0b3BvbG9neUZhaWx1cmVEb21haW5MYWJlbCI6IHNlbGYu + b3V0X21hcFsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUT1BPTE9HWV9GQUlMVVJFX0RP + TUFJTl9MQUJFTCIKICAgICAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAg + ICAgICAgInRvcG9sb2d5RmFpbHVyZURvbWFpblZhbHVlcyI6IHNlbGYub3V0X21hcFsKICAgICAg + ICAgICAgICAgICAgICAgICAgICAgICJUT1BPTE9HWV9GQUlMVVJFX0RPTUFJTl9WQUxVRVMiCiAg + ICAgICAgICAgICAgICAgICAgICAgIF0sCiAgICAgICAgICAgICAgICAgICAgICAgICJ0b3BvbG9n + eVBvb2xzIjogc2VsZi5vdXRfbWFwWyJUT1BPTE9HWV9QT09MUyJdLAogICAgICAgICAgICAgICAg + ICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJy + b29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAog + ICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhw + YW5kLXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9SQkRfUFJPVklTSU9O + RVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu + azhzLmlvL25vZGUtc3RhZ2Utc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJ + X1JCRF9OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAg + ICAgICAgICAgfQogICAgICAgICAgICApCgogICAgICAgICMgaWYgJ0NFUEhGU19GU19OQU1FJyBl + eGlzdHMsIHRoZW4gb25seSBhZGQgJ2NlcGhmcycgU3RvcmFnZUNsYXNzCiAgICAgICAgaWYgc2Vs + Zi5vdXRfbWFwWyJDRVBIRlNfRlNfTkFNRSJdOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQo + CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaGZzIiwK + ICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJTdG9yYWdlQ2xhc3MiLAogICAgICAgICAgICAg + ICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAgICAgICAgICAiZnNOYW1lIjogc2VsZi5v + dXRfbWFwWyJDRVBIRlNfRlNfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAgICAicG9vbCI6 + IHNlbGYub3V0X21hcFsiQ0VQSEZTX1BPT0xfTkFNRSJdLAogICAgICAgICAgICAgICAgICAgICAg + ICAiY3NpLnN0b3JhZ2UuazhzLmlvL3Byb3Zpc2lvbmVyLXNlY3JldC1uYW1lIjogZiJyb29rLXtz + ZWxmLm91dF9tYXBbJ0NTSV9DRVBIRlNfUFJPVklTSU9ORVJfU0VDUkVUX05BTUUnXX0iLAogICAg + ICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2UuazhzLmlvL2NvbnRyb2xsZXItZXhwYW5k + LXNlY3JldC1uYW1lIjogZiJyb29rLXtzZWxmLm91dF9tYXBbJ0NTSV9DRVBIRlNfUFJPVklTSU9O + RVJfU0VDUkVUX05BTUUnXX0iLAogICAgICAgICAgICAgICAgICAgICAgICAiY3NpLnN0b3JhZ2Uu + azhzLmlvL25vZGUtc3RhZ2Utc2VjcmV0LW5hbWUiOiBmInJvb2ste3NlbGYub3V0X21hcFsnQ1NJ + X0NFUEhGU19OT0RFX1NFQ1JFVF9OQU1FJ119IiwKICAgICAgICAgICAgICAgICAgICB9LAogICAg + ICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUkdXX0VORFBPSU5UJyBl + eGlzdHMsIHRoZW4gb25seSBhZGQgJ2NlcGgtcmd3JyBTdG9yYWdlQ2xhc3MKICAgICAgICBpZiBz + ZWxmLm91dF9tYXBbIlJHV19FTkRQT0lOVCJdOgogICAgICAgICAgICBqc29uX291dC5hcHBlbmQo + CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiY2VwaC1yZ3ci + LAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlN0b3JhZ2VDbGFzcyIsCiAgICAgICAgICAg + ICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJlbmRwb2ludCI6IHNl + bGYub3V0X21hcFsiUkdXX0VORFBPSU5UIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICJwb29s + UHJlZml4Ijogc2VsZi5vdXRfbWFwWyJSR1dfUE9PTF9QUkVGSVgiXSwKICAgICAgICAgICAgICAg + ICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgICAgIGpzb25f b3V0LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6 - ICJjZXBoLXJndyIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU3RvcmFnZUNsYXNzIiwK - ICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImVu - ZHBvaW50Ijogc2VsZi5vdXRfbWFwWyJSR1dfRU5EUE9JTlQiXSwKICAgICAgICAgICAgICAgICAg - ICAgICAgInBvb2xQcmVmaXgiOiBzZWxmLm91dF9tYXBbIlJHV19QT09MX1BSRUZJWCJdLAogICAg - ICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKICAgICAg - ICAgICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAg - ICAgICJuYW1lIjogInJndy1hZG1pbi1vcHMtdXNlciIsCiAgICAgICAgICAgICAgICAgICAgImtp - bmQiOiAiU2VjcmV0IiwKICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAg - ICAgICAgICAgICAgImFjY2Vzc0tleSI6IHNlbGYub3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VS - X0FDQ0VTU19LRVkiXSwKICAgICAgICAgICAgICAgICAgICAgICAgInNlY3JldEtleSI6IHNlbGYu - b3V0X21hcFsiUkdXX0FETUlOX09QU19VU0VSX1NFQ1JFVF9LRVkiXSwKICAgICAgICAgICAgICAg - ICAgICB9LAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICApCiAgICAgICAgIyBpZiAnUkdX - X1RMU19DRVJUJyBleGlzdHMsIHRoZW4gb25seSBhZGQgdGhlICJjZXBoLXJndy10bHMtY2VydCIg - c2VjcmV0CiAgICAgICAgaWYgc2VsZi5vdXRfbWFwWyJSR1dfVExTX0NFUlQiXToKICAgICAgICAg - ICAganNvbl9vdXQuYXBwZW5kKAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAg - ICJuYW1lIjogImNlcGgtcmd3LXRscy1jZXJ0IiwKICAgICAgICAgICAgICAgICAgICAia2luZCI6 - ICJTZWNyZXQiLAogICAgICAgICAgICAgICAgICAgICJkYXRhIjogewogICAgICAgICAgICAgICAg - ICAgICAgICAiY2VydCI6IHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl0sCiAgICAgICAgICAg - ICAgICAgICAgfSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQoKICAgICAgICByZXR1 - cm4ganNvbi5kdW1wcyhqc29uX291dCkgKyBMSU5FU0VQCgogICAgZGVmIHVwZ3JhZGVfdXNlcnNf - cGVybWlzc2lvbnMoc2VsZik6CiAgICAgICAgdXNlcnMgPSBbCiAgICAgICAgICAgICJjbGllbnQu - Y3NpLWNlcGhmcy1ub2RlIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktY2VwaGZzLXByb3Zpc2lv - bmVyIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktcmJkLW5vZGUiLAogICAgICAgICAgICAiY2xp - ZW50LmNzaS1yYmQtcHJvdmlzaW9uZXIiLAogICAgICAgICAgICAiY2xpZW50LmhlYWx0aGNoZWNr - ZXIiLAogICAgICAgIF0KICAgICAgICBpZiBzZWxmLnJ1bl9hc191c2VyICE9ICIiIGFuZCBzZWxm - LnJ1bl9hc191c2VyIG5vdCBpbiB1c2VyczoKICAgICAgICAgICAgdXNlcnMuYXBwZW5kKHNlbGYu - cnVuX2FzX3VzZXIpCiAgICAgICAgZm9yIHVzZXIgaW4gdXNlcnM6CiAgICAgICAgICAgIHNlbGYu - dXBncmFkZV91c2VyX3Blcm1pc3Npb25zKHVzZXIpCgogICAgZGVmIGdldF9yZ3dfcG9vbF9uYW1l - X2R1cmluZ191cGdyYWRlKHNlbGYsIHVzZXIsIGNhcHMpOgogICAgICAgIGlmIHVzZXIgPT0gImNs - aWVudC5oZWFsdGhjaGVja2VyIjoKICAgICAgICAgICAgIyB3aGVuIGFkbWluIGhhcyBub3QgcHJv - dmlkZWQgcmd3IHBvb2wgbmFtZSBkdXJpbmcgdXBncmFkZSwKICAgICAgICAgICAgIyBnZXQgdGhl - IHJndyBwb29sIG5hbWUgZnJvbSBjbGllbnQuaGVhbHRoY2hlY2tlciB1c2VyIHdoaWNoIHdhcyB1 - c2VkIGR1cmluZyBjb25uZWN0aW9uCiAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9hcmdfcGFyc2Vy - LnJnd19wb29sX3ByZWZpeDoKICAgICAgICAgICAgICAgICMgVG8gZ2V0IHZhbHVlICdkZWZhdWx0 - JyB3aGljaCBpcyByZ3cgcG9vbCBuYW1lIGZyb20gJ2FsbG93IHJ3eCBwb29sPWRlZmF1bHQucmd3 - Lm1ldGEnCiAgICAgICAgICAgICAgICBwYXR0ZXJuID0gciJwb29sPSguKj8pXC5yZ3dcLm1ldGEi - CiAgICAgICAgICAgICAgICBtYXRjaCA9IHJlLnNlYXJjaChwYXR0ZXJuLCBjYXBzKQogICAgICAg - ICAgICAgICAgaWYgbWF0Y2g6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5fYXJnX3BhcnNlci5y - Z3dfcG9vbF9wcmVmaXggPSBtYXRjaC5ncm91cCgxKQogICAgICAgICAgICAgICAgZWxzZToKICAg - ICAgICAgICAgICAgICAgICByYWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAg - ICAgICAgICAgICAgICAgICAiZmFpbGVkIHRvIGdldCByZ3cgcG9vbCBuYW1lIGZvciB1cGdyYWRl - IgogICAgICAgICAgICAgICAgICAgICkKCiAgICBkZWYgdXBncmFkZV91c2VyX3Blcm1pc3Npb25z - KHNlbGYsIHVzZXIpOgogICAgICAgICMgY2hlY2sgd2hldGhlciB0aGUgZ2l2ZW4gdXNlciBleGlz - dHMgb3Igbm90CiAgICAgICAgY21kX2pzb24gPSB7InByZWZpeCI6ICJhdXRoIGdldCIsICJlbnRp - dHkiOiBmInt1c2VyfSIsICJmb3JtYXQiOiAianNvbiJ9CiAgICAgICAgcmV0X3ZhbCwganNvbl9v - dXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29uKQogICAgICAg - IGlmIHJldF92YWwgIT0gMCBvciBsZW4oanNvbl9vdXQpID09IDA6CiAgICAgICAgICAgIHByaW50 - KGYidXNlciB7dXNlcn0gbm90IGZvdW5kIGZvciB1cGdyYWRpbmcuIikKICAgICAgICAgICAgcmV0 - dXJuCiAgICAgICAgZXhpc3RpbmdfY2FwcyA9IGpzb25fb3V0WzBdWyJjYXBzIl0KICAgICAgICBz - ZWxmLmdldF9yZ3dfcG9vbF9uYW1lX2R1cmluZ191cGdyYWRlKHVzZXIsIHN0cihleGlzdGluZ19j - YXBzKSkKICAgICAgICBuZXdfY2FwLCBfID0gc2VsZi5nZXRfY2Fwc19hbmRfZW50aXR5KHVzZXIp - CiAgICAgICAgY2FwX2tleXMgPSBbIm1vbiIsICJtZ3IiLCAib3NkIiwgIm1kcyJdCiAgICAgICAg - Y2FwcyA9IFtdCiAgICAgICAgZm9yIGVhY2hDYXAgaW4gY2FwX2tleXM6CiAgICAgICAgICAgIGN1 - cl9jYXBfdmFsdWVzID0gZXhpc3RpbmdfY2Fwcy5nZXQoZWFjaENhcCwgIiIpCiAgICAgICAgICAg - IG5ld19jYXBfdmFsdWVzID0gbmV3X2NhcC5nZXQoZWFjaENhcCwgIiIpCiAgICAgICAgICAgIGN1 - cl9jYXBfcGVybV9saXN0ID0gWwogICAgICAgICAgICAgICAgeC5zdHJpcCgpIGZvciB4IGluIGN1 - cl9jYXBfdmFsdWVzLnNwbGl0KCIsIikgaWYgeC5zdHJpcCgpCiAgICAgICAgICAgIF0KICAgICAg - ICAgICAgbmV3X2NhcF9wZXJtX2xpc3QgPSBbCiAgICAgICAgICAgICAgICB4LnN0cmlwKCkgZm9y - IHggaW4gbmV3X2NhcF92YWx1ZXMuc3BsaXQoIiwiKSBpZiB4LnN0cmlwKCkKICAgICAgICAgICAg - XQogICAgICAgICAgICAjIGFwcGVuZCBuZXdfY2FwX2xpc3QgdG8gY3VyX2NhcF9saXN0IHRvIG1h - aW50YWluIHRoZSBvcmRlciBvZiBjYXBzCiAgICAgICAgICAgIGN1cl9jYXBfcGVybV9saXN0LmV4 - dGVuZChuZXdfY2FwX3Blcm1fbGlzdCkKICAgICAgICAgICAgIyBlbGltaW5hdGUgZHVwbGljYXRl - cyB3aXRob3V0IHVzaW5nICdzZXQnCiAgICAgICAgICAgICMgc2V0IHJlLW9yZGVycyBpdGVtcyBp - biB0aGUgbGlzdCBhbmQgd2UgaGF2ZSB0byBrZWVwIHRoZSBvcmRlcgogICAgICAgICAgICBuZXdf - Y2FwX2xpc3QgPSBbXQogICAgICAgICAgICBbbmV3X2NhcF9saXN0LmFwcGVuZCh4KSBmb3IgeCBp - biBjdXJfY2FwX3Blcm1fbGlzdCBpZiB4IG5vdCBpbiBuZXdfY2FwX2xpc3RdCiAgICAgICAgICAg - IGV4aXN0aW5nX2NhcHNbZWFjaENhcF0gPSAiLCAiLmpvaW4obmV3X2NhcF9saXN0KQogICAgICAg - ICAgICBpZiBleGlzdGluZ19jYXBzW2VhY2hDYXBdOgogICAgICAgICAgICAgICAgY2Fwcy5hcHBl - bmQoZWFjaENhcCkKICAgICAgICAgICAgICAgIGNhcHMuYXBwZW5kKGV4aXN0aW5nX2NhcHNbZWFj - aENhcF0pCiAgICAgICAgY21kX2pzb24gPSB7CiAgICAgICAgICAgICJwcmVmaXgiOiAiYXV0aCBj - YXBzIiwKICAgICAgICAgICAgImVudGl0eSI6IHVzZXIsCiAgICAgICAgICAgICJjYXBzIjogY2Fw - cywKICAgICAgICAgICAgImZvcm1hdCI6ICJqc29uIiwKICAgICAgICB9CiAgICAgICAgcmV0X3Zh - bCwganNvbl9vdXQsIGVycl9tc2cgPSBzZWxmLl9jb21tb25fY21kX2pzb25fZ2VuKGNtZF9qc29u - KQogICAgICAgIGlmIHJldF92YWwgIT0gMDoKICAgICAgICAgICAgcmFpc2UgRXhlY3V0aW9uRmFp - bHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiJ2F1dGggY2FwcyB7dXNlcn0nIGNvbW1h - bmQgZmFpbGVkLlxuIEVycm9yOiB7ZXJyX21zZ30iCiAgICAgICAgICAgICkKICAgICAgICBwcmlu - dChmIlVwZGF0ZWQgdXNlciB7dXNlcn0gc3VjY2Vzc2Z1bGx5LiIpCgogICAgZGVmIG1haW4oc2Vs - Zik6CiAgICAgICAgZ2VuZXJhdGVkX291dHB1dCA9ICIiCiAgICAgICAgaWYgc2VsZi5fYXJnX3Bh - cnNlci51cGdyYWRlOgogICAgICAgICAgICBzZWxmLnVwZ3JhZGVfdXNlcnNfcGVybWlzc2lvbnMo - KQogICAgICAgIGVsaWYgc2VsZi5fYXJnX3BhcnNlci5mb3JtYXQgPT0gImpzb24iOgogICAgICAg - ICAgICBnZW5lcmF0ZWRfb3V0cHV0ID0gc2VsZi5nZW5fanNvbl9vdXQoKQogICAgICAgIGVsaWYg - c2VsZi5fYXJnX3BhcnNlci5mb3JtYXQgPT0gImJhc2giOgogICAgICAgICAgICBnZW5lcmF0ZWRf - b3V0cHV0ID0gc2VsZi5nZW5fc2hlbGxfb3V0KCkKICAgICAgICBlbHNlOgogICAgICAgICAgICBy - YWlzZSBFeGVjdXRpb25GYWlsdXJlRXhjZXB0aW9uKAogICAgICAgICAgICAgICAgZiJVbnN1cHBv - cnRlZCBmb3JtYXQ6IHtzZWxmLl9hcmdfcGFyc2VyLmZvcm1hdH0iCiAgICAgICAgICAgICkKICAg - ICAgICBwcmludChnZW5lcmF0ZWRfb3V0cHV0KQogICAgICAgIGlmIHNlbGYub3V0cHV0X2ZpbGUg - YW5kIGdlbmVyYXRlZF9vdXRwdXQ6CiAgICAgICAgICAgIGZPdXQgPSBvcGVuKHNlbGYub3V0cHV0 - X2ZpbGUsIG1vZGU9InciLCBlbmNvZGluZz0iVVRGLTgiKQogICAgICAgICAgICBmT3V0LndyaXRl - KGdlbmVyYXRlZF9vdXRwdXQpCiAgICAgICAgICAgIGZPdXQuY2xvc2UoKQoKCiMjIyMjIyMjIyMj - IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMj - IyMgTUFJTiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj - IyMjIyMjIyMjIyMjIyMjIyMjIyMjCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICByak9i - aiA9IFJhZG9zSlNPTigpCiAgICB0cnk6CiAgICAgICAgcmpPYmoubWFpbigpCiAgICBleGNlcHQg - RXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbiBhcyBlcnI6CiAgICAgICAgcHJpbnQoZiJFeGVjdXRp - b24gRmFpbGVkOiB7ZXJyfSIpCiAgICAgICAgcmFpc2UgZXJyCiAgICBleGNlcHQgS2V5RXJyb3Ig - YXMga0VycjoKICAgICAgICBwcmludChmIktleUVycm9yOiB7a0Vycn0iKQogICAgZXhjZXB0IE9T - RXJyb3IgYXMgb3NFcnI6CiAgICAgICAgcHJpbnQoZiJFcnJvciB3aGlsZSB0cnlpbmcgdG8gb3V0 - cHV0IHRoZSBkYXRhOiB7b3NFcnJ9IikKICAgIGZpbmFsbHk6CiAgICAgICAgcmpPYmouc2h1dGRv - d24oKQo= + ICJyZ3ctYWRtaW4tb3BzLXVzZXIiLAogICAgICAgICAgICAgICAgICAgICJraW5kIjogIlNlY3Jl + dCIsCiAgICAgICAgICAgICAgICAgICAgImRhdGEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAg + ICJhY2Nlc3NLZXkiOiBzZWxmLm91dF9tYXBbIlJHV19BRE1JTl9PUFNfVVNFUl9BQ0NFU1NfS0VZ + Il0sCiAgICAgICAgICAgICAgICAgICAgICAgICJzZWNyZXRLZXkiOiBzZWxmLm91dF9tYXBbIlJH + V19BRE1JTl9PUFNfVVNFUl9TRUNSRVRfS0VZIl0sCiAgICAgICAgICAgICAgICAgICAgfSwKICAg + ICAgICAgICAgICAgIH0KICAgICAgICAgICAgKQogICAgICAgICMgaWYgJ1JHV19UTFNfQ0VSVCcg + ZXhpc3RzLCB0aGVuIG9ubHkgYWRkIHRoZSAiY2VwaC1yZ3ctdGxzLWNlcnQiIHNlY3JldAogICAg + ICAgIGlmIHNlbGYub3V0X21hcFsiUkdXX1RMU19DRVJUIl06CiAgICAgICAgICAgIGpzb25fb3V0 + LmFwcGVuZCgKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJj + ZXBoLXJndy10bHMtY2VydCIsCiAgICAgICAgICAgICAgICAgICAgImtpbmQiOiAiU2VjcmV0IiwK + ICAgICAgICAgICAgICAgICAgICAiZGF0YSI6IHsKICAgICAgICAgICAgICAgICAgICAgICAgImNl + cnQiOiBzZWxmLm91dF9tYXBbIlJHV19UTFNfQ0VSVCJdLAogICAgICAgICAgICAgICAgICAgIH0s + CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICkKCiAgICAgICAgcmV0dXJuIGpzb24uZHVt + cHMoanNvbl9vdXQpICsgTElORVNFUAoKICAgIGRlZiB1cGdyYWRlX3VzZXJzX3Blcm1pc3Npb25z + KHNlbGYpOgogICAgICAgIHVzZXJzID0gWwogICAgICAgICAgICAiY2xpZW50LmNzaS1jZXBoZnMt + bm9kZSIsCiAgICAgICAgICAgICJjbGllbnQuY3NpLWNlcGhmcy1wcm92aXNpb25lciIsCiAgICAg + ICAgICAgICJjbGllbnQuY3NpLXJiZC1ub2RlIiwKICAgICAgICAgICAgImNsaWVudC5jc2ktcmJk + LXByb3Zpc2lvbmVyIiwKICAgICAgICAgICAgImNsaWVudC5oZWFsdGhjaGVja2VyIiwKICAgICAg + ICBdCiAgICAgICAgaWYgc2VsZi5ydW5fYXNfdXNlciAhPSAiIiBhbmQgc2VsZi5ydW5fYXNfdXNl + ciBub3QgaW4gdXNlcnM6CiAgICAgICAgICAgIHVzZXJzLmFwcGVuZChzZWxmLnJ1bl9hc191c2Vy + KQogICAgICAgIGZvciB1c2VyIGluIHVzZXJzOgogICAgICAgICAgICBzZWxmLnVwZ3JhZGVfdXNl + cl9wZXJtaXNzaW9ucyh1c2VyKQoKICAgIGRlZiBnZXRfcmd3X3Bvb2xfbmFtZV9kdXJpbmdfdXBn + cmFkZShzZWxmLCB1c2VyLCBjYXBzKToKICAgICAgICBpZiB1c2VyID09ICJjbGllbnQuaGVhbHRo + Y2hlY2tlciI6CiAgICAgICAgICAgICMgd2hlbiBhZG1pbiBoYXMgbm90IHByb3ZpZGVkIHJndyBw + b29sIG5hbWUgZHVyaW5nIHVwZ3JhZGUsCiAgICAgICAgICAgICMgZ2V0IHRoZSByZ3cgcG9vbCBu + YW1lIGZyb20gY2xpZW50LmhlYWx0aGNoZWNrZXIgdXNlciB3aGljaCB3YXMgdXNlZCBkdXJpbmcg + Y29ubmVjdGlvbgogICAgICAgICAgICBpZiBub3Qgc2VsZi5fYXJnX3BhcnNlci5yZ3dfcG9vbF9w + cmVmaXg6CiAgICAgICAgICAgICAgICAjIFRvIGdldCB2YWx1ZSAnZGVmYXVsdCcgd2hpY2ggaXMg + cmd3IHBvb2wgbmFtZSBmcm9tICdhbGxvdyByd3ggcG9vbD1kZWZhdWx0LnJndy5tZXRhJwogICAg + ICAgICAgICAgICAgcGF0dGVybiA9IHIicG9vbD0oLio/KVwucmd3XC5tZXRhIgogICAgICAgICAg + ICAgICAgbWF0Y2ggPSByZS5zZWFyY2gocGF0dGVybiwgY2FwcykKICAgICAgICAgICAgICAgIGlm + IG1hdGNoOgogICAgICAgICAgICAgICAgICAgIHNlbGYuX2FyZ19wYXJzZXIucmd3X3Bvb2xfcHJl + Zml4ID0gbWF0Y2guZ3JvdXAoMSkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAg + ICAgICAgcmFpc2UgRXhlY3V0aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgICAg + ICAgICAgImZhaWxlZCB0byBnZXQgcmd3IHBvb2wgbmFtZSBmb3IgdXBncmFkZSIKICAgICAgICAg + ICAgICAgICAgICApCgogICAgZGVmIHVwZ3JhZGVfdXNlcl9wZXJtaXNzaW9ucyhzZWxmLCB1c2Vy + KToKICAgICAgICAjIGNoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHVzZXIgZXhpc3RzIG9yIG5vdAog + ICAgICAgIGNtZF9qc29uID0geyJwcmVmaXgiOiAiYXV0aCBnZXQiLCAiZW50aXR5IjogZiJ7dXNl + cn0iLCAiZm9ybWF0IjogImpzb24ifQogICAgICAgIHJldF92YWwsIGpzb25fb3V0LCBlcnJfbXNn + ID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICBpZiByZXRfdmFs + ICE9IDAgb3IgbGVuKGpzb25fb3V0KSA9PSAwOgogICAgICAgICAgICBwcmludChmInVzZXIge3Vz + ZXJ9IG5vdCBmb3VuZCBmb3IgdXBncmFkaW5nLiIpCiAgICAgICAgICAgIHJldHVybgogICAgICAg + IGV4aXN0aW5nX2NhcHMgPSBqc29uX291dFswXVsiY2FwcyJdCiAgICAgICAgc2VsZi5nZXRfcmd3 + X3Bvb2xfbmFtZV9kdXJpbmdfdXBncmFkZSh1c2VyLCBzdHIoZXhpc3RpbmdfY2FwcykpCiAgICAg + ICAgbmV3X2NhcCwgXyA9IHNlbGYuZ2V0X2NhcHNfYW5kX2VudGl0eSh1c2VyKQogICAgICAgIGNh + cF9rZXlzID0gWyJtb24iLCAibWdyIiwgIm9zZCIsICJtZHMiXQogICAgICAgIGNhcHMgPSBbXQog + ICAgICAgIGZvciBlYWNoQ2FwIGluIGNhcF9rZXlzOgogICAgICAgICAgICBjdXJfY2FwX3ZhbHVl + cyA9IGV4aXN0aW5nX2NhcHMuZ2V0KGVhY2hDYXAsICIiKQogICAgICAgICAgICBuZXdfY2FwX3Zh + bHVlcyA9IG5ld19jYXAuZ2V0KGVhY2hDYXAsICIiKQogICAgICAgICAgICBjdXJfY2FwX3Blcm1f + bGlzdCA9IFsKICAgICAgICAgICAgICAgIHguc3RyaXAoKSBmb3IgeCBpbiBjdXJfY2FwX3ZhbHVl + cy5zcGxpdCgiLCIpIGlmIHguc3RyaXAoKQogICAgICAgICAgICBdCiAgICAgICAgICAgIG5ld19j + YXBfcGVybV9saXN0ID0gWwogICAgICAgICAgICAgICAgeC5zdHJpcCgpIGZvciB4IGluIG5ld19j + YXBfdmFsdWVzLnNwbGl0KCIsIikgaWYgeC5zdHJpcCgpCiAgICAgICAgICAgIF0KICAgICAgICAg + ICAgIyBhcHBlbmQgbmV3X2NhcF9saXN0IHRvIGN1cl9jYXBfbGlzdCB0byBtYWludGFpbiB0aGUg + b3JkZXIgb2YgY2FwcwogICAgICAgICAgICBjdXJfY2FwX3Blcm1fbGlzdC5leHRlbmQobmV3X2Nh + cF9wZXJtX2xpc3QpCiAgICAgICAgICAgICMgZWxpbWluYXRlIGR1cGxpY2F0ZXMgd2l0aG91dCB1 + c2luZyAnc2V0JwogICAgICAgICAgICAjIHNldCByZS1vcmRlcnMgaXRlbXMgaW4gdGhlIGxpc3Qg + YW5kIHdlIGhhdmUgdG8ga2VlcCB0aGUgb3JkZXIKICAgICAgICAgICAgbmV3X2NhcF9saXN0ID0g + W10KICAgICAgICAgICAgW25ld19jYXBfbGlzdC5hcHBlbmQoeCkgZm9yIHggaW4gY3VyX2NhcF9w + ZXJtX2xpc3QgaWYgeCBub3QgaW4gbmV3X2NhcF9saXN0XQogICAgICAgICAgICBleGlzdGluZ19j + YXBzW2VhY2hDYXBdID0gIiwgIi5qb2luKG5ld19jYXBfbGlzdCkKICAgICAgICAgICAgaWYgZXhp + c3RpbmdfY2Fwc1tlYWNoQ2FwXToKICAgICAgICAgICAgICAgIGNhcHMuYXBwZW5kKGVhY2hDYXAp + CiAgICAgICAgICAgICAgICBjYXBzLmFwcGVuZChleGlzdGluZ19jYXBzW2VhY2hDYXBdKQogICAg + ICAgIGNtZF9qc29uID0gewogICAgICAgICAgICAicHJlZml4IjogImF1dGggY2FwcyIsCiAgICAg + ICAgICAgICJlbnRpdHkiOiB1c2VyLAogICAgICAgICAgICAiY2FwcyI6IGNhcHMsCiAgICAgICAg + ICAgICJmb3JtYXQiOiAianNvbiIsCiAgICAgICAgfQogICAgICAgIHJldF92YWwsIGpzb25fb3V0 + LCBlcnJfbXNnID0gc2VsZi5fY29tbW9uX2NtZF9qc29uX2dlbihjbWRfanNvbikKICAgICAgICBp + ZiByZXRfdmFsICE9IDA6CiAgICAgICAgICAgIHJhaXNlIEV4ZWN1dGlvbkZhaWx1cmVFeGNlcHRp + b24oCiAgICAgICAgICAgICAgICBmIidhdXRoIGNhcHMge3VzZXJ9JyBjb21tYW5kIGZhaWxlZC5c + biBFcnJvcjoge2Vycl9tc2d9IgogICAgICAgICAgICApCiAgICAgICAgcHJpbnQoZiJVcGRhdGVk + IHVzZXIge3VzZXJ9IHN1Y2Nlc3NmdWxseS4iKQoKICAgIGRlZiBtYWluKHNlbGYpOgogICAgICAg + IGdlbmVyYXRlZF9vdXRwdXQgPSAiIgogICAgICAgIGlmIHNlbGYuX2FyZ19wYXJzZXIudXBncmFk + ZToKICAgICAgICAgICAgc2VsZi51cGdyYWRlX3VzZXJzX3Blcm1pc3Npb25zKCkKICAgICAgICBl + bGlmIHNlbGYuX2FyZ19wYXJzZXIuZm9ybWF0ID09ICJqc29uIjoKICAgICAgICAgICAgZ2VuZXJh + dGVkX291dHB1dCA9IHNlbGYuZ2VuX2pzb25fb3V0KCkKICAgICAgICBlbGlmIHNlbGYuX2FyZ19w + YXJzZXIuZm9ybWF0ID09ICJiYXNoIjoKICAgICAgICAgICAgZ2VuZXJhdGVkX291dHB1dCA9IHNl + bGYuZ2VuX3NoZWxsX291dCgpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmFpc2UgRXhlY3V0 + aW9uRmFpbHVyZUV4Y2VwdGlvbigKICAgICAgICAgICAgICAgIGYiVW5zdXBwb3J0ZWQgZm9ybWF0 + OiB7c2VsZi5fYXJnX3BhcnNlci5mb3JtYXR9IgogICAgICAgICAgICApCiAgICAgICAgcHJpbnQo + Z2VuZXJhdGVkX291dHB1dCkKICAgICAgICBpZiBzZWxmLm91dHB1dF9maWxlIGFuZCBnZW5lcmF0 + ZWRfb3V0cHV0OgogICAgICAgICAgICBmT3V0ID0gb3BlbihzZWxmLm91dHB1dF9maWxlLCBtb2Rl + PSJ3IiwgZW5jb2Rpbmc9IlVURi04IikKICAgICAgICAgICAgZk91dC53cml0ZShnZW5lcmF0ZWRf + b3V0cHV0KQogICAgICAgICAgICBmT3V0LmNsb3NlKCkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMj + IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIE1BSU4gIyMj + IyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj + IyMjIyMjIyMjIwppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgcmpPYmogPSBSYWRvc0pT + T04oKQogICAgdHJ5OgogICAgICAgIHJqT2JqLm1haW4oKQogICAgZXhjZXB0IEV4ZWN1dGlvbkZh + aWx1cmVFeGNlcHRpb24gYXMgZXJyOgogICAgICAgIHByaW50KGYiRXhlY3V0aW9uIEZhaWxlZDog + e2Vycn0iKQogICAgICAgIHJhaXNlIGVycgogICAgZXhjZXB0IEtleUVycm9yIGFzIGtFcnI6CiAg + ICAgICAgcHJpbnQoZiJLZXlFcnJvcjoge2tFcnJ9IikKICAgIGV4Y2VwdCBPU0Vycm9yIGFzIG9z + RXJyOgogICAgICAgIHByaW50KGYiRXJyb3Igd2hpbGUgdHJ5aW5nIHRvIG91dHB1dCB0aGUgZGF0 + YToge29zRXJyfSIpCiAgICBmaW5hbGx5OgogICAgICAgIHJqT2JqLnNodXRkb3duKCkK name: rook-ceph-operator.v4.17.0 namespace: placeholder spec: From 1a95d6f5338e7284d1ab526fcc35fda1ab3ca137 Mon Sep 17 00:00:00 2001 From: Santosh Pillai Date: Mon, 23 Sep 2024 10:53:19 +0530 Subject: [PATCH 36/54] core: preserve pool application name change default application name is updated inside the `CreatePool` method. Send pool spec as address in order to preserve this change. Signed-off-by: Santosh Pillai --- pkg/daemon/ceph/client/pool.go | 8 ++++---- pkg/operator/ceph/file/filesystem.go | 14 ++++++++------ pkg/operator/ceph/object/objectstore.go | 2 +- pkg/operator/ceph/pool/controller.go | 2 +- pkg/operator/ceph/pool/controller_test.go | 23 ++++++++++++++++++++--- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/pkg/daemon/ceph/client/pool.go b/pkg/daemon/ceph/client/pool.go index 82eae5e77eb9..536f5ff908b9 100644 --- a/pkg/daemon/ceph/client/pool.go +++ b/pkg/daemon/ceph/client/pool.go @@ -178,11 +178,11 @@ func ParsePoolDetails(in []byte) (CephStoragePoolDetails, error) { return poolDetails, nil } -func CreatePool(context *clusterd.Context, clusterInfo *ClusterInfo, clusterSpec *cephv1.ClusterSpec, pool cephv1.NamedPoolSpec) error { +func CreatePool(context *clusterd.Context, clusterInfo *ClusterInfo, clusterSpec *cephv1.ClusterSpec, pool *cephv1.NamedPoolSpec) error { return CreatePoolWithPGs(context, clusterInfo, clusterSpec, pool, DefaultPGCount) } -func CreatePoolWithPGs(context *clusterd.Context, clusterInfo *ClusterInfo, clusterSpec *cephv1.ClusterSpec, pool cephv1.NamedPoolSpec, pgCount string) error { +func CreatePoolWithPGs(context *clusterd.Context, clusterInfo *ClusterInfo, clusterSpec *cephv1.ClusterSpec, pool *cephv1.NamedPoolSpec, pgCount string) error { if pool.Name == "" { return errors.New("pool name must be specified") } @@ -196,7 +196,7 @@ func CreatePoolWithPGs(context *clusterd.Context, clusterInfo *ClusterInfo, clus } if pool.IsReplicated() { - return createReplicatedPoolForApp(context, clusterInfo, clusterSpec, pool, pgCount) + return createReplicatedPoolForApp(context, clusterInfo, clusterSpec, *pool, pgCount) } if !pool.IsErasureCoded() { @@ -215,7 +215,7 @@ func CreatePoolWithPGs(context *clusterd.Context, clusterInfo *ClusterInfo, clus context, clusterInfo, ecProfileName, - pool, + *pool, pgCount, true /* enableECOverwrite */) } diff --git a/pkg/operator/ceph/file/filesystem.go b/pkg/operator/ceph/file/filesystem.go index 8a35ab1a0231..b8e6b36cf303 100644 --- a/pkg/operator/ceph/file/filesystem.go +++ b/pkg/operator/ceph/file/filesystem.go @@ -196,16 +196,17 @@ func createOrUpdatePools(f *Filesystem, context *clusterd.Context, clusterInfo * PoolSpec: spec.MetadataPool, } metadataPool.Application = cephfsApplication - err := cephclient.CreatePool(context, clusterInfo, clusterSpec, metadataPool) + err := cephclient.CreatePool(context, clusterInfo, clusterSpec, &metadataPool) if err != nil { return errors.Wrapf(err, "failed to update metadata pool %q", metadataPool.Name) } // generating the data pool's name dataPoolNames := generateDataPoolNames(f, spec) - for i, dataPool := range spec.DataPools { + for i := range spec.DataPools { + dataPool := spec.DataPools[i] dataPool.Name = dataPoolNames[i] dataPool.Application = cephfsApplication - err := cephclient.CreatePool(context, clusterInfo, clusterSpec, dataPool) + err := cephclient.CreatePool(context, clusterInfo, clusterSpec, &dataPool) if err != nil { return errors.Wrapf(err, "failed to update datapool %q", dataPool.Name) } @@ -269,18 +270,19 @@ func (f *Filesystem) doFilesystemCreate(context *clusterd.Context, clusterInfo * PoolSpec: spec.MetadataPool, } if _, poolFound := reversedPoolMap[metadataPool.Name]; !poolFound { - err = cephclient.CreatePool(context, clusterInfo, clusterSpec, metadataPool) + err = cephclient.CreatePool(context, clusterInfo, clusterSpec, &metadataPool) if err != nil { return errors.Wrapf(err, "failed to create metadata pool %q", metadataPool.Name) } } dataPoolNames := generateDataPoolNames(f, spec) - for i, dataPool := range spec.DataPools { + for i := range spec.DataPools { + dataPool := spec.DataPools[i] dataPool.Name = dataPoolNames[i] dataPool.Application = cephfsApplication if _, poolFound := reversedPoolMap[dataPool.Name]; !poolFound { - err = cephclient.CreatePool(context, clusterInfo, clusterSpec, dataPool) + err = cephclient.CreatePool(context, clusterInfo, clusterSpec, &dataPool) if err != nil { return errors.Wrapf(err, "failed to create data pool %q", dataPool.Name) } diff --git a/pkg/operator/ceph/object/objectstore.go b/pkg/operator/ceph/object/objectstore.go index 794419ac8498..b34642938325 100644 --- a/pkg/operator/ceph/object/objectstore.go +++ b/pkg/operator/ceph/object/objectstore.go @@ -1116,7 +1116,7 @@ func createRGWPool(ctx *Context, cluster *cephv1.ClusterSpec, poolSpec cephv1.Po Name: poolName(ctx.Name, requestedName), PoolSpec: poolSpec, } - if err := cephclient.CreatePoolWithPGs(ctx.Context, ctx.clusterInfo, cluster, pool, pgCount); err != nil { + if err := cephclient.CreatePoolWithPGs(ctx.Context, ctx.clusterInfo, cluster, &pool, pgCount); err != nil { return errors.Wrapf(err, "failed to create pool %q", pool.Name) } // Set the pg_num_min if not the default so the autoscaler won't immediately increase the pg count diff --git a/pkg/operator/ceph/pool/controller.go b/pkg/operator/ceph/pool/controller.go index 24d080ebf644..14f57c3413c2 100644 --- a/pkg/operator/ceph/pool/controller.go +++ b/pkg/operator/ceph/pool/controller.go @@ -381,7 +381,7 @@ func createPool(context *clusterd.Context, clusterInfo *cephclient.ClusterInfo, } // create the pool logger.Infof("creating pool %q in namespace %q", p.Name, clusterInfo.Namespace) - if err := cephclient.CreatePool(context, clusterInfo, clusterSpec, *p); err != nil { + if err := cephclient.CreatePool(context, clusterInfo, clusterSpec, p); err != nil { return errors.Wrapf(err, "failed to configure pool %q", p.Name) } diff --git a/pkg/operator/ceph/pool/controller_test.go b/pkg/operator/ceph/pool/controller_test.go index 29a277370917..74afcc2d78a0 100644 --- a/pkg/operator/ceph/pool/controller_test.go +++ b/pkg/operator/ceph/pool/controller_test.go @@ -52,6 +52,18 @@ func TestCreatePool(t *testing.T) { enabledMgrApp := false clusterInfo := cephclient.AdminTestClusterInfo("mycluster") executor := &exectest.MockExecutor{ + MockExecuteCommandWithTimeout: func(timeout time.Duration, command string, args ...string) (string, error) { + logger.Infof("CommandTimeout: %s %v", command, args) + if command == "rbd" { + if args[0] == "pool" && args[1] == "init" { + // assert that `rbd pool init` is only run when application is set to `rbd` + assert.Equal(t, "rbd", p.Application) + assert.Equal(t, p.Name, args[2]) + return "{}", nil + } + } + return "", nil + }, MockExecuteCommandWithOutput: func(command string, args ...string) (string, error) { logger.Infof("Command: %s %v", command, args) if command == "ceph" { @@ -69,6 +81,7 @@ func TestCreatePool(t *testing.T) { assert.Equal(t, ".mgr", args[4]) assert.Equal(t, "mgr", args[5]) } else { + fmt.Printf("pool - %v", args) assert.Fail(t, fmt.Sprintf("invalid pool %q", args[4])) } } @@ -79,14 +92,12 @@ func TestCreatePool(t *testing.T) { return "{}", nil } else if args[0] == "mirror" && args[2] == "disable" { return "", nil - } else { - assert.Equal(t, []string{"pool", "init", p.Name}, args[0:3]) } - } return "", nil }, } + context := &clusterd.Context{Executor: executor} clusterSpec := &cephv1.ClusterSpec{Storage: cephv1.StorageScopeSpec{Config: map[string]string{cephclient.CrushRootConfigKey: "cluster-crush-root"}}} @@ -95,6 +106,8 @@ func TestCreatePool(t *testing.T) { p.Name = "replicapool" p.Replicated.Size = 1 p.Replicated.RequireSafeReplicaSize = false + // reset the application name + p.Application = "" err := createPool(context, clusterInfo, clusterSpec, p) assert.Nil(t, err) assert.False(t, enabledMetricsApp) @@ -102,6 +115,8 @@ func TestCreatePool(t *testing.T) { t.Run("built-in mgr pool", func(t *testing.T) { p.Name = ".mgr" + // reset the application name + p.Application = "" err := createPool(context, clusterInfo, clusterSpec, p) assert.Nil(t, err) assert.True(t, enabledMgrApp) @@ -112,6 +127,8 @@ func TestCreatePool(t *testing.T) { p.Replicated.Size = 0 p.ErasureCoded.CodingChunks = 1 p.ErasureCoded.DataChunks = 2 + // reset the application name + p.Application = "" err := createPool(context, clusterInfo, clusterSpec, p) assert.Nil(t, err) }) From b7539890e807960aad9223563455efd4e387fbb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:08:33 +0000 Subject: [PATCH 37/54] build(deps): bump go.uber.org/automaxprocs from 1.5.3 to 1.6.0 Bumps [go.uber.org/automaxprocs](https://github.com/uber-go/automaxprocs) from 1.5.3 to 1.6.0. - [Release notes](https://github.com/uber-go/automaxprocs/releases) - [Changelog](https://github.com/uber-go/automaxprocs/blob/master/CHANGELOG.md) - [Commits](https://github.com/uber-go/automaxprocs/compare/v1.5.3...v1.6.0) --- updated-dependencies: - dependency-name: go.uber.org/automaxprocs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 306f52aff40f..db922fc34d1e 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/sykesm/zap-logfmt v0.0.4 - go.uber.org/automaxprocs v1.5.3 + go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.8.0 diff --git a/go.sum b/go.sum index 35c658de2e3a..a23d2eeb71c2 100644 --- a/go.sum +++ b/go.sum @@ -935,8 +935,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= -go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= From c96641f29fcc50854745b33cf0817de8835942e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:54:51 +0000 Subject: [PATCH 38/54] build(deps): bump actions/checkout from 4.1.7 to 4.2.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...d632683dd7b4114ad314bca15554477dd762a938) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 4 +- .github/workflows/canary-integration-test.yml | 42 +++++++++---------- .github/workflows/codegen.yml | 2 +- .github/workflows/codespell.yaml | 4 +- .github/workflows/commitlint.yml | 2 +- .github/workflows/crds-gen.yml | 2 +- .github/workflows/daily-nightly-jobs.yml | 20 ++++----- .github/workflows/docs-check.yml | 2 +- .github/workflows/golangci-lint.yaml | 2 +- .github/workflows/helm-lint.yaml | 2 +- .../integration-test-helm-suite.yaml | 2 +- .../integration-test-keystone-auth-suite.yaml | 2 +- .../workflows/integration-test-mgr-suite.yaml | 2 +- .../integration-test-multi-cluster-suite.yaml | 2 +- .../integration-test-object-suite.yaml | 2 +- .../integration-test-smoke-suite.yaml | 2 +- .../integration-test-upgrade-suite.yaml | 4 +- .../integration-tests-on-release.yaml | 12 +++--- .github/workflows/linters.yaml | 4 +- .github/workflows/mod-check.yml | 2 +- .github/workflows/multus.yaml | 2 +- .github/workflows/push-build.yaml | 2 +- .github/workflows/rbac-gen.yaml | 2 +- .github/workflows/scorecards.yml | 2 +- .github/workflows/shellcheck.yaml | 2 +- .github/workflows/snyk.yaml | 2 +- .github/workflows/unit-test.yml | 2 +- 27 files changed, 65 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 844c71b7cb0e..4187366d735c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: if: "!contains(github.event.pull_request.labels.*.name, 'skip-ci')" steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -74,7 +74,7 @@ jobs: go-version: ["1.22", "1.23"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/canary-integration-test.yml b/.github/workflows/canary-integration-test.yml index 0c0dfcfbee0d..d3e90d0e1a4a 100644 --- a/.github/workflows/canary-integration-test.yml +++ b/.github/workflows/canary-integration-test.yml @@ -25,7 +25,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -332,7 +332,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -409,7 +409,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - name: consider debugging @@ -458,7 +458,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -506,7 +506,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -562,7 +562,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -612,7 +612,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -667,7 +667,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -743,7 +743,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -795,7 +795,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -850,7 +850,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -918,7 +918,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -972,7 +972,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1036,7 +1036,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1122,7 +1122,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1188,7 +1188,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1245,7 +1245,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1504,7 +1504,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1532,7 +1532,7 @@ jobs: matrix: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1561,7 +1561,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -1649,7 +1649,7 @@ jobs: ceph-image: ${{ fromJson(inputs.ceph_images) }} steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/codegen.yml b/.github/workflows/codegen.yml index 987095be6820..79db2fc48ac7 100644 --- a/.github/workflows/codegen.yml +++ b/.github/workflows/codegen.yml @@ -30,7 +30,7 @@ jobs: if: "!contains(github.event.pull_request.labels.*.name, 'skip-ci')" steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/codespell.yaml b/.github/workflows/codespell.yaml index 78f387374c30..970e246e3440 100644 --- a/.github/workflows/codespell.yaml +++ b/.github/workflows/codespell.yaml @@ -24,7 +24,7 @@ jobs: name: codespell runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - name: codespell @@ -53,7 +53,7 @@ jobs: name: misspell runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - name: misspell diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index aa2feb26e75d..72a06e79c98d 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -28,7 +28,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - uses: wagoid/commitlint-github-action@3d28780bbf0365e29b144e272b2121204d5be5f3 # v6.1.2 diff --git a/.github/workflows/crds-gen.yml b/.github/workflows/crds-gen.yml index e243349210ae..1d98ca06458f 100644 --- a/.github/workflows/crds-gen.yml +++ b/.github/workflows/crds-gen.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/daily-nightly-jobs.yml b/.github/workflows/daily-nightly-jobs.yml index af1676170776..ba0e412c55b4 100644 --- a/.github/workflows/daily-nightly-jobs.yml +++ b/.github/workflows/daily-nightly-jobs.yml @@ -21,7 +21,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -123,7 +123,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -163,7 +163,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -203,7 +203,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -243,7 +243,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -283,7 +283,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -323,7 +323,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -363,7 +363,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -404,7 +404,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -444,7 +444,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index 6a61cd4adc38..731802c6884b 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -24,7 +24,7 @@ jobs: name: docs-check runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index a6975e397875..783da5e6539a 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,7 +24,7 @@ jobs: name: golangci-lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 diff --git a/.github/workflows/helm-lint.yaml b/.github/workflows/helm-lint.yaml index 013074f2ec48..c3f1d924bc7c 100644 --- a/.github/workflows/helm-lint.yaml +++ b/.github/workflows/helm-lint.yaml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-helm-suite.yaml b/.github/workflows/integration-test-helm-suite.yaml index 8b9d7e42682d..78839a7c2985 100644 --- a/.github/workflows/integration-test-helm-suite.yaml +++ b/.github/workflows/integration-test-helm-suite.yaml @@ -31,7 +31,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-keystone-auth-suite.yaml b/.github/workflows/integration-test-keystone-auth-suite.yaml index dada9abca9cf..2c3239102a46 100644 --- a/.github/workflows/integration-test-keystone-auth-suite.yaml +++ b/.github/workflows/integration-test-keystone-auth-suite.yaml @@ -31,7 +31,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-mgr-suite.yaml b/.github/workflows/integration-test-mgr-suite.yaml index d88e14f67321..15eb3bfb910e 100644 --- a/.github/workflows/integration-test-mgr-suite.yaml +++ b/.github/workflows/integration-test-mgr-suite.yaml @@ -30,7 +30,7 @@ jobs: kubernetes-versions: ["v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-multi-cluster-suite.yaml b/.github/workflows/integration-test-multi-cluster-suite.yaml index 101fbf2e3841..f250586fad66 100644 --- a/.github/workflows/integration-test-multi-cluster-suite.yaml +++ b/.github/workflows/integration-test-multi-cluster-suite.yaml @@ -31,7 +31,7 @@ jobs: kubernetes-versions: ["v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-object-suite.yaml b/.github/workflows/integration-test-object-suite.yaml index b50e26f52c39..f2757fec4fc1 100644 --- a/.github/workflows/integration-test-object-suite.yaml +++ b/.github/workflows/integration-test-object-suite.yaml @@ -31,7 +31,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-smoke-suite.yaml b/.github/workflows/integration-test-smoke-suite.yaml index 829f1a14459a..d0fd057c1409 100644 --- a/.github/workflows/integration-test-smoke-suite.yaml +++ b/.github/workflows/integration-test-smoke-suite.yaml @@ -31,7 +31,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-test-upgrade-suite.yaml b/.github/workflows/integration-test-upgrade-suite.yaml index 26c6e2fbf7dc..77ae326954db 100644 --- a/.github/workflows/integration-test-upgrade-suite.yaml +++ b/.github/workflows/integration-test-upgrade-suite.yaml @@ -31,7 +31,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -75,7 +75,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/integration-tests-on-release.yaml b/.github/workflows/integration-tests-on-release.yaml index acc16b6987b9..6af0618795e1 100644 --- a/.github/workflows/integration-tests-on-release.yaml +++ b/.github/workflows/integration-tests-on-release.yaml @@ -24,7 +24,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.28.12", "v1.29.7", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -64,7 +64,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.28.12", "v1.29.7", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -105,7 +105,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.28.12", "v1.29.7", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -143,7 +143,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.28.12", "v1.29.7", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -181,7 +181,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.28.12", "v1.29.7", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -222,7 +222,7 @@ jobs: kubernetes-versions: ["v1.26.15", "v1.31.0"] steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml index d995b051c75e..36aa1208e06e 100644 --- a/.github/workflows/linters.yaml +++ b/.github/workflows/linters.yaml @@ -23,7 +23,7 @@ jobs: yaml-linter: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 @@ -41,7 +41,7 @@ jobs: pylint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/mod-check.yml b/.github/workflows/mod-check.yml index 0e852fc61226..13c63f345ad2 100644 --- a/.github/workflows/mod-check.yml +++ b/.github/workflows/mod-check.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/multus.yaml b/.github/workflows/multus.yaml index 9511ae3fbfc7..51aa8cac22c9 100644 --- a/.github/workflows/multus.yaml +++ b/.github/workflows/multus.yaml @@ -36,7 +36,7 @@ jobs: NUMBER_OF_COMPUTE_NODES: 5 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/push-build.yaml b/.github/workflows/push-build.yaml index 6427b86e7c31..1f4e5479cd46 100644 --- a/.github/workflows/push-build.yaml +++ b/.github/workflows/push-build.yaml @@ -21,7 +21,7 @@ jobs: if: github.repository == 'rook/rook' steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/rbac-gen.yaml b/.github/workflows/rbac-gen.yaml index 7123d2a91ff3..842aa974ca49 100644 --- a/.github/workflows/rbac-gen.yaml +++ b/.github/workflows/rbac-gen.yaml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 3e68e8d803cb..5dbe49f0b7b9 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -28,7 +28,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: persist-credentials: false diff --git a/.github/workflows/shellcheck.yaml b/.github/workflows/shellcheck.yaml index ea9f97952b53..89a3551a53e3 100644 --- a/.github/workflows/shellcheck.yaml +++ b/.github/workflows/shellcheck.yaml @@ -24,7 +24,7 @@ jobs: name: Shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Run ShellCheck uses: ludeeus/action-shellcheck@00b27aa7cb85167568cb48a3838b75f4265f2bca # master with: diff --git a/.github/workflows/snyk.yaml b/.github/workflows/snyk.yaml index b8c2459ba132..4aca00a56dbe 100644 --- a/.github/workflows/snyk.yaml +++ b/.github/workflows/snyk.yaml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 73c0f259f644..e7cbab9aa2a6 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -37,7 +37,7 @@ jobs: if: "!contains(github.event.pull_request.labels.*.name, 'skip-ci')" steps: - name: checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 From e82925eb00be2e32a331a4f64b2242ec8ed6af07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:55:06 +0000 Subject: [PATCH 39/54] build(deps): bump github/codeql-action from 3.26.8 to 3.26.9 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.8 to 3.26.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/294a9d92911152fe08befb9ec03e240add280cb3...461ef6c76dfe95d5c364de2f431ddbd31a417628) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 3e68e8d803cb..b9d9c5358864 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 + uses: github/codeql-action/upload-sarif@461ef6c76dfe95d5c364de2f431ddbd31a417628 # v3.26.9 with: sarif_file: results.sarif From 21ca333ed787c6eaf358a4a754ffade22ae8ea7b Mon Sep 17 00:00:00 2001 From: parth-gr Date: Mon, 30 Sep 2024 17:55:27 +0530 Subject: [PATCH 40/54] csi: add sc privileged to logrotate sidecar container deployments on openshift where we need csi container pods to be run on privileged, the logrotate sidecar container was missing the privileged permission letting, side car to not run properly Signed-off-by: parth-gr --- .../ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml | 2 ++ .../template/cephfs/csi-cephfsplugin-provisioner-dep.yaml | 2 ++ pkg/operator/ceph/csi/template/csi-logrotate-sidecar.yaml | 6 ++++++ .../ceph/csi/template/nfs/csi-nfsplugin-holder.yaml | 2 ++ .../csi/template/nfs/csi-nfsplugin-provisioner-dep.yaml | 2 ++ .../ceph/csi/template/rbd/csi-rbdplugin-holder.yaml | 2 ++ .../csi/template/rbd/csi-rbdplugin-provisioner-dep.yaml | 4 ++++ 7 files changed, 20 insertions(+) diff --git a/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml b/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml index 74937c30f62b..911536032c84 100644 --- a/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml +++ b/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml @@ -38,6 +38,8 @@ spec: # This is necessary for the Bidirectional mount propagation securityContext: privileged: true + capabilities: + drop: ["ALL"] image: {{ .CSIPluginImage }} command: - "/bin/sh" diff --git a/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-provisioner-dep.yaml b/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-provisioner-dep.yaml index e2a81a4ac7f5..54bf92cd17f8 100644 --- a/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-provisioner-dep.yaml +++ b/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-provisioner-dep.yaml @@ -254,6 +254,8 @@ spec: {{ if and .Privileged .CSILogRotation }} securityContext: privileged: true + capabilities: + drop: ["ALL"] {{ end }} volumeMounts: - name: socket-dir diff --git a/pkg/operator/ceph/csi/template/csi-logrotate-sidecar.yaml b/pkg/operator/ceph/csi/template/csi-logrotate-sidecar.yaml index e739862fa755..4a546e768e7b 100644 --- a/pkg/operator/ceph/csi/template/csi-logrotate-sidecar.yaml +++ b/pkg/operator/ceph/csi/template/csi-logrotate-sidecar.yaml @@ -28,6 +28,12 @@ command: image: {{ .CSIPluginImage }} imagePullPolicy: IfNotPresent name: log-collector +{{ if .Privileged }} +securityContext: + privileged: true + capabilities: + drop: ["ALL"] +{{ end }} volumeMounts: - mountPath: {{ .CsiLogRootPath }}/logrotate-config/{{ .CsiComponentName }} name: csi-logs-logrotate diff --git a/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-holder.yaml b/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-holder.yaml index 5ee0e6f0674c..2a4c64cf803b 100644 --- a/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-holder.yaml +++ b/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-holder.yaml @@ -38,6 +38,8 @@ spec: # This is necessary for the Bidirectional mount propagation securityContext: privileged: true + capabilities: + drop: ["ALL"] image: {{ .CSIPluginImage }} command: - "/bin/sh" diff --git a/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-provisioner-dep.yaml b/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-provisioner-dep.yaml index 1b29209343fc..7fad6f7bf258 100644 --- a/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-provisioner-dep.yaml +++ b/pkg/operator/ceph/csi/template/nfs/csi-nfsplugin-provisioner-dep.yaml @@ -161,6 +161,8 @@ spec: {{ if and .Privileged .CSILogRotation }} securityContext: privileged: true + capabilities: + drop: ["ALL"] {{ end }} volumeMounts: - name: socket-dir diff --git a/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml b/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml index 9be084d4b791..6191b9729116 100644 --- a/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml +++ b/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml @@ -38,6 +38,8 @@ spec: # This is necessary for the Bidirectional mount propagation securityContext: privileged: true + capabilities: + drop: ["ALL"] image: {{ .CSIPluginImage }} command: - "/bin/sh" diff --git a/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-provisioner-dep.yaml b/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-provisioner-dep.yaml index ed25616151ed..5f8b23974a3e 100644 --- a/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-provisioner-dep.yaml +++ b/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-provisioner-dep.yaml @@ -207,6 +207,8 @@ spec: {{ if and .Privileged .CSILogRotation }} securityContext: privileged: true + capabilities: + drop: ["ALL"] {{ end }} volumeMounts: - name: socket-dir @@ -263,6 +265,8 @@ spec: {{ if and .Privileged .CSILogRotation }} securityContext: privileged: true + capabilities: + drop: ["ALL"] {{ end }} volumeMounts: - name: socket-dir From 05ac99c0c011d8ecb4f5041e6b868eeba5cbd96b Mon Sep 17 00:00:00 2001 From: Xinliang Liu Date: Thu, 26 Sep 2024 10:34:35 +0000 Subject: [PATCH 41/54] ci: fix canary-arm64 job Fix OSD isn't up. As sdb device might change to vdb in the runner, let find_extra_block_dev() exclude the nbd devices and find the proper extra device for OSD. Clean up the nbd devices after the test job is running. Fix logs artifact upload twice and collect logs before clean up. Signed-off-by: Xinliang Liu --- .github/workflows/daily-nightly-jobs.yml | 22 +++++++--------------- tests/scripts/github-action-helper.sh | 2 +- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.github/workflows/daily-nightly-jobs.yml b/.github/workflows/daily-nightly-jobs.yml index ba0e412c55b4..65fd14ccb35d 100644 --- a/.github/workflows/daily-nightly-jobs.yml +++ b/.github/workflows/daily-nightly-jobs.yml @@ -16,8 +16,6 @@ jobs: canary-arm64: runs-on: [self-hosted, ubuntu-20.04-arm64, ARM64] if: github.repository == 'rook/rook' - env: - BLOCK: /dev/sdb steps: - name: checkout @@ -91,6 +89,12 @@ jobs: - name: wait for ceph to be ready run: tests/scripts/github-action-helper.sh wait_for_ceph_to_be_ready "mon,mgr,osd,mds,rgw,rbd_mirror,fs_mirror" 1 + - name: collect common logs + if: always() + uses: ./.github/workflows/collect-logs + with: + name: canary-arm64 + - name: teardown minikube, docker and kubectl if: always() run: | @@ -100,24 +104,12 @@ jobs: sudo service docker stop sudo rm -rf /usr/local/bin/minikube sudo rm -rf /usr/local/bin/kubectl + sudo modprobe -r nbd - name: remove /usr/bin/yq if: always() run: sudo rm -rf /usr/bin/yq - - name: collect common logs - if: always() - uses: ./.github/workflows/collect-logs - with: - name: canary-arm64 - - - name: upload canary test result - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - if: always() - with: - name: canary-arm64 - path: test - smoke-suite-quincy-devel: if: github.repository == 'rook/rook' runs-on: ubuntu-22.04 diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index 277a6f5f5739..0756a0f77360 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -30,7 +30,7 @@ function find_extra_block_dev() { boot_dev="$(sudo lsblk --noheading --list --output MOUNTPOINT,PKNAME | grep boot | awk '{print $2}')" echo " == find_extra_block_dev(): boot_dev='$boot_dev'" >/dev/stderr # debug in case of future errors # --nodeps ignores partitions - extra_dev="$(sudo lsblk --noheading --list --nodeps --output KNAME | grep -v loop | grep -v "$boot_dev" | head -1)" + extra_dev="$(sudo lsblk --noheading --list --nodeps --output KNAME | egrep -v "($boot_dev|loop|nbd)" | head -1)" echo " == find_extra_block_dev(): extra_dev='$extra_dev'" >/dev/stderr # debug in case of future errors echo "$extra_dev" # output of function } From ab8fd90aa642ea670fd8786e4b9bbb04b6beb8e2 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 26 Sep 2024 14:11:53 +0200 Subject: [PATCH 42/54] core: add ROOK_REVISION_HISTORY_LIMIT operator setting This adds an operator config setting ROOK_REVISION_HISTORY_LIMIT defaulting to kubernetes'value for RevisionHistoryLimit. If configured, the provided value will be used as RevisionHistoryLimit for all Deployments rook creates. Fixes: #12722 Signed-off-by: Michael Adam --- deploy/examples/operator-openshift.yaml | 2 ++ deploy/examples/operator.yaml | 2 ++ pkg/operator/ceph/cluster/mgr/spec.go | 1 + pkg/operator/ceph/cluster/mon/spec.go | 1 + .../ceph/cluster/nodedaemon/exporter.go | 1 + pkg/operator/ceph/cluster/osd/spec.go | 1 + pkg/operator/ceph/cluster/rbd/spec.go | 1 + pkg/operator/ceph/controller.go | 1 + .../ceph/controller/controller_utils.go | 26 +++++++++++++++++- .../ceph/controller/controller_utils_test.go | 27 +++++++++++++++++++ pkg/operator/ceph/file/mds/spec.go | 5 ++-- pkg/operator/ceph/file/mirror/spec.go | 1 + pkg/operator/ceph/nfs/spec.go | 1 + pkg/operator/ceph/object/cosi/spec.go | 5 ++-- pkg/operator/ceph/object/spec.go | 1 + pkg/operator/discover/discover.go | 1 + 16 files changed, 71 insertions(+), 6 deletions(-) diff --git a/deploy/examples/operator-openshift.yaml b/deploy/examples/operator-openshift.yaml index 82ed8f14f141..105434007652 100644 --- a/deploy/examples/operator-openshift.yaml +++ b/deploy/examples/operator-openshift.yaml @@ -638,6 +638,8 @@ data: # (Optional) QPS to use while communicating with the kubernetes apiserver. # CSI_KUBE_API_QPS: "5.0" + # RevisionHistoryLimit value for all deployments created by rook. + # ROOK_REVISION_HISTORY_LIMIT: "3" --- # The deployment for the rook operator # OLM: BEGIN OPERATOR DEPLOYMENT diff --git a/deploy/examples/operator.yaml b/deploy/examples/operator.yaml index e0faa4d2a6b4..4802f5658f20 100644 --- a/deploy/examples/operator.yaml +++ b/deploy/examples/operator.yaml @@ -568,6 +568,8 @@ data: # (Optional) QPS to use while communicating with the kubernetes apiserver. # CSI_KUBE_API_QPS: "5.0" + # RevisionHistoryLimit value for all deployments created by rook. + # ROOK_REVISION_HISTORY_LIMIT: "3" --- # OLM: BEGIN OPERATOR DEPLOYMENT apiVersion: apps/v1 diff --git a/pkg/operator/ceph/cluster/mgr/spec.go b/pkg/operator/ceph/cluster/mgr/spec.go index 01cfb5f2b617..1c38893d0789 100644 --- a/pkg/operator/ceph/cluster/mgr/spec.go +++ b/pkg/operator/ceph/cluster/mgr/spec.go @@ -128,6 +128,7 @@ func (c *Cluster) makeDeployment(mgrConfig *mgrConfig) (*apps.Deployment, error) Labels: c.getPodLabels(mgrConfig, true), }, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: c.getPodLabels(mgrConfig, false), }, diff --git a/pkg/operator/ceph/cluster/mon/spec.go b/pkg/operator/ceph/cluster/mon/spec.go index 9d79ace7ba4e..8901f26bd919 100644 --- a/pkg/operator/ceph/cluster/mon/spec.go +++ b/pkg/operator/ceph/cluster/mon/spec.go @@ -108,6 +108,7 @@ func (c *Cluster) makeDeployment(monConfig *monConfig, canary bool) (*apps.Deplo } replicaCount := int32(1) d.Spec = apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: c.getLabels(monConfig, canary, false), }, diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter.go b/pkg/operator/ceph/cluster/nodedaemon/exporter.go index dec1809eb163..ab4debc27ef1 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/exporter.go +++ b/pkg/operator/ceph/cluster/nodedaemon/exporter.go @@ -77,6 +77,7 @@ func (r *ReconcileNode) createOrUpdateCephExporter(node corev1.Node, tolerations Namespace: cephCluster.GetNamespace(), }, } + deploy.Spec.RevisionHistoryLimit = controller.RevisionHistoryLimit() err := controllerutil.SetControllerReference(&cephCluster, deploy, r.scheme) if err != nil { return controllerutil.OperationResultNone, errors.Errorf("failed to set owner reference of ceph-exporter deployment %q", deploy.Name) diff --git a/pkg/operator/ceph/cluster/osd/spec.go b/pkg/operator/ceph/cluster/osd/spec.go index b44aa4ee3225..33477cdbf88b 100644 --- a/pkg/operator/ceph/cluster/osd/spec.go +++ b/pkg/operator/ceph/cluster/osd/spec.go @@ -713,6 +713,7 @@ func (c *Cluster) makeDeployment(osdProps osdProperties, osd *OSDInfo, provision OsdIdLabelKey: fmt.Sprintf("%d", osd.ID), }, }, + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Strategy: apps.DeploymentStrategy{ Type: apps.RecreateDeploymentStrategyType, }, diff --git a/pkg/operator/ceph/cluster/rbd/spec.go b/pkg/operator/ceph/cluster/rbd/spec.go index 2b846eae826d..dd627232b2f1 100644 --- a/pkg/operator/ceph/cluster/rbd/spec.go +++ b/pkg/operator/ceph/cluster/rbd/spec.go @@ -82,6 +82,7 @@ func (r *ReconcileCephRBDMirror) makeDeployment(daemonConfig *daemonConfig, rbdM Labels: controller.CephDaemonAppLabels(AppName, rbdMirror.Namespace, config.RbdMirrorType, daemonConfig.DaemonID, rbdMirror.Name, "cephrbdmirrors.ceph.rook.io", true), }, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: podSpec.Labels, }, diff --git a/pkg/operator/ceph/controller.go b/pkg/operator/ceph/controller.go index 238dd29bd43b..c674854a5727 100644 --- a/pkg/operator/ceph/controller.go +++ b/pkg/operator/ceph/controller.go @@ -133,6 +133,7 @@ func (r *ReconcileConfig) reconcile(request reconcile.Request) (reconcile.Result opcontroller.SetAllowLoopDevices(r.config.Parameters) opcontroller.SetEnforceHostNetwork(r.config.Parameters) + opcontroller.SetRevisionHistoryLimit(r.config.Parameters) logger.Infof("%s done reconciling", controllerName) return reconcile.Result{}, nil diff --git a/pkg/operator/ceph/controller/controller_utils.go b/pkg/operator/ceph/controller/controller_utils.go index f5cc1ca1da27..9d5e207522c4 100644 --- a/pkg/operator/ceph/controller/controller_utils.go +++ b/pkg/operator/ceph/controller/controller_utils.go @@ -54,6 +54,9 @@ const ( enforceHostNetworkSettingName string = "ROOK_ENFORCE_HOST_NETWORK" enforceHostNetworkDefaultValue string = "false" + revisionHistoryLimitSettingName string = "ROOK_REVISION_HISTORY_LIMIT" + revisionHistoryLimitDefaultValue string = "" + // UninitializedCephConfigError refers to the error message printed by the Ceph CLI when there is no ceph configuration file // This typically is raised when the operator has not finished initializing UninitializedCephConfigError = "error calling conf_read_file" @@ -86,7 +89,8 @@ var ( OperatorCephBaseImageVersion string // loopDevicesAllowed indicates whether loop devices are allowed to be used - loopDevicesAllowed = false + loopDevicesAllowed = false + revisionHistoryLimit *int32 = nil ) func DiscoveryDaemonEnabled(data map[string]string) bool { @@ -133,6 +137,26 @@ func EnforceHostNetwork() bool { return cephv1.EnforceHostNetwork() } +func SetRevisionHistoryLimit(data map[string]string) { + strval := k8sutil.GetValue(data, revisionHistoryLimitSettingName, revisionHistoryLimitDefaultValue) + if strval != "" { + numval, err := strconv.ParseInt(strval, 10, 32) + if err != nil { + logger.Warningf("failed to parse value %q for %q. assuming default value.", strval, revisionHistoryLimitSettingName) + revisionHistoryLimit = nil + return + + } + limit := int32(numval) + revisionHistoryLimit = &limit + } + +} + +func RevisionHistoryLimit() *int32 { + return revisionHistoryLimit +} + // canIgnoreHealthErrStatusInReconcile determines whether a status of HEALTH_ERR in the CephCluster can be ignored safely. func canIgnoreHealthErrStatusInReconcile(cephCluster cephv1.CephCluster, controllerName string) bool { // Get a list of all the keys causing the HEALTH_ERR status. diff --git a/pkg/operator/ceph/controller/controller_utils_test.go b/pkg/operator/ceph/controller/controller_utils_test.go index 532cc0bcbecc..82774c8c7e06 100644 --- a/pkg/operator/ceph/controller/controller_utils_test.go +++ b/pkg/operator/ceph/controller/controller_utils_test.go @@ -133,6 +133,33 @@ func TestSetEnforceHostNetwork(t *testing.T) { assert.False(t, EnforceHostNetwork()) } +func TestSetRevisionHistoryLimit(t *testing.T) { + opConfig := map[string]string{} + t.Run("ROOK_REVISION_HISTORY_LIMIT: test default value", func(t *testing.T) { + SetRevisionHistoryLimit(opConfig) + assert.Nil(t, RevisionHistoryLimit()) + }) + + var value string = "foo" + t.Run("ROOK_REVISION_HISTORY_LIMIT: test invalid value 'foo'", func(t *testing.T) { + opConfig[revisionHistoryLimitSettingName] = value + SetRevisionHistoryLimit(opConfig) + assert.Nil(t, RevisionHistoryLimit()) + }) + + t.Run("ROOK_REVISION_HISTORY_LIMIT: test empty string value", func(t *testing.T) { + value = "" + opConfig[revisionHistoryLimitSettingName] = value + SetRevisionHistoryLimit(opConfig) + assert.Nil(t, RevisionHistoryLimit()) + }) + t.Run("ROOK_REVISION_HISTORY_LIMIT: test valig value '10'", func(t *testing.T) { + value = "10" + opConfig[revisionHistoryLimitSettingName] = value + SetRevisionHistoryLimit(opConfig) + assert.Equal(t, int32(10), *RevisionHistoryLimit()) + }) +} func TestIsReadyToReconcile(t *testing.T) { scheme := scheme.Scheme scheme.AddKnownTypes(cephv1.SchemeGroupVersion, &cephv1.CephCluster{}, &cephv1.CephClusterList{}) diff --git a/pkg/operator/ceph/file/mds/spec.go b/pkg/operator/ceph/file/mds/spec.go index 426957a2409c..31065deef622 100644 --- a/pkg/operator/ceph/file/mds/spec.go +++ b/pkg/operator/ceph/file/mds/spec.go @@ -94,8 +94,9 @@ func (c *Cluster) makeDeployment(mdsConfig *mdsConfig, fsNamespacedname types.Na Selector: &metav1.LabelSelector{ MatchLabels: c.podLabels(mdsConfig, false), }, - Template: podSpec, - Replicas: &replicas, + RevisionHistoryLimit: controller.RevisionHistoryLimit(), + Template: podSpec, + Replicas: &replicas, Strategy: apps.DeploymentStrategy{ Type: apps.RecreateDeploymentStrategyType, }, diff --git a/pkg/operator/ceph/file/mirror/spec.go b/pkg/operator/ceph/file/mirror/spec.go index 8e9153b5bc28..d13d1848bec9 100644 --- a/pkg/operator/ceph/file/mirror/spec.go +++ b/pkg/operator/ceph/file/mirror/spec.go @@ -79,6 +79,7 @@ func (r *ReconcileFilesystemMirror) makeDeployment(daemonConfig *daemonConfig, f Annotations: fsMirror.Spec.Annotations, Labels: controller.CephDaemonAppLabels(AppName, fsMirror.Namespace, config.FilesystemMirrorType, userID, fsMirror.Name, "cephfilesystemmirrors.ceph.rook.io", true)}, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: podSpec.Labels, }, diff --git a/pkg/operator/ceph/nfs/spec.go b/pkg/operator/ceph/nfs/spec.go index 10edf9399f6c..5834acf5c781 100644 --- a/pkg/operator/ceph/nfs/spec.go +++ b/pkg/operator/ceph/nfs/spec.go @@ -191,6 +191,7 @@ func (r *ReconcileCephNFS) makeDeployment(nfs *cephv1.CephNFS, cfg daemonConfig) // Multiple replicas of the nfs service would be handled by creating a service and a new deployment for each one, rather than increasing the pod count here replicas := int32(1) deployment.Spec = apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: getLabels(nfs, cfg.ID, false), }, diff --git a/pkg/operator/ceph/object/cosi/spec.go b/pkg/operator/ceph/object/cosi/spec.go index 50bf737c5bab..f0cc0a5a990e 100644 --- a/pkg/operator/ceph/object/cosi/spec.go +++ b/pkg/operator/ceph/object/cosi/spec.go @@ -43,7 +43,6 @@ func createCephCOSIDriverDeployment(cephCOSIDriver *cephv1.CephCOSIDriver) (*app replica := int32(1) minReadySeconds := int32(30) progressDeadlineSeconds := int32(600) - revisionHistoryLimit := int32(3) cephcosidriverDeployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -52,7 +51,8 @@ func createCephCOSIDriverDeployment(cephCOSIDriver *cephv1.CephCOSIDriver) (*app Labels: getCOSILabels(cephCOSIDriver.Name, cephCOSIDriver.Namespace), }, Spec: appsv1.DeploymentSpec{ - Replicas: &replica, + RevisionHistoryLimit: controller.RevisionHistoryLimit(), + Replicas: &replica, Selector: &metav1.LabelSelector{ MatchLabels: getCOSILabels(cephCOSIDriver.Name, cephCOSIDriver.Namespace), }, @@ -60,7 +60,6 @@ func createCephCOSIDriverDeployment(cephCOSIDriver *cephv1.CephCOSIDriver) (*app Strategy: strategy, MinReadySeconds: minReadySeconds, ProgressDeadlineSeconds: &progressDeadlineSeconds, - RevisionHistoryLimit: &revisionHistoryLimit, }, } diff --git a/pkg/operator/ceph/object/spec.go b/pkg/operator/ceph/object/spec.go index cd34dab8d9fa..b72910fb9b55 100644 --- a/pkg/operator/ceph/object/spec.go +++ b/pkg/operator/ceph/object/spec.go @@ -117,6 +117,7 @@ func (c *clusterConfig) createDeployment(rgwConfig *rgwConfig) (*apps.Deployment Labels: getLabels(c.store.Name, c.store.Namespace, true), }, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: getLabels(c.store.Name, c.store.Namespace, false), }, diff --git a/pkg/operator/discover/discover.go b/pkg/operator/discover/discover.go index ee4cdb3f6369..b895badd7e84 100644 --- a/pkg/operator/discover/discover.go +++ b/pkg/operator/discover/discover.go @@ -102,6 +102,7 @@ func (d *Discover) createDiscoverDaemonSet(ctx context.Context, namespace, disco Labels: getLabels(), }, Spec: apps.DaemonSetSpec{ + RevisionHistoryLimit: opcontroller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ "app": discoverDaemonsetName, From 20f00312805a2b17fb89a465614f931e19a12567 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 2 Oct 2024 16:23:42 +0200 Subject: [PATCH 43/54] helm: add revisionHistoryLimit setting Co-authored-by: Travis Nielsen Signed-off-by: Michael Adam --- Documentation/Helm-Charts/operator-chart.md | 1 + deploy/charts/rook-ceph/templates/configmap.yaml | 3 +++ deploy/charts/rook-ceph/values.yaml | 3 +++ 3 files changed, 7 insertions(+) diff --git a/Documentation/Helm-Charts/operator-chart.md b/Documentation/Helm-Charts/operator-chart.md index ebb42204fb1f..07acac83603e 100644 --- a/Documentation/Helm-Charts/operator-chart.md +++ b/Documentation/Helm-Charts/operator-chart.md @@ -163,6 +163,7 @@ The following table lists the configurable parameters of the rook-operator chart | `rbacAggregate.enableOBCs` | If true, create a ClusterRole aggregated to [user facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) for objectbucketclaims | `false` | | `rbacEnable` | If true, create & use RBAC resources | `true` | | `resources` | Pod resource requests & limits | `{"limits":{"memory":"512Mi"},"requests":{"cpu":"200m","memory":"128Mi"}}` | +| `revisionHistoryLimit` | The revision history limit for all pods created by Rook. If blank, the K8s default is 10. | `nil` | | `scaleDownOperator` | If true, scale down the rook operator. This is useful for administrative actions where the rook operator must be scaled down, while using gitops style tooling to deploy your helm charts. | `false` | | `tolerations` | List of Kubernetes [`tolerations`](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to add to the Deployment. | `[]` | | `unreachableNodeTolerationSeconds` | Delay to use for the `node.kubernetes.io/unreachable` pod failure toleration to override the Kubernetes default of 5 minutes | `5` | diff --git a/deploy/charts/rook-ceph/templates/configmap.yaml b/deploy/charts/rook-ceph/templates/configmap.yaml index ea1c5230f107..f0f8987dc0d5 100644 --- a/deploy/charts/rook-ceph/templates/configmap.yaml +++ b/deploy/charts/rook-ceph/templates/configmap.yaml @@ -20,6 +20,9 @@ data: {{- if .Values.discoverDaemonUdev }} DISCOVER_DAEMON_UDEV_BLACKLIST: {{ .Values.discoverDaemonUdev | quote }} {{- end }} +{{- if .Values.revisionHistoryLimit }} + ROOK_REVISION_HISTORY_LIMIT: {{ .Values.revisionHistoryLimit | quote }} +{{- end }} {{- if .Values.csi }} ROOK_CSI_ENABLE_RBD: {{ .Values.csi.enableRbdDriver | quote }} ROOK_CSI_ENABLE_CEPHFS: {{ .Values.csi.enableCephfsDriver | quote }} diff --git a/deploy/charts/rook-ceph/values.yaml b/deploy/charts/rook-ceph/values.yaml index 4cf7c298d6a4..c630bcd33b23 100644 --- a/deploy/charts/rook-ceph/values.yaml +++ b/deploy/charts/rook-ceph/values.yaml @@ -636,6 +636,9 @@ hostpathRequiresPrivileged: false # -- Disable automatic orchestration when new devices are discovered. disableDeviceHotplug: false +# -- The revision history limit for all pods created by Rook. If blank, the K8s default is 10. +revisionHistoryLimit: + # -- Blacklist certain disks according to the regex provided. discoverDaemonUdev: From 810de394e7196a185b4544e98311109e1d1f305b Mon Sep 17 00:00:00 2001 From: Travis Nielsen Date: Wed, 2 Oct 2024 07:51:05 -0600 Subject: [PATCH 44/54] helm: add enforce host network setting The ROOK_ENFORCE_HOST_NETWORK option was implemented recently and now we add the helm setting to expose this new setting in the rook chart. Signed-off-by: Travis Nielsen --- Documentation/Helm-Charts/operator-chart.md | 1 + deploy/charts/rook-ceph/templates/configmap.yaml | 4 ++++ deploy/charts/rook-ceph/values.yaml | 3 +++ deploy/examples/operator-openshift.yaml | 4 ++++ deploy/examples/operator.yaml | 4 ++++ tests/framework/installer/ceph_helm_installer.go | 2 ++ 6 files changed, 18 insertions(+) diff --git a/Documentation/Helm-Charts/operator-chart.md b/Documentation/Helm-Charts/operator-chart.md index 07acac83603e..a78ddc1ad4e7 100644 --- a/Documentation/Helm-Charts/operator-chart.md +++ b/Documentation/Helm-Charts/operator-chart.md @@ -149,6 +149,7 @@ The following table lists the configurable parameters of the rook-operator chart | `discoveryDaemonInterval` | Set the discovery daemon device discovery interval (default to 60m) | `"60m"` | | `enableDiscoveryDaemon` | Enable discovery daemon | `false` | | `enableOBCWatchOperatorNamespace` | Whether the OBC provisioner should watch on the operator namespace or not, if not the namespace of the cluster will be used | `true` | +| `enforceHostNetwork` | Whether to create all Rook pods to run on the host network, for example in environments where a CNI is not enabled | `false` | | `hostpathRequiresPrivileged` | Runs Ceph Pods as privileged to be able to write to `hostPaths` in OpenShift with SELinux restrictions. | `false` | | `image.pullPolicy` | Image pull policy | `"IfNotPresent"` | | `image.repository` | Image | `"docker.io/rook/ceph"` | diff --git a/deploy/charts/rook-ceph/templates/configmap.yaml b/deploy/charts/rook-ceph/templates/configmap.yaml index f0f8987dc0d5..c29dbcd74fc9 100644 --- a/deploy/charts/rook-ceph/templates/configmap.yaml +++ b/deploy/charts/rook-ceph/templates/configmap.yaml @@ -23,6 +23,10 @@ data: {{- if .Values.revisionHistoryLimit }} ROOK_REVISION_HISTORY_LIMIT: {{ .Values.revisionHistoryLimit | quote }} {{- end }} +{{- if .Values.enforceHostNetwork }} + ROOK_ENFORCE_HOST_NETWORK: {{ .Values.enforceHostNetwork | quote }} +{{- end }} + {{- if .Values.csi }} ROOK_CSI_ENABLE_RBD: {{ .Values.csi.enableRbdDriver | quote }} ROOK_CSI_ENABLE_CEPHFS: {{ .Values.csi.enableCephfsDriver | quote }} diff --git a/deploy/charts/rook-ceph/values.yaml b/deploy/charts/rook-ceph/values.yaml index c630bcd33b23..7e3d47bb3c04 100644 --- a/deploy/charts/rook-ceph/values.yaml +++ b/deploy/charts/rook-ceph/values.yaml @@ -633,6 +633,9 @@ discover: # -- Runs Ceph Pods as privileged to be able to write to `hostPaths` in OpenShift with SELinux restrictions. hostpathRequiresPrivileged: false +# -- Whether to create all Rook pods to run on the host network, for example in environments where a CNI is not enabled +enforceHostNetwork: false + # -- Disable automatic orchestration when new devices are discovered. disableDeviceHotplug: false diff --git a/deploy/examples/operator-openshift.yaml b/deploy/examples/operator-openshift.yaml index 105434007652..876a029f0df3 100644 --- a/deploy/examples/operator-openshift.yaml +++ b/deploy/examples/operator-openshift.yaml @@ -638,6 +638,10 @@ data: # (Optional) QPS to use while communicating with the kubernetes apiserver. # CSI_KUBE_API_QPS: "5.0" + + # Whether to create all Rook pods to run on the host network, for example in environments where a CNI is not enabled + ROOK_ENFORCE_HOST_NETWORK: "false" + # RevisionHistoryLimit value for all deployments created by rook. # ROOK_REVISION_HISTORY_LIMIT: "3" --- diff --git a/deploy/examples/operator.yaml b/deploy/examples/operator.yaml index 4802f5658f20..667c718ba8b6 100644 --- a/deploy/examples/operator.yaml +++ b/deploy/examples/operator.yaml @@ -568,6 +568,10 @@ data: # (Optional) QPS to use while communicating with the kubernetes apiserver. # CSI_KUBE_API_QPS: "5.0" + + # Whether to create all Rook pods to run on the host network, for example in environments where a CNI is not enabled + ROOK_ENFORCE_HOST_NETWORK: "false" + # RevisionHistoryLimit value for all deployments created by rook. # ROOK_REVISION_HISTORY_LIMIT: "3" --- diff --git a/tests/framework/installer/ceph_helm_installer.go b/tests/framework/installer/ceph_helm_installer.go index a8042469cae8..13d1c69fb63d 100644 --- a/tests/framework/installer/ceph_helm_installer.go +++ b/tests/framework/installer/ceph_helm_installer.go @@ -57,6 +57,8 @@ func (h *CephInstaller) configureRookOperatorViaHelm(upgrade bool) error { "enableDiscoveryDaemon": h.settings.EnableDiscovery, "image": map[string]interface{}{"tag": h.settings.RookVersion}, "monitoring": map[string]interface{}{"enabled": true}, + "revisionHistoryLimit": "3", + "enforceHostNetwork": "false", } values["csi"] = map[string]interface{}{ "csiRBDProvisionerResource": nil, From b665d7a7b7b65aa9dde62f79e77445926c7064c4 Mon Sep 17 00:00:00 2001 From: Travis Nielsen Date: Wed, 2 Oct 2024 14:11:55 -0600 Subject: [PATCH 45/54] core: remove support for ceph quincy Given that Ceph Quincy (v17) is past end of life, remove Quincy from the supported Ceph versions, examples, and documentation. Supported versions now include only Reef and Squid. Signed-off-by: Travis Nielsen --- .github/workflows/daily-nightly-jobs.yml | 122 +----------------- .../CRDs/Cluster/ceph-cluster-crd.md | 14 +- .../external-cluster/external-cluster.md | 2 +- .../external-cluster/provider-export.md | 2 +- .../Object-Storage/ceph-object-store-crd.md | 4 +- Documentation/CRDs/ceph-nfs-crd.md | 12 -- Documentation/CRDs/specification.md | 7 +- .../Storage-Configuration/NFS/nfs-security.md | 5 - .../Storage-Configuration/NFS/nfs.md | 6 +- .../ceph-object-bucket-notifications.md | 2 +- .../Object-Storage-RGW/object-storage.md | 4 +- Documentation/Upgrade/ceph-upgrade.md | 12 +- PendingReleaseNotes.md | 1 + deploy/charts/rook-ceph-cluster/values.yaml | 8 +- .../charts/rook-ceph/templates/resources.yaml | 5 +- deploy/examples/cluster.yaml | 10 +- deploy/examples/crds.yaml | 5 +- design/ceph/ceph-nfs-ganesha.md | 4 +- design/ceph/object/ceph-sse-s3.md | 2 - pkg/apis/ceph.rook.io/v1/types.go | 5 +- pkg/daemon/ceph/client/config_test.go | 7 +- pkg/daemon/ceph/client/upgrade.go | 4 +- pkg/daemon/ceph/client/upgrade_test.go | 4 +- pkg/daemon/ceph/osd/daemon.go | 8 -- pkg/daemon/ceph/osd/daemon_test.go | 17 +-- pkg/operator/ceph/cluster/cephstatus_test.go | 2 - .../ceph/cluster/mgr/dashboard_test.go | 2 +- .../ceph/cluster/mgr/orchestrator_test.go | 2 +- pkg/operator/ceph/cluster/mon/mon_test.go | 12 +- pkg/operator/ceph/cluster/mon/node_test.go | 12 +- pkg/operator/ceph/cluster/osd/create_test.go | 4 +- .../ceph/cluster/osd/integration_test.go | 2 +- pkg/operator/ceph/cluster/osd/osd_test.go | 10 +- pkg/operator/ceph/cluster/osd/spec.go | 29 +---- pkg/operator/ceph/cluster/osd/spec_test.go | 10 +- pkg/operator/ceph/cluster/osd/status_test.go | 2 +- pkg/operator/ceph/cluster/osd/update_test.go | 4 +- .../ceph/cluster/rbd/controller_test.go | 2 +- pkg/operator/ceph/cluster/rbd/spec_test.go | 2 +- pkg/operator/ceph/cluster/version_test.go | 40 +++--- pkg/operator/ceph/config/defaults.go | 5 - pkg/operator/ceph/config/monstore.go | 2 +- .../ceph/controller/predicate_test.go | 8 +- .../disruption/clusterdisruption/osd_test.go | 2 +- pkg/operator/ceph/file/controller_test.go | 2 +- pkg/operator/ceph/file/filesystem_test.go | 117 ++++++++++------- pkg/operator/ceph/file/mds/spec_test.go | 2 +- .../ceph/file/mirror/controller_test.go | 2 +- pkg/operator/ceph/file/mirror/spec_test.go | 2 +- pkg/operator/ceph/nfs/controller_test.go | 2 +- pkg/operator/ceph/nfs/nfs_test.go | 4 +- pkg/operator/ceph/nfs/security_test.go | 8 +- pkg/operator/ceph/nfs/spec_test.go | 4 +- pkg/operator/ceph/object/config.go | 2 +- pkg/operator/ceph/object/config_test.go | 2 +- pkg/operator/ceph/object/controller_test.go | 16 +-- pkg/operator/ceph/object/objectstore.go | 26 +--- pkg/operator/ceph/object/objectstore_test.go | 6 - pkg/operator/ceph/object/spec.go | 6 - pkg/operator/ceph/object/spec_test.go | 22 ++-- pkg/operator/ceph/version/version.go | 18 +-- pkg/operator/ceph/version/version_test.go | 31 ++--- tests/framework/installer/ceph_installer.go | 14 +- tests/integration/ceph_auth_keystone_test.go | 2 +- tests/integration/ceph_helm_test.go | 2 +- tests/integration/ceph_multi_cluster_test.go | 4 +- tests/integration/ceph_upgrade_test.go | 49 +------ 67 files changed, 236 insertions(+), 531 deletions(-) diff --git a/.github/workflows/daily-nightly-jobs.yml b/.github/workflows/daily-nightly-jobs.yml index 65fd14ccb35d..a8577c38e0cf 100644 --- a/.github/workflows/daily-nightly-jobs.yml +++ b/.github/workflows/daily-nightly-jobs.yml @@ -110,46 +110,6 @@ jobs: if: always() run: sudo rm -rf /usr/bin/yq - smoke-suite-quincy-devel: - if: github.repository == 'rook/rook' - runs-on: ubuntu-22.04 - steps: - - name: checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - with: - fetch-depth: 0 - - - name: consider debugging - uses: ./.github/workflows/tmate_debug - with: - use-tmate: ${{ secrets.USE_TMATE }} - - - name: setup cluster resources - uses: ./.github/workflows/integration-test-config-latest-k8s - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - kubernetes-version: "1.28.4" - - - name: TestCephSmokeSuite - run: | - export DEVICE_FILTER=$(tests/scripts/github-action-helper.sh find_extra_block_dev) - SKIP_CLEANUP_POLICY=false CEPH_SUITE_VERSION="quincy-devel" go test -v -timeout 1800s -run TestCephSmokeSuite github.com/rook/rook/tests/integration - - - name: collect common logs - if: always() - run: | - export LOG_DIR="/home/runner/work/rook/rook/tests/integration/_output/tests/" - export CLUSTER_NAMESPACE="smoke-ns" - export OPERATOR_NAMESPACE="smoke-ns-system" - tests/scripts/collect-logs.sh - - - name: Artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - if: failure() - with: - name: ceph-smoke-suite-quincy-artifact - path: /home/runner/work/rook/rook/tests/integration/_output/tests/ - smoke-suite-reef-devel: if: github.repository == 'rook/rook' runs-on: ubuntu-22.04 @@ -270,46 +230,6 @@ jobs: name: ceph-smoke-suite-master-artifact path: /home/runner/work/rook/rook/tests/integration/_output/tests/ - object-suite-quincy-devel: - if: github.repository == 'rook/rook' - runs-on: ubuntu-22.04 - steps: - - name: checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - with: - fetch-depth: 0 - - - name: consider debugging - uses: ./.github/workflows/tmate_debug - with: - use-tmate: ${{ secrets.USE_TMATE }} - - - name: setup cluster resources - uses: ./.github/workflows/integration-test-config-latest-k8s - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - kubernetes-version: "1.28.4" - - - name: TestCephObjectSuite - run: | - export DEVICE_FILTER=$(tests/scripts/github-action-helper.sh find_extra_block_dev) - SKIP_CLEANUP_POLICY=false CEPH_SUITE_VERSION="quincy-devel" go test -v -timeout 1800s -failfast -run TestCephObjectSuite github.com/rook/rook/tests/integration - - - name: collect common logs - if: always() - run: | - export LOG_DIR="/home/runner/work/rook/rook/tests/integration/_output/tests/" - export CLUSTER_NAMESPACE="object-ns" - export OPERATOR_NAMESPACE="object-ns-system" - tests/scripts/collect-logs.sh - - - name: Artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - if: failure() - with: - name: ceph-object-suite-quincy-artifact - path: /home/runner/work/rook/rook/tests/integration/_output/tests/ - object-suite-ceph-main: if: github.repository == 'rook/rook' runs-on: ubuntu-22.04 @@ -431,49 +351,9 @@ jobs: name: ceph-upgrade-suite-reef-artifact path: /home/runner/work/rook/rook/tests/integration/_output/tests/ - upgrade-from-quincy-stable-to-quincy-devel: - if: github.repository == 'rook/rook' - runs-on: ubuntu-22.04 - steps: - - name: checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - with: - fetch-depth: 0 - - - name: consider debugging - uses: ./.github/workflows/tmate_debug - with: - use-tmate: ${{ secrets.USE_TMATE }} - - - name: setup cluster resources - uses: ./.github/workflows/integration-test-config-latest-k8s - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - kubernetes-version: "1.28.4" - - - name: TestCephUpgradeSuite - run: | - export DEVICE_FILTER=$(tests/scripts/github-action-helper.sh find_extra_block_dev) - go test -v -timeout 1800s -failfast -run TestCephUpgradeSuite/TestUpgradeCephToQuincyDevel github.com/rook/rook/tests/integration - - - name: collect common logs - if: always() - run: | - export LOG_DIR="/home/runner/work/rook/rook/tests/integration/_output/tests/" - export CLUSTER_NAMESPACE="upgrade" - export OPERATOR_NAMESPACE="upgrade-system" - tests/scripts/collect-logs.sh - - - name: Artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 - if: failure() - with: - name: ceph-upgrade-suite-quincy-artifact - path: /home/runner/work/rook/rook/tests/integration/_output/tests/ - canary-tests: if: github.repository == 'rook/rook' uses: ./.github/workflows/canary-integration-test.yml with: - ceph_images: '["quay.io/ceph/ceph:v18", "quay.io/ceph/daemon-base:latest-main-devel", "quay.io/ceph/daemon-base:latest-quincy-devel", "quay.io/ceph/daemon-base:latest-reef-devel", "quay.io/ceph/daemon-base:latest-squid-devel"]' + ceph_images: '["quay.io/ceph/ceph:v18", "quay.io/ceph/daemon-base:latest-main-devel", "quay.io/ceph/daemon-base:latest-reef-devel", "quay.io/ceph/daemon-base:latest-squid-devel"]' secrets: inherit diff --git a/Documentation/CRDs/Cluster/ceph-cluster-crd.md b/Documentation/CRDs/Cluster/ceph-cluster-crd.md index 38edb30d8eb0..fce6603648a1 100755 --- a/Documentation/CRDs/Cluster/ceph-cluster-crd.md +++ b/Documentation/CRDs/Cluster/ceph-cluster-crd.md @@ -29,9 +29,9 @@ Settings can be specified at the global level to apply to the cluster as a whole * `image`: The image used for running the ceph daemons. For example, `quay.io/ceph/ceph:v18.2.4`. For more details read the [container images section](#ceph-container-images). For the latest ceph images, see the [Ceph DockerHub](https://hub.docker.com/r/ceph/ceph/tags/). To ensure a consistent version of the image is running across all nodes in the cluster, it is recommended to use a very specific image version. - Tags also exist that would give the latest version, but they are only recommended for test environments. For example, the tag `v17` will be updated each time a new Quincy build is released. - Using the `v17` tag is not recommended in production because it may lead to inconsistent versions of the image running across different nodes in the cluster. - * `allowUnsupported`: If `true`, allow an unsupported major version of the Ceph release. Currently `quincy` and `reef` are supported. Future versions such as `squid` (v19) would require this to be set to `true`. Should be set to `false` in production. + Tags also exist that would give the latest version, but they are only recommended for test environments. For example, the tag `v19` will be updated each time a new Squid build is released. + Using the general `v19` tag is not recommended in production because it may lead to inconsistent versions of the image running across different nodes in the cluster. + * `allowUnsupported`: If `true`, allow an unsupported major version of the Ceph release. Currently Reef and Squid are supported. Future versions such as Tentacle (v20) would require this to be set to `true`. Should be set to `false` in production. * `imagePullPolicy`: The image pull policy for the ceph daemon pods. Possible values are `Always`, `IfNotPresent`, and `Never`. The default is `IfNotPresent`. * `dataDirHostPath`: The path on the host ([hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath)) where config and data should be stored for each of the services. If the directory does not exist, it will be created. Because this directory persists on the host, it will remain after pods are deleted. Following paths and any of their subpaths **must not be used**: `/etc/ceph`, `/rook` or `/var/log/ceph`. * **WARNING**: For test scenarios, if you delete a cluster and start a new cluster on the same hosts, the path used by `dataDirHostPath` must be deleted. Otherwise, stale keys and other config will remain from the previous cluster and the new mons will fail to start. @@ -120,10 +120,10 @@ These are general purpose Ceph container with all necessary daemons and dependen | TAG | MEANING | | -------------------- | --------------------------------------------------------- | -| vRELNUM | Latest release in this series (e.g., **v17** = Quincy) | -| vRELNUM.Y | Latest stable release in this stable series (e.g., v17.2) | -| vRELNUM.Y.Z | A specific release (e.g., v18.2.4) | -| vRELNUM.Y.Z-YYYYMMDD | A specific build (e.g., v18.2.4-20240724) | +| vRELNUM | Latest release in this series (e.g., **v19** = Squid) | +| vRELNUM.Y | Latest stable release in this stable series (e.g., v19.2) | +| vRELNUM.Y.Z | A specific release (e.g., v19.2.0) | +| vRELNUM.Y.Z-YYYYMMDD | A specific build (e.g., v19.2.0-20240927) | A specific will contain a specific release of Ceph as well as security fixes from the Operating System. diff --git a/Documentation/CRDs/Cluster/external-cluster/external-cluster.md b/Documentation/CRDs/Cluster/external-cluster/external-cluster.md index 28dd279bfbf1..68b965fcedce 100644 --- a/Documentation/CRDs/Cluster/external-cluster/external-cluster.md +++ b/Documentation/CRDs/Cluster/external-cluster/external-cluster.md @@ -17,7 +17,7 @@ In external mode, Rook will provide the configuration for the CSI driver and oth Create the desired types of storage in the provider Ceph cluster: * [RBD pools](https://docs.ceph.com/en/latest/rados/operations/pools/#create-a-pool) -* [CephFS filesystem](https://docs.ceph.com/en/quincy/cephfs/createfs/) +* [CephFS filesystem](https://docs.ceph.com/en/latest/cephfs/createfs/) ## Connect the external Ceph Provider cluster to the Rook consumer cluster diff --git a/Documentation/CRDs/Cluster/external-cluster/provider-export.md b/Documentation/CRDs/Cluster/external-cluster/provider-export.md index 7f3b3e8e7abf..db64ab9584f0 100644 --- a/Documentation/CRDs/Cluster/external-cluster/provider-export.md +++ b/Documentation/CRDs/Cluster/external-cluster/provider-export.md @@ -105,7 +105,7 @@ python3 create-external-cluster-resources.py --cephfs-filesystem-name --format bash --rgw-endpoint --rgw-realm-name > --rgw-zonegroup-name --rgw-zone-name > diff --git a/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md b/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md index 4b4efb8f0418..9c928a372983 100644 --- a/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md +++ b/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md @@ -148,7 +148,7 @@ The protocols section is divided into two parts: In the `s3` section of the `protocols` section the following options can be configured: * `authKeystone`: Whether S3 should also authenticated using Keystone (`true`) or not (`false`). If set to `false` the default S3 auth will be used. -* `enabled`: Whether to enable S3 (`true`) or not (`false`). The default is `true` even if the section is not listed at all! Please note that S3 should not be disabled in a [Ceph Multi Site configuration](https://docs.ceph.com/en/quincy/radosgw/multisite). +* `enabled`: Whether to enable S3 (`true`) or not (`false`). The default is `true` even if the section is not listed at all! Please note that S3 should not be disabled in a [Ceph Multi Site configuration](https://docs.ceph.com/en/latest/radosgw/multisite). #### protocols/swift settings @@ -332,9 +332,7 @@ vault kv put rook/ key=$(openssl rand -base64 32) # kv engine vault write -f transit/keys/ exportable=true # transit engine ``` -* TLS authentication with custom certificates between Vault and CephObjectStore RGWs are supported from ceph v16.2.6 onwards * `tokenSecretName` can be (and often will be) the same for both kms and s3 configurations. -* `AWS-SSE:S3` requires Ceph Quincy v17.2.3 or later. ## Deleting a CephObjectStore diff --git a/Documentation/CRDs/ceph-nfs-crd.md b/Documentation/CRDs/ceph-nfs-crd.md index 8accbbc7c884..16721d8f4f44 100644 --- a/Documentation/CRDs/ceph-nfs-crd.md +++ b/Documentation/CRDs/ceph-nfs-crd.md @@ -194,15 +194,3 @@ the size of the cluster. not always happen due to the Kubernetes scheduler. * Workaround: It is safest to run only a single NFS server, but we do not limit this if it benefits your use case. - -### Ceph v17.2.1 - -* Ceph NFS management with the Rook mgr module enabled has a breaking regression with the Ceph - Quincy v17.2.1 release. - * Workaround: Leave Ceph's Rook orchestrator mgr module disabled. If you have enabled it, you must - disable it using the snippet below from the toolbox. - - ```console - ceph orch set backend "" - ceph mgr module disable rook - ``` diff --git a/Documentation/CRDs/specification.md b/Documentation/CRDs/specification.md index ebd043d22f6e..888db90878a4 100644 --- a/Documentation/CRDs/specification.md +++ b/Documentation/CRDs/specification.md @@ -8892,7 +8892,7 @@ map[github.com/rook/rook/pkg/apis/ceph.rook.io/v1.CephNetworkType]string networks when the “multus” network provider is used. This config section is not used for other network providers.

Valid keys are “public” and “cluster”. Refer to Ceph networking documentation for more: -https://docs.ceph.com/en/reef/rados/configuration/network-config-ref/

+https://docs.ceph.com/en/latest/rados/configuration/network-config-ref/

Refer to Multus network annotation documentation for help selecting values: https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/how-to-use.md#run-pod-with-network-annotation

Rook will make a best-effort attempt to automatically detect CIDR address ranges for given @@ -9574,8 +9574,7 @@ The object store’s advertiseEndpoint and Kubernetes service endpoint, plus Each DNS name must be valid according RFC-1123. If the DNS name corresponds to an endpoint with DNS wildcard support, do not include the wildcard itself in the list of hostnames. -E.g., use “mystore.example.com” instead of “*.mystore.example.com”. -The feature is supported only for Ceph v18 and later versions.

+E.g., use “mystore.example.com” instead of “*.mystore.example.com”.

@@ -10169,7 +10168,7 @@ string (Optional) -

Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/quincy/radosgw/rgw-cache/#cache-api

+

Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/latest/radosgw/rgw-cache/#cache-api

diff --git a/Documentation/Storage-Configuration/NFS/nfs-security.md b/Documentation/Storage-Configuration/NFS/nfs-security.md index 4a3aa2baca2c..decd1c0e9a90 100644 --- a/Documentation/Storage-Configuration/NFS/nfs-security.md +++ b/Documentation/Storage-Configuration/NFS/nfs-security.md @@ -26,11 +26,6 @@ users stored in LDAP can be associated with NFS users and vice versa. mapping from a number of sources including LDAP, Active Directory, and FreeIPA. Currently, only LDAP has been tested. -!!! attention - The Ceph container image must have the `sssd-client` package installed to support SSSD. This - package is included in `quay.io/ceph/ceph` in v17.2.4 and newer. For older Ceph versions you may - build your own Ceph image which adds `RUN yum install sssd-client && yum clean all`. - #### SSSD configuration SSSD requires a configuration file in order to configure its connection to the user ID mapping diff --git a/Documentation/Storage-Configuration/NFS/nfs.md b/Documentation/Storage-Configuration/NFS/nfs.md index 5d15154fb12b..176427cab791 100644 --- a/Documentation/Storage-Configuration/NFS/nfs.md +++ b/Documentation/Storage-Configuration/NFS/nfs.md @@ -64,11 +64,7 @@ The Ceph CLI can be used from the Rook toolbox pod to create and manage NFS expo ensure the necessary Ceph mgr modules are enabled, if necessary, and that the Ceph orchestrator backend is set to Rook. -#### Enable the Ceph orchestrator if necessary - -* Required for Ceph v16.2.7 and below -* Optional for Ceph v16.2.8 and above -* Must be disabled for Ceph v17.2.1 due to a [Ceph regression](../../CRDs/ceph-nfs-crd.md#ceph-v1721) +#### Enable the Ceph orchestrator (optional) ```console ceph mgr module enable rook diff --git a/Documentation/Storage-Configuration/Object-Storage-RGW/ceph-object-bucket-notifications.md b/Documentation/Storage-Configuration/Object-Storage-RGW/ceph-object-bucket-notifications.md index 6c29b3bdf9d1..4df51db963ee 100644 --- a/Documentation/Storage-Configuration/Object-Storage-RGW/ceph-object-bucket-notifications.md +++ b/Documentation/Storage-Configuration/Object-Storage-RGW/ceph-object-bucket-notifications.md @@ -79,7 +79,7 @@ spec: 8. `http` (optional) hold the spec for an HTTP endpoint. The format of the URI would be: `http[s]://[:][/]` + port defaults to: 80/443 for HTTP/S accordingly 9. `disableVerifySSL` indicates whether the RGW is going to verify the SSL certificate of the HTTP server in case HTTPS is used ("false" by default) -10. `sendCloudEvents`: (optional) send the notifications with the [CloudEvents header](https://github.com/cloudevents/spec/blob/main/cloudevents/adapters/aws-s3.md). Supported for Ceph Quincy (v17) or newer ("false" by default) +10. `sendCloudEvents`: (optional) send the notifications with the [CloudEvents header](https://github.com/cloudevents/spec/blob/main/cloudevents/adapters/aws-s3.md). ("false" by default) 11. `amqp` (optional) hold the spec for an AMQP endpoint. The format of the URI would be: `amqp[s]://[:@][:][/]` + port defaults to: 5672/5671 for AMQP/S accordingly + user/password defaults to: guest/guest diff --git a/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md b/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md index 4c291a0c2409..3ada73c7eb94 100644 --- a/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md +++ b/Documentation/Storage-Configuration/Object-Storage-RGW/object-storage.md @@ -23,7 +23,7 @@ Rook can configure the Ceph Object Store for several different scenarios. See ea Rook has the ability to either deploy an object store in Kubernetes or to connect to an external RGW service. Most commonly, the object store will be configured in Kubernetes by Rook. -Alternatively see the [external section](#connect-to-an-external-object-store) to consume an existing Ceph cluster with [Rados Gateways](https://docs.ceph.com/en/quincy/radosgw/index.html) from Rook. +Alternatively see the [external section](#connect-to-an-external-object-store) to consume an existing Ceph cluster with [Rados Gateways](https://docs.ceph.com/en/latest/radosgw/index.html) from Rook. ### Create a Local Object Store with S3 @@ -198,7 +198,7 @@ This section contains a guide on how to configure [RGW's pool placement and stor Object Storage API allows users to override where bucket data will be stored during bucket creation. With `` parameter in S3 API and `X-Storage-Policy` header in SWIFT. Similarly, users can override where object data will be stored by setting `X-Amz-Storage-Class` and `X-Object-Storage-Class` during object creation. -To enable this feature, configure `poolPlacements` representing a list of possible bucket data locations. +To enable this feature, configure `poolPlacements` representing a list of possible bucket data locations. Each `poolPlacement` must have: * a **unique** `name` to refer to it in `` or `X-Storage-Policy`. A placement with reserved name `default` will be used by default if no location constraint is provided. diff --git a/Documentation/Upgrade/ceph-upgrade.md b/Documentation/Upgrade/ceph-upgrade.md index 0ea0e3a5109c..5205eac2b7cd 100644 --- a/Documentation/Upgrade/ceph-upgrade.md +++ b/Documentation/Upgrade/ceph-upgrade.md @@ -24,23 +24,15 @@ until all the daemons have been updated. ## Supported Versions -Rook v1.15 supports the following Ceph versions: +Rook v1.16 supports the following Ceph versions: +* Ceph Squid v19.2.0 or newer * Ceph Reef v18.2.0 or newer -* Ceph Quincy v17.2.0 or newer !!! important When an update is requested, the operator will check Ceph's status, **if it is in `HEALTH_ERR` the operator will refuse to proceed with the upgrade.** -!!! warning - Ceph v17.2.2 has a blocking issue when running with Rook. Use v17.2.3 or newer when possible. - -### CephNFS User Consideration - -Ceph Quincy v17.2.1 has a potentially breaking regression with CephNFS. See the NFS documentation's -[known issue](../CRDs/ceph-nfs-crd.md#ceph-v1721) for more detail. - ### Ceph Images Official Ceph container images can be found on [Quay](https://quay.io/repository/ceph/ceph?tab=tags). diff --git a/PendingReleaseNotes.md b/PendingReleaseNotes.md index 779cd62017d5..111d57e0f74c 100644 --- a/PendingReleaseNotes.md +++ b/PendingReleaseNotes.md @@ -2,5 +2,6 @@ ## Breaking Changes +- Removed support for Ceph Quincy (v17) since it has reached end of life ## Features diff --git a/deploy/charts/rook-ceph-cluster/values.yaml b/deploy/charts/rook-ceph-cluster/values.yaml index f154e012628b..7de9fdebb169 100644 --- a/deploy/charts/rook-ceph-cluster/values.yaml +++ b/deploy/charts/rook-ceph-cluster/values.yaml @@ -89,14 +89,14 @@ cephClusterSpec: # For more details, check https://rook.io/docs/rook/v1.10/CRDs/Cluster/ceph-cluster-crd/ cephVersion: # The container image used to launch the Ceph daemon pods (mon, mgr, osd, mds, rgw). - # v17 is Quincy, v18 is Reef. + # v18 is Reef, v19 is Squid # RECOMMENDATION: In production, use a specific version tag instead of the general v18 flag, which pulls the latest release and could result in different # versions running within the cluster. See tags available at https://hub.docker.com/r/ceph/ceph/tags/. # If you want to be more precise, you can always use a timestamp tag such as quay.io/ceph/ceph:v18.2.4-20240724 # This tag might not contain a new Ceph version, just security fixes from the underlying operating system, which will reduce vulnerabilities image: quay.io/ceph/ceph:v18.2.4 - # Whether to allow unsupported versions of Ceph. Currently `quincy`, and `reef` are supported. - # Future versions such as `squid` (v19) would require this to be set to `true`. + # Whether to allow unsupported versions of Ceph. Currently Reef and Squid are supported. + # Future versions such as Tentacle (v20) would require this to be set to `true`. # Do not set to true in production. allowUnsupported: false @@ -169,7 +169,7 @@ cephClusterSpec: encryption: enabled: false # Whether to compress the data in transit across the wire. The default is false. - # Requires Ceph Quincy (v17) or newer. Also see the kernel requirements above for encryption. + # The kernel requirements above for encryption also apply to compression. compression: enabled: false # Whether to require communication over msgr2. If true, the msgr v1 port (6789) will be disabled diff --git a/deploy/charts/rook-ceph/templates/resources.yaml b/deploy/charts/rook-ceph/templates/resources.yaml index 0092ad799fad..214888caadb4 100644 --- a/deploy/charts/rook-ceph/templates/resources.yaml +++ b/deploy/charts/rook-ceph/templates/resources.yaml @@ -2564,7 +2564,7 @@ spec: other network providers. Valid keys are "public" and "cluster". Refer to Ceph networking documentation for more: - https://docs.ceph.com/en/reef/rados/configuration/network-config-ref/ + https://docs.ceph.com/en/latest/rados/configuration/network-config-ref/ Refer to Multus network annotation documentation for help selecting values: https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/how-to-use.md#run-pod-with-network-annotation @@ -12046,7 +12046,6 @@ spec: If the DNS name corresponds to an endpoint with DNS wildcard support, do not include the wildcard itself in the list of hostnames. E.g., use "mystore.example.com" instead of "*.mystore.example.com". - The feature is supported only for Ceph v18 and later versions. items: type: string type: array @@ -12527,7 +12526,7 @@ spec: nullable: true properties: amz-cache: - description: Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/quincy/radosgw/rgw-cache/#cache-api + description: Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/latest/radosgw/rgw-cache/#cache-api enum: - '*' - read diff --git a/deploy/examples/cluster.yaml b/deploy/examples/cluster.yaml index a01f99f396b0..345897fb58bd 100644 --- a/deploy/examples/cluster.yaml +++ b/deploy/examples/cluster.yaml @@ -16,14 +16,14 @@ metadata: spec: cephVersion: # The container image used to launch the Ceph daemon pods (mon, mgr, osd, mds, rgw). - # v17 is Quincy, v18 is Reef. - # RECOMMENDATION: In production, use a specific version tag instead of the general v17 flag, which pulls the latest release and could result in different + # v18 is Reef, v19 is Squid + # RECOMMENDATION: In production, use a specific version tag instead of the general v19 flag, which pulls the latest release and could result in different # versions running within the cluster. See tags available at https://hub.docker.com/r/ceph/ceph/tags/. # If you want to be more precise, you can always use a timestamp tag such as quay.io/ceph/ceph:v18.2.4-20240724 # This tag might not contain a new Ceph version, just security fixes from the underlying operating system, which will reduce vulnerabilities image: quay.io/ceph/ceph:v18.2.4 - # Whether to allow unsupported versions of Ceph. Currently `quincy` and `reef` are supported. - # Future versions such as `squid` (v19) would require this to be set to `true`. + # Whether to allow unsupported versions of Ceph. Currently Reef and Squid are supported. + # Future versions such as Tentacle (v20) would require this to be set to `true`. # Do not set to true in production. allowUnsupported: false # The path on the host where configuration files will be persisted. Must be specified. @@ -322,7 +322,7 @@ spec: cephfs: # Set CephFS Kernel mount options to use https://docs.ceph.com/en/latest/man/8/mount.ceph/#options. # kernelMountOptions: "" - # Set CephFS Fuse mount options to use https://docs.ceph.com/en/quincy/man/8/ceph-fuse/#options. + # Set CephFS Fuse mount options to use https://docs.ceph.com/en/latest/man/8/ceph-fuse/#options. # fuseMountOptions: "" # healthChecks diff --git a/deploy/examples/crds.yaml b/deploy/examples/crds.yaml index aa8759c17784..dc75ac22e092 100644 --- a/deploy/examples/crds.yaml +++ b/deploy/examples/crds.yaml @@ -2562,7 +2562,7 @@ spec: other network providers. Valid keys are "public" and "cluster". Refer to Ceph networking documentation for more: - https://docs.ceph.com/en/reef/rados/configuration/network-config-ref/ + https://docs.ceph.com/en/latest/rados/configuration/network-config-ref/ Refer to Multus network annotation documentation for help selecting values: https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/how-to-use.md#run-pod-with-network-annotation @@ -12037,7 +12037,6 @@ spec: If the DNS name corresponds to an endpoint with DNS wildcard support, do not include the wildcard itself in the list of hostnames. E.g., use "mystore.example.com" instead of "*.mystore.example.com". - The feature is supported only for Ceph v18 and later versions. items: type: string type: array @@ -12517,7 +12516,7 @@ spec: nullable: true properties: amz-cache: - description: Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/quincy/radosgw/rgw-cache/#cache-api + description: Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/latest/radosgw/rgw-cache/#cache-api enum: - '*' - read diff --git a/design/ceph/ceph-nfs-ganesha.md b/design/ceph/ceph-nfs-ganesha.md index a26647f62af3..9baa05e1eda6 100644 --- a/design/ceph/ceph-nfs-ganesha.md +++ b/design/ceph/ceph-nfs-ganesha.md @@ -218,9 +218,7 @@ Directory, and FreeIPA. Prototype information detailed on Rook blog: https://blog.rook.io/prototyping-an-nfs-connection-to-ldap-using-sssd-7c27f624f1a4 -NFS-Ganesha (via libraries within its container) is the client to SSSD. As of Ceph v17.2.3, the Ceph -container image does not have the `sssd-client` package installed which is required for supporting -SSSD. It is available starting from Ceph v17.2.4. +NFS-Ganesha (via libraries within its container) is the client to SSSD. The following directories must be shared between SSSD and the NFS-Ganesha container: - `/var/lib/sss/pipes`: this directory holds the sockets used to communicate between client and SSSD diff --git a/design/ceph/object/ceph-sse-s3.md b/design/ceph/object/ceph-sse-s3.md index 4bad91c8acd7..73e6391d0dde 100644 --- a/design/ceph/object/ceph-sse-s3.md +++ b/design/ceph/object/ceph-sse-s3.md @@ -9,8 +9,6 @@ AWS server side encryption SSE-S3 support for RGW ## Summary The S3 protocol supports three different types of [server side encryption](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html): SSE-C, SSE-KMS and SSE-S3. For the last two RGW server need to configure with external services such as [vault](https://www.vaultproject.io/). Currently Rook configure RGW with `SSE-KMS` options to handle the S3 requests with the `sse:kms` header. Recently the support for handling the `sse:s3` was added to RGW, so Rook will now provide the option to configure RGW with `sse:s3`. -The `sse:s3` is supported only from Ceph v17 an onwards, so this feature can only be enabled for Quincy or newer. - ### Goals Configure RGW with `SSE-S3` options, so that RGW can handle request with `sse:s3` headers. diff --git a/pkg/apis/ceph.rook.io/v1/types.go b/pkg/apis/ceph.rook.io/v1/types.go index d06c20081f95..27eba7c978e6 100755 --- a/pkg/apis/ceph.rook.io/v1/types.go +++ b/pkg/apis/ceph.rook.io/v1/types.go @@ -1863,7 +1863,6 @@ type ObjectStoreHostingSpec struct { // If the DNS name corresponds to an endpoint with DNS wildcard support, do not include the // wildcard itself in the list of hostnames. // E.g., use "mystore.example.com" instead of "*.mystore.example.com". - // The feature is supported only for Ceph v18 and later versions. // +optional DNSNames []string `json:"dnsNames,omitempty"` } @@ -1985,7 +1984,7 @@ type ObjectUserCapSpec struct { Info string `json:"info,omitempty"` // +optional // +kubebuilder:validation:Enum={"*","read","write","read, write"} - // Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/quincy/radosgw/rgw-cache/#cache-api + // Add capabilities for user to send request to RGW Cache API header. Documented in https://docs.ceph.com/en/latest/radosgw/rgw-cache/#cache-api AMZCache string `json:"amz-cache,omitempty"` // +optional // +kubebuilder:validation:Enum={"*","read","write","read, write"} @@ -2627,7 +2626,7 @@ type NetworkSpec struct { // other network providers. // // Valid keys are "public" and "cluster". Refer to Ceph networking documentation for more: - // https://docs.ceph.com/en/reef/rados/configuration/network-config-ref/ + // https://docs.ceph.com/en/latest/rados/configuration/network-config-ref/ // // Refer to Multus network annotation documentation for help selecting values: // https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/how-to-use.md#run-pod-with-network-annotation diff --git a/pkg/daemon/ceph/client/config_test.go b/pkg/daemon/ceph/client/config_test.go index c3e4496ae683..cfb2afa20a6a 100644 --- a/pkg/daemon/ceph/client/config_test.go +++ b/pkg/daemon/ceph/client/config_test.go @@ -29,7 +29,6 @@ import ( "github.com/go-ini/ini" "github.com/rook/rook/pkg/clusterd" - cephver "github.com/rook/rook/pkg/operator/ceph/version" "github.com/stretchr/testify/assert" ) @@ -42,7 +41,6 @@ func TestCreateDefaultCephConfig(t *testing.T) { "node0": {Name: "mon0", Endpoint: "10.0.0.1:6789"}, "node1": {Name: "mon1", Endpoint: "10.0.0.2:6789"}, }, - CephVersion: cephver.Quincy, } // start with INFO level logging @@ -94,9 +92,8 @@ func TestGenerateConfigFile(t *testing.T) { Monitors: map[string]*MonInfo{ "node0": {Name: "mon0", Endpoint: "10.0.0.1:6789"}, }, - CephVersion: cephver.Quincy, - CephCred: CephCred{Username: "admin", Secret: "mysecret"}, - Context: ctx, + CephCred: CephCred{Username: "admin", Secret: "mysecret"}, + Context: ctx, } isInitialized := clusterInfo.IsInitialized() diff --git a/pkg/daemon/ceph/client/upgrade.go b/pkg/daemon/ceph/client/upgrade.go index 9fea46170209..0b9ffcc21a36 100644 --- a/pkg/daemon/ceph/client/upgrade.go +++ b/pkg/daemon/ceph/client/upgrade.go @@ -131,7 +131,7 @@ func OkToStop(context *clusterd.Context, clusterInfo *ClusterInfo, deployment, d // if we have less than 3 mons we skip the check and do best-effort // we do less than 3 because during the initial bootstrap the mon sequence is updated too // so running the check on 2/3 mon fails - // versions.Mon looks like this map[ceph version 17.0.0-12-g6c8fb92 (6c8fb920cb1d862f36ee852ed849a15f9a50bd68) quincy (dev):1] + // versions.Mon looks like this map[ceph version 19.0.0-12-g6c8fb92 (6c8fb920cb1d862f36ee852ed849a15f9a50bd68) squid (dev):1] // now looping over a single element since we can't address the key directly (we don't know its name) for _, monCount := range versions.Mon { if monCount < 3 { @@ -215,7 +215,7 @@ func okToContinueMDSDaemon(context *clusterd.Context, clusterInfo *ClusterInfo, // // "mon": { // "ceph version 18.2.5 (cbff874f9007f1869bfd3821b7e33b2a6ffd4988) reef (stable)": 2, -// "ceph version 17.2.6 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 1 +// "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 1 // } // // In the case we will pick: "ceph version 18.2.5 (cbff874f9007f1869bfd3821b7e33b2a6ffd4988) reef (stable)": 2, diff --git a/pkg/daemon/ceph/client/upgrade_test.go b/pkg/daemon/ceph/client/upgrade_test.go index 6630fd196886..45329915cce4 100644 --- a/pkg/daemon/ceph/client/upgrade_test.go +++ b/pkg/daemon/ceph/client/upgrade_test.go @@ -62,7 +62,7 @@ func TestEnableReleaseOSDFunctionality(t *testing.T) { } context := &clusterd.Context{Executor: executor} - err := EnableReleaseOSDFunctionality(context, AdminTestClusterInfo("mycluster"), "quincy") + err := EnableReleaseOSDFunctionality(context, AdminTestClusterInfo("mycluster"), "squid") assert.NoError(t, err) } @@ -129,7 +129,7 @@ func TestDaemonMapEntry(t *testing.T) { { "mon": { "ceph version 18.2.5 (cbff874f9007f1869bfd3821b7e33b2a6ffd4988) reef (stable)": 1, - "ceph version 17.2.7 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 2 + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 2 } }`) diff --git a/pkg/daemon/ceph/osd/daemon.go b/pkg/daemon/ceph/osd/daemon.go index 61063aa8328b..1ede9148f407 100644 --- a/pkg/daemon/ceph/osd/daemon.go +++ b/pkg/daemon/ceph/osd/daemon.go @@ -33,7 +33,6 @@ import ( "github.com/rook/rook/pkg/clusterd" "github.com/rook/rook/pkg/daemon/ceph/client" oposd "github.com/rook/rook/pkg/operator/ceph/cluster/osd" - cephver "github.com/rook/rook/pkg/operator/ceph/version" "github.com/rook/rook/pkg/util/sys" ) @@ -395,13 +394,6 @@ func getAvailableDevices(context *clusterd.Context, agent *OsdAgent) (*DeviceOsd } } - if device.Type == sys.LoopType { - if !agent.clusterInfo.CephVersion.IsAtLeast(cephver.CephVersion{Major: 17, Minor: 2, Extra: 4}) { - logger.Infof("partition %q is not picked because loop devices are not allowed on Ceph clusters older than v17.2.4", device.Name) - continue - } - } - // Check if the desired device is available // // We need to use the /dev path, provided by the NAME property from "lsblk --paths", diff --git a/pkg/daemon/ceph/osd/daemon_test.go b/pkg/daemon/ceph/osd/daemon_test.go index bf6dcbd5e4cd..eabc974f3016 100644 --- a/pkg/daemon/ceph/osd/daemon_test.go +++ b/pkg/daemon/ceph/osd/daemon_test.go @@ -382,8 +382,6 @@ NAME="sdb1" SIZE="30" TYPE="part" PKNAME="sdb"`, nil {Name: "loop0", RealPath: "/dev/loop0", Type: sys.LoopType}, } - version := cephver.Quincy - // select all devices, including nvme01 for metadata pvcBackedOSD := false agent := &OsdAgent{ @@ -392,7 +390,6 @@ NAME="sdb1" SIZE="30" TYPE="part" PKNAME="sdb"`, nil pvcBacked: pvcBackedOSD, clusterInfo: &cephclient.ClusterInfo{}, } - agent.clusterInfo.CephVersion = version mapping, err := getAvailableDevices(context, agent) assert.Nil(t, err) assert.Equal(t, 7, len(mapping.Entries)) @@ -536,19 +533,8 @@ NAME="sdb1" SIZE="30" TYPE="part" PKNAME="sdb"`, nil {Name: "sda", DevLinks: "/dev/disk/by-id/scsi-0123 /dev/disk/by-path/pci-0:1:2:3-scsi-1", RealPath: "/dev/sda"}, } - // loop device: Ceph version is too old - agent.pvcBacked = false - agent.devices = []DesiredDevice{{Name: "loop0"}} - mapping, err = getAvailableDevices(context, agent) - assert.Nil(t, err) - assert.Equal(t, 0, len(mapping.Entries)) - // loop device: specify a loop device - agent.clusterInfo.CephVersion = cephver.CephVersion{ - Major: 17, - Minor: 2, - Extra: 4, - } + agent.clusterInfo.CephVersion = cephver.Squid agent.pvcBacked = false agent.devices = []DesiredDevice{{Name: "loop0"}} mapping, err = getAvailableDevices(context, agent) @@ -574,7 +560,6 @@ NAME="sdb1" SIZE="30" TYPE="part" PKNAME="sdb"`, nil mapping, err = getAvailableDevices(context, agent) assert.Nil(t, err) assert.Equal(t, 0, len(mapping.Entries)) - agent.clusterInfo.CephVersion = cephver.Quincy } func TestGetVolumeGroupName(t *testing.T) { diff --git a/pkg/operator/ceph/cluster/cephstatus_test.go b/pkg/operator/ceph/cluster/cephstatus_test.go index 1dc01a67bef4..d464f3a529bb 100644 --- a/pkg/operator/ceph/cluster/cephstatus_test.go +++ b/pkg/operator/ceph/cluster/cephstatus_test.go @@ -29,7 +29,6 @@ import ( cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1" "github.com/rook/rook/pkg/clusterd" cephclient "github.com/rook/rook/pkg/daemon/ceph/client" - "github.com/rook/rook/pkg/operator/ceph/version" optest "github.com/rook/rook/pkg/operator/test" exectest "github.com/rook/rook/pkg/util/exec/test" "github.com/stretchr/testify/assert" @@ -162,7 +161,6 @@ func TestConfigureHealthSettings(t *testing.T) { context: &clusterd.Context{}, clusterInfo: cephclient.AdminTestClusterInfo("ns"), } - c.clusterInfo.CephVersion = version.Quincy setGlobalIDReclaim := false c.context.Executor = &exectest.MockExecutor{ MockExecuteCommandWithTimeout: func(timeout time.Duration, command string, args ...string) (string, error) { diff --git a/pkg/operator/ceph/cluster/mgr/dashboard_test.go b/pkg/operator/ceph/cluster/mgr/dashboard_test.go index f82ada4d32d3..4fea16c18d75 100644 --- a/pkg/operator/ceph/cluster/mgr/dashboard_test.go +++ b/pkg/operator/ceph/cluster/mgr/dashboard_test.go @@ -114,7 +114,7 @@ func TestStartSecureDashboard(t *testing.T) { ownerInfo := cephclient.NewMinimumOwnerInfoWithOwnerRef() clusterInfo := &cephclient.ClusterInfo{ Namespace: "myns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, OwnerInfo: ownerInfo, Context: ctx, } diff --git a/pkg/operator/ceph/cluster/mgr/orchestrator_test.go b/pkg/operator/ceph/cluster/mgr/orchestrator_test.go index 58c5923aa01c..e2215accf6b0 100644 --- a/pkg/operator/ceph/cluster/mgr/orchestrator_test.go +++ b/pkg/operator/ceph/cluster/mgr/orchestrator_test.go @@ -59,7 +59,7 @@ func TestOrchestratorModules(t *testing.T) { } clusterInfo := &cephclient.ClusterInfo{ - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: context.TODO(), } context := &clusterd.Context{Executor: executor} diff --git a/pkg/operator/ceph/cluster/mon/mon_test.go b/pkg/operator/ceph/cluster/mon/mon_test.go index 9d27be4014c9..e5918745adc3 100644 --- a/pkg/operator/ceph/cluster/mon/mon_test.go +++ b/pkg/operator/ceph/cluster/mon/mon_test.go @@ -190,7 +190,7 @@ func TestStartMonPods(t *testing.T) { } // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) // test annotations @@ -201,7 +201,7 @@ func TestStartMonPods(t *testing.T) { validateStart(t, c) // starting again should be a no-op - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) validateStart(t, c) @@ -215,7 +215,7 @@ func TestOperatorRestart(t *testing.T) { c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - info, err := c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + info, err := c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) assert.NoError(t, info.IsInitialized()) @@ -225,7 +225,7 @@ func TestOperatorRestart(t *testing.T) { c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // starting again should be a no-op, but will not result in an error - info, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + info, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) assert.NoError(t, info.IsInitialized()) @@ -243,7 +243,7 @@ func TestOperatorRestartHostNetwork(t *testing.T) { c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - info, err := c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + info, err := c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) assert.NoError(t, info.IsInitialized()) @@ -255,7 +255,7 @@ func TestOperatorRestartHostNetwork(t *testing.T) { c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // starting again should be a no-op, but still results in an error - info, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + info, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) assert.NoError(t, info.IsInitialized(), info) diff --git a/pkg/operator/ceph/cluster/mon/node_test.go b/pkg/operator/ceph/cluster/mon/node_test.go index cac949235f50..ba9236f0dccd 100644 --- a/pkg/operator/ceph/cluster/mon/node_test.go +++ b/pkg/operator/ceph/cluster/mon/node_test.go @@ -86,7 +86,7 @@ func TestHostNetworkSameNode(t *testing.T) { c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.Error(t, err) } @@ -104,7 +104,7 @@ func TestPodMemory(t *testing.T) { c := newCluster(context, namespace, true, r) c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) // Test REQUEST == LIMIT @@ -120,7 +120,7 @@ func TestPodMemory(t *testing.T) { c = newCluster(context, namespace, true, r) c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) // Test LIMIT != REQUEST but obviously LIMIT > REQUEST @@ -136,7 +136,7 @@ func TestPodMemory(t *testing.T) { c = newCluster(context, namespace, true, r) c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) // Test valid case where pod resource is set appropriately @@ -152,7 +152,7 @@ func TestPodMemory(t *testing.T) { c = newCluster(context, namespace, true, r) c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) // Test no resources were specified on the pod @@ -160,7 +160,7 @@ func TestPodMemory(t *testing.T) { c = newCluster(context, namespace, true, r) c.ClusterInfo = clienttest.CreateTestClusterInfo(1) // start a basic cluster - _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Quincy, c.spec) + _, err = c.Start(c.ClusterInfo, c.rookImage, cephver.Squid, c.spec) assert.NoError(t, err) } diff --git a/pkg/operator/ceph/cluster/osd/create_test.go b/pkg/operator/ceph/cluster/osd/create_test.go index 7312d8b95ae7..2939eea27bd4 100644 --- a/pkg/operator/ceph/cluster/osd/create_test.go +++ b/pkg/operator/ceph/cluster/osd/create_test.go @@ -310,7 +310,7 @@ func Test_startProvisioningOverPVCs(t *testing.T) { clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("mycluster") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) @@ -447,7 +447,7 @@ func Test_startProvisioningOverNodes(t *testing.T) { clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("mycluster") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) diff --git a/pkg/operator/ceph/cluster/osd/integration_test.go b/pkg/operator/ceph/cluster/osd/integration_test.go index 9ff325f8ae25..e402633ac4d0 100644 --- a/pkg/operator/ceph/cluster/osd/integration_test.go +++ b/pkg/operator/ceph/cluster/osd/integration_test.go @@ -591,7 +591,7 @@ func osdIntegrationTestExecutor(t *testing.T, clientset *fake.Clientset, namespa } if args[0] == "versions" { // the update deploy code only cares about the mons from the ceph version command results - v := `{"mon":{"ceph version 17.2.1 (somehash) quincy (stable)":3}}` + v := `{"mon":{"ceph version 19.2.1 (somehash) squid (stable)":3}}` return v, nil } return "", errors.Errorf("unexpected ceph command %q", args) diff --git a/pkg/operator/ceph/cluster/osd/osd_test.go b/pkg/operator/ceph/cluster/osd/osd_test.go index de2e62c270e7..1ed4571185f9 100644 --- a/pkg/operator/ceph/cluster/osd/osd_test.go +++ b/pkg/operator/ceph/cluster/osd/osd_test.go @@ -118,7 +118,7 @@ func TestStart(t *testing.T) { client := clientfake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(object...).Build() clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: context.TODO(), } clusterInfo.SetName("rook-ceph-test") @@ -201,7 +201,7 @@ func TestAddRemoveNode(t *testing.T) { clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: ctx, } clusterInfo.SetName("rook-ceph-test") @@ -425,7 +425,7 @@ func TestPostReconcileUpdateOSDProperties(t *testing.T) { client := clientfake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(object...).Build() clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: context.TODO(), } clusterInfo.SetName("rook-ceph-test") @@ -475,7 +475,7 @@ func TestAddNodeFailure(t *testing.T) { clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns-add-remove", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: context.TODO(), } clusterInfo.SetName("testcluster") @@ -1085,7 +1085,7 @@ func TestValidateOSDSettings(t *testing.T) { namespace := "ns" clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: context.TODO(), } clusterInfo.SetName("rook-ceph-test") diff --git a/pkg/operator/ceph/cluster/osd/spec.go b/pkg/operator/ceph/cluster/osd/spec.go index 33477cdbf88b..386bb9a24719 100644 --- a/pkg/operator/ceph/cluster/osd/spec.go +++ b/pkg/operator/ceph/cluster/osd/spec.go @@ -65,7 +65,6 @@ const ( bluestoreBlockName = "block" bluestoreMetadataName = "block.db" bluestoreWalName = "block.wal" - tempEtcCephDir = "/etc/temp-ceph" osdPortv1 = 6801 osdPortv2 = 6800 ) @@ -105,36 +104,12 @@ set -o nounset # fail if variables are unset set -o xtrace OSD_ID="$ROOK_OSD_ID" -CEPH_FSID=%s OSD_UUID=%s OSD_STORE_FLAG="%s" OSD_DATA_DIR=/var/lib/ceph/osd/ceph-"$OSD_ID" CV_MODE=%s DEVICE="$%s" -# "ceph.conf" must have the "fsid" global configuration to activate encrypted OSDs -# after the following Ceph's PR is merged. -# https://github.com/ceph/ceph/commit/25655e5a8829e001adf467511a6bde8142b0a575 -# This limitation will be removed later. After that, we can remove this -# fsid injection code. Probably a good time is when to remove Quincy support. -# https://github.com/rook/rook/pull/10333#discussion_r892817877 -cp --no-preserve=mode /etc/temp-ceph/ceph.conf /etc/ceph/ceph.conf -python3 -c " -import configparser - -config = configparser.ConfigParser() -config.read('/etc/ceph/ceph.conf') - -if not config.has_section('global'): - config['global'] = {} - -if not config.has_option('global','fsid'): - config['global']['fsid'] = '$CEPH_FSID' - -with open('/etc/ceph/ceph.conf', 'w') as configfile: - config.write(configfile) -" - # create new keyring ceph -n client.admin auth get-or-create osd."$OSD_ID" mon 'allow profile osd' mgr 'allow profile osd' osd 'allow *' -k /etc/ceph/admin-keyring-store/keyring @@ -894,7 +869,7 @@ func (c *Cluster) getActivateOSDInitContainer(configDir, namespace, osdID string volMounts := []v1.VolumeMount{ {Name: activateOSDVolumeName, MountPath: activateOSDMountPathID}, {Name: "devices", MountPath: "/dev"}, - {Name: k8sutil.ConfigOverrideName, ReadOnly: true, MountPath: tempEtcCephDir}, + {Name: k8sutil.ConfigOverrideName, ReadOnly: true, MountPath: opconfig.EtcCephDir}, adminKeyringVolMount, } @@ -908,7 +883,7 @@ func (c *Cluster) getActivateOSDInitContainer(configDir, namespace, osdID string Command: []string{ "/bin/bash", "-c", - fmt.Sprintf(activateOSDOnNodeCode, c.clusterInfo.FSID, osdInfo.UUID, osdStoreFlag, osdInfo.CVMode, blockPathVarName), + fmt.Sprintf(activateOSDOnNodeCode, osdInfo.UUID, osdStoreFlag, osdInfo.CVMode, blockPathVarName), }, Name: "activate", Image: c.spec.CephVersion.Image, diff --git a/pkg/operator/ceph/cluster/osd/spec_test.go b/pkg/operator/ceph/cluster/osd/spec_test.go index b4dbfc2d6507..5f5a9579be39 100644 --- a/pkg/operator/ceph/cluster/osd/spec_test.go +++ b/pkg/operator/ceph/cluster/osd/spec_test.go @@ -85,7 +85,7 @@ func testPodDevices(t *testing.T, dataDir, deviceName string, allDevices bool) { clientset := fake.NewSimpleClientset() clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("test") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) @@ -463,7 +463,7 @@ func testPodDevices(t *testing.T, dataDir, deviceName string, allDevices bool) { t.Run(("check hostpid and shareprocessnamespace"), func(t *testing.T) { clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("test") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) @@ -512,7 +512,7 @@ func TestStorageSpecConfig(t *testing.T) { clientset := fake.NewSimpleClientset() clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("testing") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) @@ -595,7 +595,7 @@ func TestHostNetwork(t *testing.T) { clientset := fake.NewSimpleClientset() clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("test") @@ -756,7 +756,7 @@ func TestOSDPlacement(t *testing.T) { clientset := fake.NewSimpleClientset() clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("testing") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) diff --git a/pkg/operator/ceph/cluster/osd/status_test.go b/pkg/operator/ceph/cluster/osd/status_test.go index 533286fb4721..78a07ddbd34d 100644 --- a/pkg/operator/ceph/cluster/osd/status_test.go +++ b/pkg/operator/ceph/cluster/osd/status_test.go @@ -40,7 +40,7 @@ func TestOrchestrationStatus(t *testing.T) { clientset := fake.NewSimpleClientset() clusterInfo := &cephclient.ClusterInfo{ Namespace: "ns", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } context := &clusterd.Context{Clientset: clientset, ConfigDir: "/var/lib/rook", Executor: &exectest.MockExecutor{}} spec := cephv1.ClusterSpec{} diff --git a/pkg/operator/ceph/cluster/osd/update_test.go b/pkg/operator/ceph/cluster/osd/update_test.go index 134ba2dba9b7..47b1da7498b7 100644 --- a/pkg/operator/ceph/cluster/osd/update_test.go +++ b/pkg/operator/ceph/cluster/osd/update_test.go @@ -557,7 +557,7 @@ func Test_getOSDUpdateInfo(t *testing.T) { } clusterInfo := &cephclient.ClusterInfo{ Namespace: namespace, - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo.SetName("mycluster") clusterInfo.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) @@ -589,7 +589,7 @@ func Test_getOSDUpdateInfo(t *testing.T) { // osd.1 and 3 in another namespace (another Rook cluster) clusterInfo2 := &cephclient.ClusterInfo{ Namespace: "other-namespace", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterInfo2.SetName("other-cluster") clusterInfo2.OwnerInfo = cephclient.NewMinimumOwnerInfo(t) diff --git a/pkg/operator/ceph/cluster/rbd/controller_test.go b/pkg/operator/ceph/cluster/rbd/controller_test.go index 1bfbf3c4f3f4..b32a3d3bf7db 100644 --- a/pkg/operator/ceph/cluster/rbd/controller_test.go +++ b/pkg/operator/ceph/cluster/rbd/controller_test.go @@ -47,7 +47,7 @@ const ( dummyVersionsRaw = ` { "mon": { - "ceph version 17.2.1 (0000000000000000000000000000000000) quincy (stable)": 3 + "ceph version 19.2.1 (0000000000000000000000000000000000) squid (stable)": 3 } }` ) diff --git a/pkg/operator/ceph/cluster/rbd/spec_test.go b/pkg/operator/ceph/cluster/rbd/spec_test.go index d03596645f52..2be8c04b588d 100644 --- a/pkg/operator/ceph/cluster/rbd/spec_test.go +++ b/pkg/operator/ceph/cluster/rbd/spec_test.go @@ -76,7 +76,7 @@ func TestPodSpec(t *testing.T) { TypeMeta: controllerTypeMeta, } clusterInfo := &cephclient.ClusterInfo{ - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } s := scheme.Scheme object := []runtime.Object{rbdMirror} diff --git a/pkg/operator/ceph/cluster/version_test.go b/pkg/operator/ceph/cluster/version_test.go index 8f4a2d65747b..23037c5dc537 100755 --- a/pkg/operator/ceph/cluster/version_test.go +++ b/pkg/operator/ceph/cluster/version_test.go @@ -37,7 +37,7 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { fakeRunningVersions := []byte(` { "mon": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 1, + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 1, "ceph version 18.1.0 (4be78cea2b4ae54a27b1049cffa1208df48bffae) reef (stable)": 2 } }`) @@ -53,7 +53,7 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { fakeRunningVersions = []byte(` { "overall": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 1, + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 1, "ceph version 18.1.0 (4be78cea2b4ae54a27b1049cffa1208df48bffae) reef (stable)": 2 } }`) @@ -69,7 +69,7 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { fakeRunningVersions = []byte(` { "overall": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 2 + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 2 } }`) var dummyRunningVersions3 cephv1.CephDaemonsVersions @@ -82,11 +82,11 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { assert.True(t, m) // 4 test - spec version is higher than running cluster --> we upgrade - fakeImageVersion = cephver.Quincy + fakeImageVersion = cephver.Squid fakeRunningVersions = []byte(` { "overall": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 2 + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 2 } }`) var dummyRunningVersions4 cephv1.CephDaemonsVersions @@ -98,12 +98,12 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { assert.True(t, m) // 5 test - spec version and running cluster versions are identical --> we upgrade - fakeImageVersion = cephver.CephVersion{Major: 17, Minor: 2, Extra: 0, + fakeImageVersion = cephver.CephVersion{Major: 19, Minor: 2, Extra: 0, CommitID: "3a54b2b6d167d4a2a19e003a705696d4fe619afc"} fakeRunningVersions = []byte(` { "overall": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 2 + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 2 } }`) var dummyRunningVersions5 cephv1.CephDaemonsVersions @@ -115,12 +115,12 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { assert.False(t, m) // 6 test - spec version and running cluster have different commit ID - fakeImageVersion = cephver.CephVersion{Major: 17, Minor: 2, Extra: 0, Build: 139, + fakeImageVersion = cephver.CephVersion{Major: 19, Minor: 2, Extra: 0, Build: 139, CommitID: "3a54b2b6d167d4a2a19e003a705696d4fe619afc"} fakeRunningVersions = []byte(` { "overall": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 2 + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 2 } }`) var dummyRunningVersions6 cephv1.CephDaemonsVersions @@ -132,12 +132,12 @@ func TestDiffImageSpecAndClusterRunningVersion(t *testing.T) { assert.True(t, m) // 7 test - spec version and running cluster have same commit ID - fakeImageVersion = cephver.CephVersion{Major: 17, Minor: 2, Extra: 0, + fakeImageVersion = cephver.CephVersion{Major: 19, Minor: 2, Extra: 0, CommitID: "3a54b2b6d167d4a2a19e003a705696d4fe619afc"} fakeRunningVersions = []byte(` { "overall": { - "ceph version 17.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) quincy (stable)": 2 + "ceph version 19.2.0 (3a54b2b6d167d4a2a19e003a705696d4fe619afc) squid (stable)": 2 } }`) var dummyRunningVersions7 cephv1.CephDaemonsVersions @@ -154,16 +154,14 @@ func TestMinVersion(t *testing.T) { c.Spec.CephVersion.AllowUnsupported = true c.ClusterInfo = &client.ClusterInfo{Context: context.TODO()} - // All versions less than 16.2.0 or invalid tag are invalid - v := &cephver.CephVersion{Major: 16, Minor: 1, Extra: 999} + // All versions less than 18.2.0 or invalid tag are invalid + v := &cephver.CephVersion{Major: 18, Minor: 1, Extra: 999} assert.Error(t, c.validateCephVersion(v)) - v = &cephver.CephVersion{Major: 15, Minor: 2, Extra: 11} + v = &cephver.CephVersion{Major: 16, Minor: 2, Extra: 11} assert.Error(t, c.validateCephVersion(v)) - // All versions at least 17.2.0 are valid - v = &cephver.CephVersion{Major: 17, Minor: 2} - assert.NoError(t, c.validateCephVersion(v)) - v = &cephver.CephVersion{Major: 18} + // All versions at least 18.2.0 are valid + v = &cephver.CephVersion{Major: 18, Minor: 2} assert.NoError(t, c.validateCephVersion(v)) v = &cephver.CephVersion{Major: 19} assert.NoError(t, c.validateCephVersion(v)) @@ -174,13 +172,9 @@ func TestSupportedVersion(t *testing.T) { c.ClusterInfo = &client.ClusterInfo{Context: context.TODO()} // lower version is not supported - v := &cephver.CephVersion{Major: 16, Minor: 2, Extra: 7} + v := &cephver.CephVersion{Major: 17, Minor: 2, Extra: 7} assert.Error(t, c.validateCephVersion(v)) - // Quincy is supported - v = &cephver.CephVersion{Major: 17, Minor: 2, Extra: 0} - assert.NoError(t, c.validateCephVersion(v)) - // Reef is supported v = &cephver.CephVersion{Major: 18, Minor: 2, Extra: 0} assert.NoError(t, c.validateCephVersion(v)) diff --git a/pkg/operator/ceph/config/defaults.go b/pkg/operator/ceph/config/defaults.go index d659d52e7f1e..8cf6f239153d 100644 --- a/pkg/operator/ceph/config/defaults.go +++ b/pkg/operator/ceph/config/defaults.go @@ -59,11 +59,6 @@ func DefaultCentralizedConfigs(cephVersion version.CephVersion) map[string]strin "mon allow pool size one": "true", } - // Every release before Quincy will enable PG auto repair on Bluestore OSDs - if !cephVersion.IsAtLeastQuincy() { - overrides["osd scrub auto repair"] = "true" - } - return overrides } diff --git a/pkg/operator/ceph/config/monstore.go b/pkg/operator/ceph/config/monstore.go index 01c4eac44157..ac2e9d39e508 100644 --- a/pkg/operator/ceph/config/monstore.go +++ b/pkg/operator/ceph/config/monstore.go @@ -197,7 +197,7 @@ func (m *MonStore) DeleteAll(options ...Option) error { // SetKeyValue sets an arbitrary key/value pair in Ceph's general purpose (as opposed to // configuration-specific) key/value store. Keys and values can be any arbitrary string including // spaces, underscores, dashes, and slashes. -// See: https://docs.ceph.com/en/quincy/man/8/ceph/#config-key +// See: https://docs.ceph.com/en/latest/man/8/ceph/#config-key func (m *MonStore) SetKeyValue(key, value string) error { logger.Debugf("setting %q=%q option in the mon config-key store", key, value) args := []string{"config-key", "set", key, value} diff --git a/pkg/operator/ceph/controller/predicate_test.go b/pkg/operator/ceph/controller/predicate_test.go index 63565f154543..e1158ebf02ba 100644 --- a/pkg/operator/ceph/controller/predicate_test.go +++ b/pkg/operator/ceph/controller/predicate_test.go @@ -98,18 +98,18 @@ func TestIsUpgrade(t *testing.T) { assert.False(t, b) // different value do something - newLabel["ceph_version"] = "17.2.0-quincy" + newLabel["ceph_version"] = "19.2.0-squid" b = isUpgrade(oldLabel, newLabel) assert.True(t, b, fmt.Sprintf("%v,%v", oldLabel, newLabel)) // same value do nothing - oldLabel["ceph_version"] = "17.2.0-quincy" - newLabel["ceph_version"] = "17.2.0-quincy" + oldLabel["ceph_version"] = "19.2.0-squid" + newLabel["ceph_version"] = "19.2.0-squid" b = isUpgrade(oldLabel, newLabel) assert.False(t, b, fmt.Sprintf("%v,%v", oldLabel, newLabel)) // different value do something - newLabel["ceph_version"] = "17.2.1-quincy" + newLabel["ceph_version"] = "19.2.1-squid" b = isUpgrade(oldLabel, newLabel) assert.True(t, b, fmt.Sprintf("%v,%v", oldLabel, newLabel)) } diff --git a/pkg/operator/ceph/disruption/clusterdisruption/osd_test.go b/pkg/operator/ceph/disruption/clusterdisruption/osd_test.go index aefc87897b89..92d8af82d108 100644 --- a/pkg/operator/ceph/disruption/clusterdisruption/osd_test.go +++ b/pkg/operator/ceph/disruption/clusterdisruption/osd_test.go @@ -44,7 +44,7 @@ import ( const ( healthyCephStatus = `{"fsid":"877a47e0-7f6c-435e-891a-76983ab8c509","health":{"checks":{},"status":"HEALTH_OK"},"election_epoch":12,"quorum":[0,1,2],"quorum_names":["a","b","c"],"monmap":{"epoch":3,"fsid":"877a47e0-7f6c-435e-891a-76983ab8c509","modified":"2020-11-02 09:58:23.015313","created":"2020-11-02 09:57:37.719235","min_mon_release":14,"min_mon_release_name":"nautilus","features":{"persistent":["kraken","luminous","mimic","osdmap-prune","nautilus"],"optional":[]},"mons":[{"rank":0,"name":"a","public_addrs":{"addrvec":[{"type":"v2","addr":"172.30.74.42:3300","nonce":0},{"type":"v1","addr":"172.30.74.42:6789","nonce":0}]},"addr":"172.30.74.42:6789/0","public_addr":"172.30.74.42:6789/0"},{"rank":1,"name":"b","public_addrs":{"addrvec":[{"type":"v2","addr":"172.30.101.61:3300","nonce":0},{"type":"v1","addr":"172.30.101.61:6789","nonce":0}]},"addr":"172.30.101.61:6789/0","public_addr":"172.30.101.61:6789/0"},{"rank":2,"name":"c","public_addrs":{"addrvec":[{"type":"v2","addr":"172.30.250.55:3300","nonce":0},{"type":"v1","addr":"172.30.250.55:6789","nonce":0}]},"addr":"172.30.250.55:6789/0","public_addr":"172.30.250.55:6789/0"}]},"osdmap":{"osdmap":{"epoch":19,"num_osds":3,"num_up_osds":3,"num_in_osds":3,"num_remapped_pgs":0}},"pgmap":{"pgs_by_state":[{"state_name":"active+clean","count":96}],"num_pgs":96,"num_pools":3,"num_objects":79,"data_bytes":81553681,"bytes_used":3255447552,"bytes_avail":1646011994112,"bytes_total":1649267441664,"read_bytes_sec":853,"write_bytes_sec":5118,"read_op_per_sec":1,"write_op_per_sec":0},"fsmap":{"epoch":9,"id":1,"up":1,"in":1,"max":1,"by_rank":[{"filesystem_id":1,"rank":0,"name":"ocs-storagecluster-cephfilesystem-b","status":"up:active","gid":14161},{"filesystem_id":1,"rank":0,"name":"ocs-storagecluster-cephfilesystem-a","status":"up:standby-replay","gid":24146}],"up:standby":0},"mgrmap":{"epoch":10,"active_gid":14122,"active_name":"a","active_addrs":{"addrvec":[{"type":"v2","addr":"10.131.0.28:6800","nonce":1},{"type":"v1","addr":"10.131.0.28:6801","nonce":1}]}}}` unHealthyCephStatus = `{"fsid":"613975f3-3025-4802-9de1-a2280b950e75","health":{"checks":{"OSD_DOWN":{"severity":"HEALTH_WARN","summary":{"message":"1 osds down"}},"OSD_HOST_DOWN":{"severity":"HEALTH_WARN","summary":{"message":"1 host (1 osds) down"}},"PG_AVAILABILITY":{"severity":"HEALTH_WARN","summary":{"message":"Reduced data availability: 101 pgs stale"}},"POOL_APP_NOT_ENABLED":{"severity":"HEALTH_WARN","summary":{"message":"application not enabled on 1 pool(s)"}}},"status":"HEALTH_WARN","overall_status":"HEALTH_WARN"},"election_epoch":12,"quorum":[0,1,2],"quorum_names":["rook-ceph-mon0","rook-ceph-mon2","rook-ceph-mon1"],"monmap":{"epoch":3,"fsid":"613975f3-3025-4802-9de1-a2280b950e75","modified":"2017-08-11 20:13:02.075679","created":"2017-08-11 20:12:35.314510","features":{"persistent":["kraken","luminous"],"optional":[]},"mons":[{"rank":0,"name":"rook-ceph-mon0","addr":"10.3.0.45:6789/0","public_addr":"10.3.0.45:6789/0"},{"rank":1,"name":"rook-ceph-mon2","addr":"10.3.0.249:6789/0","public_addr":"10.3.0.249:6789/0"},{"rank":2,"name":"rook-ceph-mon1","addr":"10.3.0.252:6789/0","public_addr":"10.3.0.252:6789/0"}]},"osdmap":{"osdmap":{"epoch":17,"num_osds":2,"num_up_osds":1,"num_in_osds":2,"full":false,"nearfull":true,"num_remapped_pgs":0}},"pgmap":{"pgs_by_state":[{"state_name":"stale+active+clean","count":101},{"state_name":"active+clean","count":99}],"num_pgs":200,"num_pools":2,"num_objects":243,"data_bytes":976793635,"bytes_used":13611479040,"bytes_avail":19825307648,"bytes_total":33436786688},"fsmap":{"epoch":1,"by_rank":[]},"mgrmap":{"epoch":3,"active_gid":14111,"active_name":"rook-ceph-mgr0","active_addr":"10.2.73.6:6800/9","available":true,"standbys":[],"modules":["restful","status"],"available_modules":["dashboard","prometheus","restful","status","zabbix"]},"servicemap":{"epoch":1,"modified":"0.000000","services":{}}}` - healthyCephStatusRemapped = `{"fsid":"e32d91a2-24ff-4953-bc4a-6864d31dd2a0","health":{"status":"HEALTH_OK","checks":{},"mutes":[]},"election_epoch":3,"quorum":[0],"quorum_names":["a"],"quorum_age":1177701,"monmap":{"epoch":1,"min_mon_release_name":"quincy","num_mons":1},"osdmap":{"epoch":1800,"num_osds":5,"num_up_osds":5,"osd_up_since":1699834324,"num_in_osds":5,"osd_in_since":1699834304,"num_remapped_pgs":11},"pgmap":{"pgs_by_state":[{"state_name":"active+clean","count":174},{"state_name":"active+remapped+backfilling","count":10},{"state_name":"active+clean+remapped","count":1}],"num_pgs":185,"num_pools":9,"num_objects":2383,"data_bytes":2222656224,"bytes_used":8793104384,"bytes_avail":18050441216,"bytes_total":26843545600,"misplaced_objects":139,"misplaced_total":7149,"misplaced_ratio":0.019443278780248985,"recovering_objects_per_sec":10,"recovering_bytes_per_sec":9739877,"recovering_keys_per_sec":0,"num_objects_recovered":62,"num_bytes_recovered":58471087,"num_keys_recovered":0,"write_bytes_sec":2982994,"read_op_per_sec":0,"write_op_per_sec":26},"fsmap":{"epoch":1,"by_rank":[],"up:standby":0},"mgrmap":{"available":true,"num_standbys":0,"modules":["iostat","nfs","prometheus","restful"],"services":{"prometheus":"http://10.244.0.36:9283/"}},"servicemap":{"epoch":1,"modified":"0.000000","services":{}},"progress_events":{}}` + healthyCephStatusRemapped = `{"fsid":"e32d91a2-24ff-4953-bc4a-6864d31dd2a0","health":{"status":"HEALTH_OK","checks":{},"mutes":[]},"election_epoch":3,"quorum":[0],"quorum_names":["a"],"quorum_age":1177701,"monmap":{"epoch":1,"min_mon_release_name":"reef","num_mons":1},"osdmap":{"epoch":1800,"num_osds":5,"num_up_osds":5,"osd_up_since":1699834324,"num_in_osds":5,"osd_in_since":1699834304,"num_remapped_pgs":11},"pgmap":{"pgs_by_state":[{"state_name":"active+clean","count":174},{"state_name":"active+remapped+backfilling","count":10},{"state_name":"active+clean+remapped","count":1}],"num_pgs":185,"num_pools":9,"num_objects":2383,"data_bytes":2222656224,"bytes_used":8793104384,"bytes_avail":18050441216,"bytes_total":26843545600,"misplaced_objects":139,"misplaced_total":7149,"misplaced_ratio":0.019443278780248985,"recovering_objects_per_sec":10,"recovering_bytes_per_sec":9739877,"recovering_keys_per_sec":0,"num_objects_recovered":62,"num_bytes_recovered":58471087,"num_keys_recovered":0,"write_bytes_sec":2982994,"read_op_per_sec":0,"write_op_per_sec":26},"fsmap":{"epoch":1,"by_rank":[],"up:standby":0},"mgrmap":{"available":true,"num_standbys":0,"modules":["iostat","nfs","prometheus","restful"],"services":{"prometheus":"http://10.244.0.36:9283/"}},"servicemap":{"epoch":1,"modified":"0.000000","services":{}},"progress_events":{}}` ) var nodeName = "node01" diff --git a/pkg/operator/ceph/file/controller_test.go b/pkg/operator/ceph/file/controller_test.go index cf7f67d82816..293d370abac6 100644 --- a/pkg/operator/ceph/file/controller_test.go +++ b/pkg/operator/ceph/file/controller_test.go @@ -142,7 +142,7 @@ const ( dummyVersionsRaw = ` { "mon": { - "ceph version 17.2.1 (000000000000000000000000000000) quincy (stable)": 3 + "ceph version 19.2.1 (000000000000000000000000000000) squid (stable)": 3 } }` ) diff --git a/pkg/operator/ceph/file/filesystem_test.go b/pkg/operator/ceph/file/filesystem_test.go index 856add3885eb..75f33ade9f32 100644 --- a/pkg/operator/ceph/file/filesystem_test.go +++ b/pkg/operator/ceph/file/filesystem_test.go @@ -224,7 +224,7 @@ func fsExecutor(t *testing.T, fsName, configDir string, multiFS bool, createData versionStr, _ := json.Marshal( map[string]map[string]int{ "mds": { - "ceph version 17.0.0-0-g2f728b9 (2f728b952cf293dd7f809ad8a0f5b5d040c43010) quincy (stable)": 2, + "ceph version 19.0.0-0-g2f728b9 (2f728b952cf293dd7f809ad8a0f5b5d040c43010) squid (stable)": 2, }, }) return string(versionStr), nil @@ -307,7 +307,7 @@ func fsExecutor(t *testing.T, fsName, configDir string, multiFS bool, createData versionStr, _ := json.Marshal( map[string]map[string]int{ "mds": { - "ceph version 17.2.0-0-g2f728b9 (2f728b952cf293dd7f809ad8a0f5b5d040c43010) quincy (stable)": 2, + "ceph version 19.2.0-0-g2f728b9 (2f728b952cf293dd7f809ad8a0f5b5d040c43010) squid (stable)": 2, }, }) return string(versionStr), nil @@ -361,7 +361,7 @@ func TestCreateFilesystem(t *testing.T) { ConfigDir: configDir, Clientset: clientset} fs := fsTest(fsName) - clusterInfo := &cephclient.ClusterInfo{FSID: "myfsid", CephVersion: version.Quincy, Context: ctx} + clusterInfo := &cephclient.ClusterInfo{FSID: "myfsid", CephVersion: version.Squid, Context: ctx} ownerInfo := cephclient.NewMinimumOwnerInfoWithOwnerRef() t.Run("start basic filesystem", func(t *testing.T) { @@ -405,7 +405,7 @@ func TestCreateFilesystem(t *testing.T) { }) t.Run("multi filesystem creation should succeed", func(t *testing.T) { - clusterInfo.CephVersion = version.Quincy + clusterInfo.CephVersion = version.Squid err := createFilesystem(context, clusterInfo, fs, &cephv1.ClusterSpec{}, ownerInfo, "/var/lib/rook/") assert.NoError(t, err) }) @@ -427,7 +427,7 @@ func TestUpgradeFilesystem(t *testing.T) { ConfigDir: configDir, Clientset: clientset} fs := fsTest(fsName) - clusterInfo := &cephclient.ClusterInfo{FSID: "myfsid", CephVersion: version.Quincy, Context: ctx} + clusterInfo := &cephclient.ClusterInfo{FSID: "myfsid", CephVersion: version.Squid, Context: ctx} // start a basic cluster for upgrade ownerInfo := cephclient.NewMinimumOwnerInfoWithOwnerRef() @@ -438,7 +438,7 @@ func TestUpgradeFilesystem(t *testing.T) { testopk8s.ClearDeploymentsUpdated(deploymentsUpdated) // do upgrade - clusterInfo.CephVersion = version.Quincy + clusterInfo.CephVersion = version.Squid context = &clusterd.Context{ Executor: executor, ConfigDir: configDir, @@ -473,56 +473,81 @@ func TestUpgradeFilesystem(t *testing.T) { }, } createdFsResponse, _ := json.Marshal(mdsmap) - firstGet := false + + // actual version + clusterInfo.CephVersion = version.Squid + // mocked version to cause an error different from the actual version + mockedVersionStr, _ := json.Marshal( + map[string]map[string]int{ + "mds": { + "ceph version 18.2.0-0-g2f728b9 (2f728b952cf293dd7f809ad8a0f5b5d040c43010) reef (stable)": 2, + }, + }) executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) { - if contains(args, "fs") && contains(args, "get") { - if firstGet { - firstGet = false - return "", errors.New("fs doesn't exist") + if contains(args, "fs") { + if contains(args, "get") { + return string(createdFsResponse), nil + } else if contains(args, "ls") { + return "[]", nil + } else if contains(args, "dump") { + return `{"standbys":[], "filesystems":[]}`, nil + } else if contains(args, "subvolumegroup") { + return "[]", nil + } + } + if contains(args, "osd") { + if contains(args, "lspools") { + return "[]", nil } - return string(createdFsResponse), nil - } else if contains(args, "fs") && contains(args, "ls") { - return "[]", nil - } else if contains(args, "fs") && contains(args, "dump") { - return `{"standbys":[], "filesystems":[]}`, nil - } else if contains(args, "osd") && contains(args, "lspools") { - return "[]", nil - } else if contains(args, "mds") && contains(args, "fail") { + if contains(args, "pool") && contains(args, "application") { + if contains(args, "get") { + return `{"":{}}`, nil + } + return "[]", nil + } + if reflect.DeepEqual(args[1:3], []string{"pool", "get"}) { + return "", errors.New("test pool does not exist yet") + } + } + if contains(args, "mds") && contains(args, "fail") { return "", errors.New("fail mds failed") - } else if isBasePoolOperation(fsName, command, args) { - return "", nil - } else if reflect.DeepEqual(args[0:5], []string{"fs", "new", fsName, fsName + "-metadata", fsName + "-data0"}) { - return "", nil - } else if contains(args, "auth") && contains(args, "get-or-create-key") { - return "{\"key\":\"mysecurekey\"}", nil - } else if contains(args, "auth") && contains(args, "del") { - return "", nil - } else if contains(args, "config") && contains(args, "mds_cache_memory_limit") { - return "", nil - } else if contains(args, "set") && contains(args, "max_mds") { - return "", nil - } else if contains(args, "set") && contains(args, "allow_standby_replay") { + } + if isBasePoolOperation(fsName, command, args) { return "", nil - } else if contains(args, "config") && contains(args, "mds_join_fs") { + } + if reflect.DeepEqual(args[0:5], []string{"fs", "new", fsName, fsName + "-metadata", fsName + "-data0"}) { return "", nil - } else if contains(args, "config") && contains(args, "get") { - return "{}", nil - } else if reflect.DeepEqual(args[0:3], []string{"osd", "pool", "get"}) { - return "", errors.New("test pool does not exist yet") - } else if contains(args, "versions") { - versionStr, _ := json.Marshal( - map[string]map[string]int{ - "mds": { - "ceph version 17.2.0-0-g2f728b9 (2f728b952cf293dd7f809ad8a0f5b5d040c43010) quincy (stable)": 2, - }, - }) - return string(versionStr), nil + } + if contains(args, "auth") { + if contains(args, "get-or-create-key") { + return "{\"key\":\"mysecurekey\"}", nil + } else if contains(args, "auth") && contains(args, "del") { + return "", nil + } + } + if contains(args, "config") { + if contains(args, "mds_cache_memory_limit") { + return "", nil + } else if contains(args, "mds_join_fs") { + return "", nil + } else if contains(args, "get") { + return "{}", nil + } + } + if contains(args, "set") { + if contains(args, "max_mds") { + return "", nil + } else if contains(args, "allow_standby_replay") { + return "", nil + } + } + if contains(args, "versions") { + return string(mockedVersionStr), nil } assert.Fail(t, fmt.Sprintf("Unexpected command %q %q", command, args)) return "", nil } // do upgrade - clusterInfo.CephVersion = version.Reef context = &clusterd.Context{ Executor: executor, ConfigDir: configDir, diff --git a/pkg/operator/ceph/file/mds/spec_test.go b/pkg/operator/ceph/file/mds/spec_test.go index 803c3b6c019e..f41b077bfe26 100644 --- a/pkg/operator/ceph/file/mds/spec_test.go +++ b/pkg/operator/ceph/file/mds/spec_test.go @@ -60,7 +60,7 @@ func testDeploymentObject(t *testing.T, network cephv1.NetworkSpec) (*apps.Deplo } clusterInfo := &cephclient.ClusterInfo{ FSID: "myfsid", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clientset := testop.New(t, 1) diff --git a/pkg/operator/ceph/file/mirror/controller_test.go b/pkg/operator/ceph/file/mirror/controller_test.go index 1edcd6253ea1..e73f83d0762d 100644 --- a/pkg/operator/ceph/file/mirror/controller_test.go +++ b/pkg/operator/ceph/file/mirror/controller_test.go @@ -228,7 +228,7 @@ func TestCephFilesystemMirrorController(t *testing.T) { } currentAndDesiredCephVersion = func(ctx context.Context, rookImage string, namespace string, jobName string, ownerInfo *k8sutil.OwnerInfo, context *clusterd.Context, cephClusterSpec *cephv1.ClusterSpec, clusterInfo *client.ClusterInfo) (*version.CephVersion, *version.CephVersion, error) { - return &version.Quincy, &version.Reef, nil + return &version.Squid, &version.Reef, nil } res, err := r.Reconcile(ctx, req) diff --git a/pkg/operator/ceph/file/mirror/spec_test.go b/pkg/operator/ceph/file/mirror/spec_test.go index 256705fab3c9..9d35d81b2b4e 100644 --- a/pkg/operator/ceph/file/mirror/spec_test.go +++ b/pkg/operator/ceph/file/mirror/spec_test.go @@ -74,7 +74,7 @@ func TestPodSpec(t *testing.T) { TypeMeta: controllerTypeMeta, } clusterInfo := &cephclient.ClusterInfo{ - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } s := scheme.Scheme object := []runtime.Object{fsMirror} diff --git a/pkg/operator/ceph/nfs/controller_test.go b/pkg/operator/ceph/nfs/controller_test.go index f03292ec063b..34bd23b76dc3 100644 --- a/pkg/operator/ceph/nfs/controller_test.go +++ b/pkg/operator/ceph/nfs/controller_test.go @@ -218,7 +218,7 @@ func TestCephNFSController(t *testing.T) { } currentAndDesiredCephVersion = func(ctx context.Context, rookImage string, namespace string, jobName string, ownerInfo *k8sutil.OwnerInfo, context *clusterd.Context, cephClusterSpec *cephv1.ClusterSpec, clusterInfo *cephclient.ClusterInfo) (*version.CephVersion, *version.CephVersion, error) { - return &version.Quincy, &version.Quincy, nil + return &version.Squid, &version.Squid, nil } t.Run("error - no ceph cluster", func(t *testing.T) { diff --git a/pkg/operator/ceph/nfs/nfs_test.go b/pkg/operator/ceph/nfs/nfs_test.go index f8a812a507a2..be90a8ab99ba 100644 --- a/pkg/operator/ceph/nfs/nfs_test.go +++ b/pkg/operator/ceph/nfs/nfs_test.go @@ -49,7 +49,7 @@ func TestReconcileCephNFS_createConfigMap(t *testing.T) { context: c, clusterInfo: &cephclient.ClusterInfo{ FSID: "myfsid", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, }, cephClusterSpec: &cephv1.ClusterSpec{ CephVersion: cephv1.CephVersionSpec{ @@ -154,7 +154,7 @@ func TestReconcileCephNFS_upCephNFS(t *testing.T) { context: c, clusterInfo: &cephclient.ClusterInfo{ FSID: "myfsid", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, Context: context.TODO(), Namespace: ns, }, diff --git a/pkg/operator/ceph/nfs/security_test.go b/pkg/operator/ceph/nfs/security_test.go index 681980598a88..d03853a5ed6c 100644 --- a/pkg/operator/ceph/nfs/security_test.go +++ b/pkg/operator/ceph/nfs/security_test.go @@ -47,11 +47,11 @@ func mockReconcile() *ReconcileCephNFS { return &ReconcileCephNFS{ clusterInfo: &cephclient.ClusterInfo{ FSID: "myfsid", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, }, cephClusterSpec: &cephv1.ClusterSpec{ CephVersion: cephv1.CephVersionSpec{ - Image: "quay.io/ceph/ceph:v17", + Image: "quay.io/ceph/ceph:v19", }, }, } @@ -191,7 +191,7 @@ func TestReconcileCephNFS_addSecurityConfigsToPod(t *testing.T) { nss := containerByName(pod.InitContainers, "generate-nsswitch-conf") assert.NotEmpty(t, nss) // container should have CLUSTER image and resources from SERVER spec - assert.Equal(t, "quay.io/ceph/ceph:v17", nss.Image) + assert.Equal(t, "quay.io/ceph/ceph:v19", nss.Image) nssTester := optest.NewContainersSpecTester(t, []v1.Container{nss}) nssTester.AssertResourceSpec(optest.ResourceLimitExpectations{ CPUResourceLimit: "3000", @@ -308,7 +308,7 @@ func TestReconcileCephNFS_addSecurityConfigsToPod(t *testing.T) { nss := containerByName(pod.InitContainers, "generate-nsswitch-conf") assert.NotEmpty(t, nss) // container should have CLUSTER image and resources from SERVER spec - assert.Equal(t, "quay.io/ceph/ceph:v17", nss.Image) + assert.Equal(t, "quay.io/ceph/ceph:v19", nss.Image) nssTester := optest.NewContainersSpecTester(t, []v1.Container{nss}) nssTester.AssertResourceSpec(optest.ResourceLimitExpectations{ CPUResourceLimit: "3000", diff --git a/pkg/operator/ceph/nfs/spec_test.go b/pkg/operator/ceph/nfs/spec_test.go index 870321581a39..87ec566a50dc 100644 --- a/pkg/operator/ceph/nfs/spec_test.go +++ b/pkg/operator/ceph/nfs/spec_test.go @@ -71,11 +71,11 @@ func newDeploymentSpecTest(t *testing.T) (*ReconcileCephNFS, daemonConfig) { context: c, clusterInfo: &cephclient.ClusterInfo{ FSID: "myfsid", - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, }, cephClusterSpec: &cephv1.ClusterSpec{ CephVersion: cephv1.CephVersionSpec{ - Image: "quay.io/ceph/ceph:v17", + Image: "quay.io/ceph/ceph:v19", }, }, } diff --git a/pkg/operator/ceph/object/config.go b/pkg/operator/ceph/object/config.go index 31082d7bf676..cbfc3ce99491 100644 --- a/pkg/operator/ceph/object/config.go +++ b/pkg/operator/ceph/object/config.go @@ -213,7 +213,7 @@ func (c *clusterConfig) setFlagsMonConfigStore(rgwConfig *rgwConfig) error { // swift in the resource, `admin` is required for the operator to // work, `swift_auth` is required to access swift without keystone // – not sure about the additional APIs - // https://docs.ceph.com/en/quincy/radosgw/config-ref/#confval-rgw_enable_apis + // https://docs.ceph.com/en/latest/radosgw/config-ref/#confval-rgw_enable_apis // see also https://docs.ceph.com/en/octopus/radosgw/config-ref/#swift-settings on disabling s3 // when using '/' as prefix diff --git a/pkg/operator/ceph/object/config_test.go b/pkg/operator/ceph/object/config_test.go index ce5f2eda57e6..88d3ad9d8a72 100644 --- a/pkg/operator/ceph/object/config_test.go +++ b/pkg/operator/ceph/object/config_test.go @@ -29,7 +29,7 @@ import ( func newConfig(t *testing.T) *clusterConfig { clusterInfo := &cephclient.ClusterInfo{ - CephVersion: cephver.Quincy, + CephVersion: cephver.Squid, } clusterSpec := &cephv1.ClusterSpec{ Network: cephv1.NetworkSpec{ diff --git a/pkg/operator/ceph/object/controller_test.go b/pkg/operator/ceph/object/controller_test.go index 1920a834b015..c6e1d2cda31e 100644 --- a/pkg/operator/ceph/object/controller_test.go +++ b/pkg/operator/ceph/object/controller_test.go @@ -149,7 +149,7 @@ const ( dummyVersionsRaw = ` { "mon": { - "ceph version 17.2.1 (0000000000000000) quincy (stable)": 3 + "ceph version 19.2.1 (0000000000000000) squid (stable)": 3 } }` //nolint:gosec // only test values, not a real secret @@ -1049,22 +1049,22 @@ func TestDiffVersions(t *testing.T) { if args[0] == "versions" { return `{ "mon": { - "ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)": 3 + "ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)": 3 }, "mgr": { - "ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)": 1 + "ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)": 1 }, "osd": { - "ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)": 3 + "ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)": 3 }, "mds": { - "ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)": 2 + "ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)": 2 }, "rgw": { - "ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)": 1 + "ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)": 1 }, "overall": { - "ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)": 10 + "ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)": 10 } }`, nil } @@ -1074,7 +1074,7 @@ func TestDiffVersions(t *testing.T) { c := &clusterd.Context{Executor: executor} // desiredCephVersion comes from DetectCephVersion() (ceph --version) which uses ExtractCephVersion() - desiredCephVersion, err := cephver.ExtractCephVersion("ceph version 17.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) quincy (dev)") + desiredCephVersion, err := cephver.ExtractCephVersion("ceph version 19.0.0-9718-g4ff72306 (4ff723061fc15c803dcf6556d02f56bdf56de5fa) squid (dev)") assert.NoError(t, err) // runningCephVersion comes from LeastUptodateDaemonVersion() diff --git a/pkg/operator/ceph/object/objectstore.go b/pkg/operator/ceph/object/objectstore.go index b34642938325..a851520feea0 100644 --- a/pkg/operator/ceph/object/objectstore.go +++ b/pkg/operator/ceph/object/objectstore.go @@ -31,8 +31,6 @@ import ( cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1" "github.com/rook/rook/pkg/clusterd" cephclient "github.com/rook/rook/pkg/daemon/ceph/client" - "github.com/rook/rook/pkg/operator/ceph/config" - cephver "github.com/rook/rook/pkg/operator/ceph/version" "github.com/rook/rook/pkg/operator/k8sutil" "github.com/rook/rook/pkg/util" "github.com/rook/rook/pkg/util/exec" @@ -73,8 +71,7 @@ var ( dataPoolName = "rgw.buckets.data" // An user with system privileges for dashboard service - DashboardUser = "dashboard-admin" - rgwPgNumRemovedQuincyVersion = cephver.CephVersion{Major: 17, Minor: 2, Extra: 2} + DashboardUser = "dashboard-admin" ) type idType struct { @@ -760,20 +757,7 @@ func CreateObjectStorePools(context *Context, cluster *cephv1.ClusterSpec, metad } } - // get the default PG count for rgw metadata pools - var err error - var metadataPoolPGs string - if rgwRadosPGNumIsNew(context.clusterInfo.CephVersion) { - metadataPoolPGs = rgwRadosPoolPgNum - } else { - metadataPoolPGs, err = config.GetMonStore(context.Context, context.clusterInfo).Get("mon.", "rgw_rados_pool_pg_num_min") - } - if err != nil { - logger.Warningf("failed to adjust the PG count for rgw metadata pools. using the general default. %v", err) - metadataPoolPGs = cephclient.DefaultPGCount - } - - if err := createSimilarPools(context, append(metadataPools, rootPool), cluster, metadataPool, metadataPoolPGs); err != nil { + if err := createSimilarPools(context, append(metadataPools, rootPool), cluster, metadataPool, rgwRadosPoolPgNum); err != nil { return errors.Wrap(err, "failed to create metadata pools") } @@ -1069,12 +1053,6 @@ func zoneUpdatePlacementWorkaround(objContext *Context, placementID string, expe return nil } -// Check if this is a recent release of ceph where the legacy rgw_rados_pool_pg_num_min -// is no longer available. -func rgwRadosPGNumIsNew(cephVer cephver.CephVersion) bool { - return cephVer.IsAtLeast(rgwPgNumRemovedQuincyVersion) -} - // configurePoolsConcurrently checks if operator pod resources are set or not func configurePoolsConcurrently() bool { // if operator resources are specified return false as it will lead to operator pod killed due to resource limit diff --git a/pkg/operator/ceph/object/objectstore_test.go b/pkg/operator/ceph/object/objectstore_test.go index 7c0d16c851c4..4662349a53e5 100644 --- a/pkg/operator/ceph/object/objectstore_test.go +++ b/pkg/operator/ceph/object/objectstore_test.go @@ -548,12 +548,6 @@ func TestGetObjectBucketProvisioner(t *testing.T) { } -func TestRGWPGNumVersion(t *testing.T) { - assert.False(t, rgwRadosPGNumIsNew(cephver.CephVersion{Major: 17, Minor: 2, Extra: 1})) - assert.True(t, rgwRadosPGNumIsNew(cephver.CephVersion{Major: 17, Minor: 2, Extra: 2})) - assert.True(t, rgwRadosPGNumIsNew(cephver.CephVersion{Major: 18, Minor: 0, Extra: 0})) -} - func TestCheckDashboardUser(t *testing.T) { storeName := "myobject" executor := &exectest.MockExecutor{ diff --git a/pkg/operator/ceph/object/spec.go b/pkg/operator/ceph/object/spec.go index b72910fb9b55..83d338f5a5dc 100644 --- a/pkg/operator/ceph/object/spec.go +++ b/pkg/operator/ceph/object/spec.go @@ -32,7 +32,6 @@ import ( "github.com/rook/rook/pkg/daemon/ceph/osd/kms" cephconfig "github.com/rook/rook/pkg/operator/ceph/config" "github.com/rook/rook/pkg/operator/ceph/controller" - cephver "github.com/rook/rook/pkg/operator/ceph/version" "github.com/rook/rook/pkg/operator/k8sutil" apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" @@ -70,8 +69,6 @@ chown --recursive --verbose ceph:ceph $VAULT_TOKEN_NEW_PATH ) var ( - cephVersionMinRGWSSES3 = cephver.CephVersion{Major: 17, Minor: 2, Extra: 3} - //go:embed rgw-probe.sh rgwProbeScriptTemplate string ) @@ -693,9 +690,6 @@ func (c *clusterConfig) CheckRGWKMS() (bool, error) { func (c *clusterConfig) CheckRGWSSES3Enabled() (bool, error) { if c.store.Spec.Security != nil && c.store.Spec.Security.ServerSideEncryptionS3.IsEnabled() { - if !c.clusterInfo.CephVersion.IsAtLeast(cephVersionMinRGWSSES3) { - return false, errors.New("minimum ceph quincy is required for AWS-SSE:S3") - } err := kms.ValidateConnectionDetails(c.clusterInfo.Context, c.context, &c.store.Spec.Security.ServerSideEncryptionS3, c.store.Namespace) if err != nil { return false, err diff --git a/pkg/operator/ceph/object/spec_test.go b/pkg/operator/ceph/object/spec_test.go index aeeaa368130e..f920f5f5a1cb 100644 --- a/pkg/operator/ceph/object/spec_test.go +++ b/pkg/operator/ceph/object/spec_test.go @@ -82,7 +82,7 @@ func TestPodSpecs(t *testing.T) { } store.Spec.Gateway.PriorityClassName = "my-priority-class" info := clienttest.CreateTestClusterInfo(1) - info.CephVersion = cephver.Quincy + info.CephVersion = cephver.Squid data := cephconfig.NewStatelessDaemonDataPathMap(cephconfig.RgwType, "default", "rook-ceph", "/var/lib/rook/") c := &clusterConfig{ @@ -150,7 +150,7 @@ func TestSSLPodSpec(t *testing.T) { } store.Spec.Gateway.PriorityClassName = "my-priority-class" info := clienttest.CreateTestClusterInfo(1) - info.CephVersion = cephver.Quincy + info.CephVersion = cephver.Squid info.Namespace = store.Namespace data := cephconfig.NewStatelessDaemonDataPathMap(cephconfig.RgwType, "default", "rook-ceph", "/var/lib/rook/") store.Spec.Gateway.SecurePort = 443 @@ -161,7 +161,7 @@ func TestSSLPodSpec(t *testing.T) { context: context, rookVersion: "rook/rook:myversion", clusterSpec: &cephv1.ClusterSpec{ - CephVersion: cephv1.CephVersionSpec{Image: "quay.io/ceph/ceph:v17"}, + CephVersion: cephv1.CephVersionSpec{Image: "quay.io/ceph/ceph:v19"}, Network: cephv1.NetworkSpec{ HostNetwork: true, }, @@ -560,7 +560,7 @@ func TestCheckRGWSSES3Enabled(t *testing.T) { store: store, clusterInfo: &client.ClusterInfo{Context: ctx, CephVersion: cephver.CephVersion{Major: 17, Minor: 2, Extra: 3}}, clusterSpec: &cephv1.ClusterSpec{ - CephVersion: cephv1.CephVersionSpec{Image: "quay.io/ceph/ceph:v17"}, + CephVersion: cephv1.CephVersionSpec{Image: "quay.io/ceph/ceph:v19"}, DataDirHostPath: "/var/lib/rook", }, } @@ -758,7 +758,7 @@ func TestAWSServerSideEncryption(t *testing.T) { context: context, rookVersion: "rook/rook:myversion", clusterSpec: &cephv1.ClusterSpec{ - CephVersion: cephv1.CephVersionSpec{Image: "quay.io/ceph/ceph:v17.3"}, + CephVersion: cephv1.CephVersionSpec{Image: "quay.io/ceph/ceph:v19.3"}, Network: cephv1.NetworkSpec{ HostNetwork: true, }, @@ -966,12 +966,12 @@ func TestAddDNSNamesToRGWPodSpec(t *testing.T) { {"dns name with zone with custom endpoints ceph v18", []string{"my.dns.name1", "my.dns.name2"}, "--rgw-dns-name=my.dns.name1,my.dns.name2,rook-ceph-rgw-default.mycluster.svc,my.custom.endpoint1,my.custom.endpoint2", cephV18, "myzone", []string{"http://my.custom.endpoint1:80", "http://my.custom.endpoint2:80"}, false}, {"dns name with zone with custom invalid endpoints ceph v18", []string{"my.dns.name1", "my.dns.name2"}, "", cephV18, "myzone", []string{"http://my.custom.endpoint:80", "http://!my.invalid-custom.endpoint:80"}, true}, {"dns name with zone with mixed invalid and valid dnsnames/custom endpoint ceph v18", []string{"my.dns.name", "!my.dns.name"}, "", cephV18, "myzone", []string{"http://my.custom.endpoint1:80", "http://my.custom.endpoint2:80:80"}, true}, - {"no dns names ceph v17", []string{}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, false}, - {"one dns name ceph v17", []string{"my.dns.name"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, - {"multiple dns names ceph v17", []string{"my.dns.name1", "my.dns.name2"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, - {"duplicate dns names ceph v17", []string{"my.dns.name1", "my.dns.name2", "my.dns.name2"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, - {"invalid dns name ceph v17", []string{"!my.invalid-dns.name"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, - {"mixed invalid and valid dns names ceph v17", []string{"my.dns.name", "!my.invalid-dns.name"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, + {"no dns names ceph v19", []string{}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, false}, + {"one dns name ceph v19", []string{"my.dns.name"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, + {"multiple dns names ceph v19", []string{"my.dns.name1", "my.dns.name2"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, + {"duplicate dns names ceph v19", []string{"my.dns.name1", "my.dns.name2", "my.dns.name2"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, + {"invalid dns name ceph v19", []string{"!my.invalid-dns.name"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, + {"mixed invalid and valid dns names ceph v19", []string{"my.dns.name", "!my.invalid-dns.name"}, "", cephver.CephVersion{Major: 17, Minor: 0, Extra: 0}, "", []string{}, true}, {"no dns names ceph v19", []string{}, "", cephver.CephVersion{Major: 19, Minor: 0, Extra: 0}, "", []string{}, false}, {"no dns names with zone ceph v19", []string{}, "", cephver.CephVersion{Major: 19, Minor: 0, Extra: 0}, "myzone", []string{}, false}, {"no dns names with zone and custom endpoints ceph v19", []string{}, "", cephver.CephVersion{Major: 19, Minor: 0, Extra: 0}, "myzone", []string{"http://my.custom.endpoint1:80", "http://my.custom.endpoint2:80"}, false}, diff --git a/pkg/operator/ceph/version/version.go b/pkg/operator/ceph/version/version.go index 705258102da1..de0bbfb96ffb 100644 --- a/pkg/operator/ceph/version/version.go +++ b/pkg/operator/ceph/version/version.go @@ -40,10 +40,8 @@ const ( var ( // Minimum supported version - Minimum = CephVersion{17, 2, 0, 0, ""} + Minimum = CephVersion{18, 2, 0, 0, ""} - // Quincy Ceph version - Quincy = CephVersion{17, 0, 0, 0, ""} // Reef Ceph version Reef = CephVersion{18, 0, 0, 0, ""} // Squid ceph version @@ -52,7 +50,7 @@ var ( Tentacle = CephVersion{20, 0, 0, 0, ""} // supportedVersions are production-ready versions that rook supports - supportedVersions = []CephVersion{Quincy, Reef, Squid} + supportedVersions = []CephVersion{Reef, Squid} // unsupportedVersions are possibly Ceph pin-point release that introduced breaking changes and not recommended unsupportedVersions []CephVersion @@ -86,8 +84,6 @@ func (v *CephVersion) CephVersionFormatted() string { // ReleaseName is the name of the Ceph release func (v *CephVersion) ReleaseName() string { switch v.Major { - case Quincy.Major: - return "quincy" case Reef.Major: return "reef" case Squid.Major: @@ -169,11 +165,6 @@ func (v *CephVersion) isExactly(other CephVersion) bool { return v.Major == other.Major && v.Minor == other.Minor && v.Extra == other.Extra } -// IsQuincy checks if the Ceph version is Quincy -func (v *CephVersion) IsQuincy() bool { - return v.isRelease(Quincy) -} - // IsReef checks if the Ceph version is Reef func (v *CephVersion) IsReef() bool { return v.isRelease(Reef) @@ -227,11 +218,6 @@ func (v *CephVersion) IsAtLeastReef() bool { return v.IsAtLeast(Reef) } -// IsAtLeastQuincy checks that the Ceph version is at least Quincy -func (v *CephVersion) IsAtLeastQuincy() bool { - return v.IsAtLeast(Quincy) -} - // IsIdentical checks if Ceph versions are identical func IsIdentical(a, b CephVersion) bool { if a.Major == b.Major { diff --git a/pkg/operator/ceph/version/version_test.go b/pkg/operator/ceph/version/version_test.go index 1a95a3f1cd9e..013bf986f93c 100644 --- a/pkg/operator/ceph/version/version_test.go +++ b/pkg/operator/ceph/version/version_test.go @@ -24,7 +24,7 @@ import ( ) func TestToString(t *testing.T) { - assert.Equal(t, "17.0.0-0 quincy", Quincy.String()) + assert.Equal(t, "19.0.0-0 squid", Squid.String()) received := CephVersion{-1, 0, 0, 0, ""} expected := fmt.Sprintf("-1.0.0-0 %s", unknownVersionString) @@ -32,11 +32,11 @@ func TestToString(t *testing.T) { } func TestCephVersionFormatted(t *testing.T) { - assert.Equal(t, "ceph version 17.0.0-0 quincy", Quincy.CephVersionFormatted()) + assert.Equal(t, "ceph version 19.0.0-0 squid", Squid.CephVersionFormatted()) } func TestReleaseName(t *testing.T) { - assert.Equal(t, "quincy", Quincy.ReleaseName()) + assert.Equal(t, "squid", Squid.ReleaseName()) ver := CephVersion{-1, 0, 0, 0, ""} assert.Equal(t, unknownVersionString, ver.ReleaseName()) } @@ -79,7 +79,7 @@ ceph version 18.1.33-403-g7ba6bece41 v2d := ` bin/ceph --version *** DEVELOPER MODE: setting PATH, PYTHONPATH and LD_LIBRARY_PATH *** -ceph version Development (no_version) quincy (rc) +ceph version Development (no_version) reef (rc) ` v, err := ExtractCephVersion(v2c) assert.Error(t, err) @@ -105,23 +105,24 @@ func TestSupported(t *testing.T) { } func TestIsRelease(t *testing.T) { - assert.True(t, Quincy.isRelease(Quincy)) assert.True(t, Reef.isRelease(Reef)) + assert.True(t, Squid.isRelease(Squid)) - assert.False(t, Reef.isRelease(Quincy)) + assert.False(t, Reef.isRelease(Squid)) - QuincyUpdate := Quincy - QuincyUpdate.Minor = 33 - QuincyUpdate.Extra = 4 - assert.True(t, QuincyUpdate.isRelease(Quincy)) + ReefUpdate := Reef + ReefUpdate.Minor = 33 + ReefUpdate.Extra = 4 + assert.True(t, ReefUpdate.isRelease(Reef)) } func TestIsReleaseX(t *testing.T) { - assert.False(t, Quincy.IsReef()) + assert.False(t, Squid.IsReef()) } func TestVersionAtLeast(t *testing.T) { - assert.True(t, Quincy.IsAtLeast(Quincy)) + assert.True(t, Squid.IsAtLeast(Squid)) + assert.True(t, Squid.IsAtLeast(Reef)) assert.True(t, (&CephVersion{1, 0, 0, 0, ""}).IsAtLeast(CephVersion{0, 0, 0, 0, ""})) assert.False(t, (&CephVersion{0, 0, 0, 0, ""}).IsAtLeast(CephVersion{1, 0, 0, 0, ""})) @@ -133,8 +134,8 @@ func TestVersionAtLeast(t *testing.T) { } func TestVersionAtLeastX(t *testing.T) { - assert.True(t, Quincy.IsAtLeastQuincy()) - assert.False(t, Quincy.IsAtLeastReef()) + assert.True(t, Reef.IsAtLeastReef()) + assert.False(t, Reef.IsAtLeastSquid()) } func TestIsIdentical(t *testing.T) { @@ -205,7 +206,7 @@ func TestCephVersion_Unsupported(t *testing.T) { fields fields want bool }{ - {"quincy", fields{Major: 17, Minor: 2, Extra: 0, Build: 0}, false}, + {"squid", fields{Major: 19, Minor: 2, Extra: 0, Build: 0}, false}, {"reef", fields{Major: 18, Minor: 2, Extra: 0, Build: 0}, false}, } for _, tt := range tests { diff --git a/tests/framework/installer/ceph_installer.go b/tests/framework/installer/ceph_installer.go index 9d7a725b7fad..a02757fcd83d 100644 --- a/tests/framework/installer/ceph_installer.go +++ b/tests/framework/installer/ceph_installer.go @@ -43,13 +43,11 @@ import ( const ( // test with the latest releases - quincyTestImage = "quay.io/ceph/ceph:v17" - reefTestImage = "quay.io/ceph/ceph:v18" - squidTestImage = "quay.io/ceph/ceph:v19" + reefTestImage = "quay.io/ceph/ceph:v18" + squidTestImage = "quay.io/ceph/ceph:v19" // test with the current development versions - quincyDevelTestImage = "quay.io/ceph/daemon-base:latest-quincy-devel" - reefDevelTestImage = "quay.io/ceph/daemon-base:latest-reef-devel" - squidDevelTestImage = "quay.io/ceph/daemon-base:latest-squid-devel" + reefDevelTestImage = "quay.io/ceph/daemon-base:latest-reef-devel" + squidDevelTestImage = "quay.io/ceph/daemon-base:latest-squid-devel" // test with the latest Ceph main image mainTestImage = "quay.io/ceph/daemon-base:latest-main-devel" cephOperatorLabel = "app=rook-ceph-operator" @@ -69,8 +67,6 @@ mon compact on start = true ) var ( - QuincyVersion = cephv1.CephVersionSpec{Image: quincyTestImage} - QuincyDevelVersion = cephv1.CephVersionSpec{Image: quincyDevelTestImage} ReefVersion = cephv1.CephVersionSpec{Image: reefTestImage} ReefDevelVersion = cephv1.CephVersionSpec{Image: reefDevelTestImage} SquidVersion = cephv1.CephVersionSpec{Image: squidTestImage} @@ -97,8 +93,6 @@ func ReturnCephVersion() cephv1.CephVersionSpec { switch os.Getenv("CEPH_SUITE_VERSION") { case "main": return MainVersion - case "quincy-devel": - return QuincyDevelVersion case "reef-devel": return ReefDevelVersion case "squid-devel": diff --git a/tests/integration/ceph_auth_keystone_test.go b/tests/integration/ceph_auth_keystone_test.go index cf4625b725ad..8d0de029cd06 100644 --- a/tests/integration/ceph_auth_keystone_test.go +++ b/tests/integration/ceph_auth_keystone_test.go @@ -93,7 +93,7 @@ func (h *KeystoneAuthSuite) SetupSuite() { ChangeHostName: true, ConnectionsEncrypted: true, RookVersion: installer.LocalBuildTag, - CephVersion: installer.QuincyVersion, + CephVersion: installer.ReefVersion, SkipClusterCleanup: false, SkipCleanupPolicy: false, } diff --git a/tests/integration/ceph_helm_test.go b/tests/integration/ceph_helm_test.go index 884573f60f29..de16e4319973 100644 --- a/tests/integration/ceph_helm_test.go +++ b/tests/integration/ceph_helm_test.go @@ -70,7 +70,7 @@ func (h *HelmSuite) SetupSuite() { ChangeHostName: true, ConnectionsEncrypted: true, RookVersion: installer.LocalBuildTag, - CephVersion: installer.QuincyVersion, + CephVersion: installer.ReefVersion, } h.settings.ApplyEnvVars() h.installer, h.k8shelper = StartTestCluster(h.T, h.settings) diff --git a/tests/integration/ceph_multi_cluster_test.go b/tests/integration/ceph_multi_cluster_test.go index 5e30ec6394ca..0f4e3c596d8d 100644 --- a/tests/integration/ceph_multi_cluster_test.go +++ b/tests/integration/ceph_multi_cluster_test.go @@ -81,7 +81,7 @@ func (s *MultiClusterDeploySuite) SetupSuite() { Mons: 1, MultipleMgrs: true, RookVersion: installer.LocalBuildTag, - CephVersion: installer.QuincyVersion, + CephVersion: installer.SquidVersion, RequireMsgr2: true, } s.settings.ApplyEnvVars() @@ -91,7 +91,7 @@ func (s *MultiClusterDeploySuite) SetupSuite() { Namespace: "multi-external", OperatorNamespace: s.settings.OperatorNamespace, RookVersion: s.settings.RookVersion, - CephVersion: installer.QuincyVersion, + CephVersion: installer.SquidVersion, } externalSettings.ApplyEnvVars() s.externalManifests = installer.NewCephManifests(externalSettings) diff --git a/tests/integration/ceph_upgrade_test.go b/tests/integration/ceph_upgrade_test.go index a31184e959de..04ee2b4bb7dc 100644 --- a/tests/integration/ceph_upgrade_test.go +++ b/tests/integration/ceph_upgrade_test.go @@ -97,11 +97,11 @@ func (s *UpgradeSuite) baseSetup(useHelm bool, initialRookVersion string, initia } func (s *UpgradeSuite) TestUpgradeRook() { - s.testUpgrade(false, installer.QuincyVersion) + s.testUpgrade(false, installer.ReefVersion) } func (s *UpgradeSuite) TestUpgradeHelm() { - s.testUpgrade(true, installer.QuincyVersion) + s.testUpgrade(true, installer.ReefVersion) } func (s *UpgradeSuite) testUpgrade(useHelm bool, initialCephVersion v1.CephVersionSpec) { @@ -158,17 +158,6 @@ func (s *UpgradeSuite) testUpgrade(useHelm bool, initialCephVersion v1.CephVersi return } - // - // Upgrade from quincy to reef - // - logger.Infof("*** UPGRADING CEPH FROM QUINCY TO REEF ***") - s.gatherLogs(s.settings.OperatorNamespace, "_before_reef_upgrade") - s.upgradeCephVersion(installer.ReefVersion.Image, numOSDs) - // Verify reading and writing to the test clients - newFile = "post-reef-upgrade-file" - s.verifyFilesAfterUpgrade(newFile, rbdFilesToRead, cephfsFilesToRead) - logger.Infof("Verified upgrade from quincy to reef") - // // Upgrade from reef to squid // @@ -183,40 +172,6 @@ func (s *UpgradeSuite) testUpgrade(useHelm bool, initialCephVersion v1.CephVersi checkCephObjectUser(&s.Suite, s.helper, s.k8sh, s.namespace, installer.ObjectStoreName, objectUserID, true, false) } -func (s *UpgradeSuite) TestUpgradeCephToQuincyDevel() { - baseRookImage := installer.LocalBuildTag - s.baseSetup(false, baseRookImage, installer.QuincyVersion) - - objectUserID := "upgraded-user" - preFilename := "pre-upgrade-file" - s.settings.CephVersion = installer.QuincyVersion - numOSDs, rbdFilesToRead, cephfsFilesToRead := s.deployClusterforUpgrade(baseRookImage, objectUserID, preFilename) - clusterInfo := client.AdminTestClusterInfo(s.namespace) - requireBlockImagesRemoved := false - defer func() { - blockTestDataCleanUp(s.helper, s.k8sh, &s.Suite, clusterInfo, installer.BlockPoolName, installer.BlockPoolSCName, blockName, rbdPodName, requireBlockImagesRemoved) - cleanupFilesystemConsumer(s.helper, s.k8sh, &s.Suite, s.namespace, filePodName) - cleanupFilesystem(s.helper, s.k8sh, &s.Suite, s.namespace, installer.FilesystemName) - _ = s.helper.ObjectUserClient.Delete(s.namespace, objectUserID) - _ = s.helper.BucketClient.DeleteObc(obcName, installer.ObjectStoreSCName, bucketPrefix, maxObject, false) - _ = s.helper.BucketClient.DeleteBucketStorageClass(s.namespace, installer.ObjectStoreName, installer.ObjectStoreName, "Delete") - objectStoreCleanUp(&s.Suite, s.helper, s.k8sh, s.settings.Namespace, installer.ObjectStoreName) - }() - - // - // Upgrade from quincy to quincy devel - // - logger.Infof("*** UPGRADING CEPH FROM QUINCY STABLE TO QUINCY DEVEL ***") - s.gatherLogs(s.settings.OperatorNamespace, "_before_quincy_upgrade") - s.upgradeCephVersion(installer.QuincyDevelVersion.Image, numOSDs) - // Verify reading and writing to the test clients - newFile := "post-quincy-upgrade-file" - s.verifyFilesAfterUpgrade(newFile, rbdFilesToRead, cephfsFilesToRead) - logger.Infof("Verified upgrade from quincy stable to quincy devel") - - checkCephObjectUser(&s.Suite, s.helper, s.k8sh, s.namespace, installer.ObjectStoreName, objectUserID, true, false) -} - func (s *UpgradeSuite) TestUpgradeCephToReefDevel() { baseRookImage := installer.LocalBuildTag s.baseSetup(false, baseRookImage, installer.ReefVersion) From cb1dd152ad09ab62a684658ebbfa04bc42900b4b Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Tue, 1 Oct 2024 11:39:20 -0700 Subject: [PATCH 46/54] test: add github-action-helper toolbox functions Added these functions for running commands in the toolbox pod: - toolbox() - ceph() - rbd() - radosgw-admin() Signed-off-by: Joshua Hoblitt --- tests/scripts/github-action-helper.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index 0756a0f77360..d752e4e68726 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -738,6 +738,22 @@ function install_minikube_with_none_driver() { minikube start --kubernetes-version="$1" --driver=none --memory 6g --cpus=2 --addons ingress --cni=calico } +function toolbox() { + kubectl -n rook-ceph exec -it "$(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}')" -- "$@" +} + +function ceph() { + toolbox ceph "$@" +} + +function rbd() { + toolbox rbd "$@" +} + +function radosgw-admin() { + toolbox radosgw-admin "$@" +} + FUNCTION="$1" shift # remove function arg now that we've recorded it # call the function with the remainder of the user-provided args From 9b952e0a553d06be42f907cfb8a0d0f3b4102483 Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Wed, 25 Sep 2024 14:21:53 -0700 Subject: [PATCH 47/54] rgw: fix cephObjectStore failing with pre-existing pools When attempting to use pre-existing (or cephBlockPool managed) pools and the cephObjectStore.spec.{metadataPool,dataPool} fields are not specified, rgw creation will fail with this error: 2024-09-25 21:00:17.744358 E | ceph-object-controller: failed to reconcile CephObjectStore "rook-ceph/test1". failed to create object store deployments: failed to create object pools: failed to create metadata pools: failed to create pool "test1.rgw.control": pool "test1.rgw.control" type is not defined as replicated or erasure coded Signed-off-by: Joshua Hoblitt --- pkg/operator/ceph/object/objectstore.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/operator/ceph/object/objectstore.go b/pkg/operator/ceph/object/objectstore.go index b34642938325..a697fae46a8a 100644 --- a/pkg/operator/ceph/object/objectstore.go +++ b/pkg/operator/ceph/object/objectstore.go @@ -758,6 +758,9 @@ func CreateObjectStorePools(context *Context, cluster *cephv1.ClusterSpec, metad if len(missingPools) > 0 { return fmt.Errorf("CR store pools are missing: %v", missingPools) } + + // pools exist, nothing to do + return nil } // get the default PG count for rgw metadata pools From ed8156017e5cfc00304838bb32b1859444665366 Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Mon, 30 Sep 2024 12:14:43 -0700 Subject: [PATCH 48/54] test: add object-with-cephblockpool canary test Signed-off-by: Joshua Hoblitt --- .github/workflows/canary-integration-test.yml | 50 +++++++ .../object-with-cephblockpools-test.yaml | 135 ++++++++++++++++++ tests/scripts/github-action-helper.sh | 37 +++++ 3 files changed, 222 insertions(+) create mode 100644 deploy/examples/object-with-cephblockpools-test.yaml diff --git a/.github/workflows/canary-integration-test.yml b/.github/workflows/canary-integration-test.yml index d3e90d0e1a4a..8b2cc11584df 100644 --- a/.github/workflows/canary-integration-test.yml +++ b/.github/workflows/canary-integration-test.yml @@ -1698,3 +1698,53 @@ jobs: uses: ./.github/workflows/collect-logs with: name: ${{ github.job }}-${{ matrix.ceph-image }} + + object-with-cephblockpools: + runs-on: ubuntu-22.04 + if: "!contains(github.event.pull_request.labels.*.name, 'skip-ci')" + strategy: + matrix: + ceph-image: ${{ fromJson(inputs.ceph_images) }} + steps: + - name: checkout + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + with: + fetch-depth: 0 + + - name: consider debugging + uses: ./.github/workflows/tmate_debug + with: + use-tmate: ${{ secrets.USE_TMATE }} + + - name: setup cluster resources + uses: ./.github/workflows/canary-test-config + + - name: set Ceph version in CephCluster manifest + run: tests/scripts/github-action-helper.sh replace_ceph_image "deploy/examples/cluster-test.yaml" "${{ github.event.inputs.ceph-image }}" + + - name: validate-yaml + run: tests/scripts/github-action-helper.sh validate_yaml + + - name: use local disk and create partitions for osds + run: | + tests/scripts/github-action-helper.sh use_local_disk + tests/scripts/github-action-helper.sh create_partitions_for_osds + + - name: deploy cluster + run: tests/scripts/github-action-helper.sh deploy_cluster + + - name: create CephBlockPool(s) and CephObjectStore + shell: bash --noprofile --norc -eo pipefail -x {0} + run: kubectl create -f deploy/examples/object-with-cephblockpools-test.yaml + + - name: wait for CephObjectStore to be ready + run: tests/scripts/validate_cluster.sh rgw object-with-cephblockpools + + - name: check for pools created by RGW that are unexpected + run: tests/scripts/github-action-helper.sh test_object_with_cephblockpools_extra_pools + + - name: collect common logs + if: always() + uses: ./.github/workflows/collect-logs + with: + name: ${{ github.job }}-${{ matrix.ceph-image }} diff --git a/deploy/examples/object-with-cephblockpools-test.yaml b/deploy/examples/object-with-cephblockpools-test.yaml new file mode 100644 index 000000000000..5d67248f475c --- /dev/null +++ b/deploy/examples/object-with-cephblockpools-test.yaml @@ -0,0 +1,135 @@ +########################################################## +# Create an object store using pre-created pools +# kubectl create -f object-with-cephblockpools-test.yaml +########################################################## +--- +apiVersion: ceph.rook.io/v1 +kind: CephObjectStore +metadata: + name: object-with-cephblockpools + namespace: rook-ceph # namespace:cluster +spec: + gateway: + port: 80 + instances: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: rgw.root + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + name: .rgw.root + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.control + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.meta + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.log + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.buckets.index + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.buckets.non-ec + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.otp + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 +--- +apiVersion: ceph.rook.io/v1 +kind: CephBlockPool +metadata: + name: object-with-cephblockpools.rgw.buckets.data + namespace: rook-ceph # namespace:cluster +spec: + application: rgw + failureDomain: osd + parameters: + pg_autoscale_mode: "off" + pg_num: "1" + replicated: + requireSafeReplicaSize: false + size: 1 diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index d752e4e68726..99c4e63f5d97 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -754,6 +754,43 @@ function radosgw-admin() { toolbox radosgw-admin "$@" } +function test_object_with_cephblockpools_extra_pools() { + expected_pools=( + .mgr + .rgw.root + object-with-cephblockpools.rgw.control + object-with-cephblockpools.rgw.meta + object-with-cephblockpools.rgw.log + object-with-cephblockpools.rgw.buckets.index + object-with-cephblockpools.rgw.buckets.non-ec + object-with-cephblockpools.rgw.otp + object-with-cephblockpools.rgw.buckets.data + ) + + output=$(ceph osd pool ls) + readarray -t live_pools < <(printf '%s' "$output") + + errors=0 + for l in "${live_pools[@]}"; do + found=false + for e in "${expected_pools[@]}"; do + if [[ "$l" == "$e" ]]; then + found=true + break + fi + done + if [[ "$found" == false ]]; then + echo "Live pool $l is not an expected pool" + errors=$((errors+1)) + fi + done + + if [[ $errors -gt 0 ]]; then + echo "Found $errors errors" + exit $errors + fi +} + FUNCTION="$1" shift # remove function arg now that we've recorded it # call the function with the remainder of the user-provided args From 31d55b90fef8ff646c9117555cef64eb3781af1e Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Tue, 1 Oct 2024 16:14:14 -0700 Subject: [PATCH 49/54] test: mv canary test specific resources out of deploy_cluster() Factor out most of the CRs used by various canary tests to a new deploy_cluster_full_of_cruft_please_stop_using_this() function. Signed-off-by: Joshua Hoblitt --- .github/workflows/canary-integration-test.yml | 22 ++++++++++--- tests/scripts/github-action-helper.sh | 33 ++++++++++++++++--- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/.github/workflows/canary-integration-test.yml b/.github/workflows/canary-integration-test.yml index 8b2cc11584df..a00973870d72 100644 --- a/.github/workflows/canary-integration-test.yml +++ b/.github/workflows/canary-integration-test.yml @@ -49,7 +49,9 @@ jobs: tests/scripts/github-action-helper.sh create_partitions_for_osds - name: deploy cluster - run: tests/scripts/github-action-helper.sh deploy_cluster + run: | + tests/scripts/github-action-helper.sh deploy_cluster + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster - name: setup csi-addons run: tests/scripts/csiaddons.sh setup_csiaddons @@ -364,6 +366,7 @@ jobs: run: | export ALLOW_LOOP_DEVICES=true tests/scripts/github-action-helper.sh deploy_cluster loop + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster tests/scripts/github-action-helper.sh create_operator_toolbox - name: wait for prepare pod @@ -433,7 +436,9 @@ jobs: tests/scripts/create-bluestore-partitions.sh --disk "$BLOCK" --wipe-only - name: deploy cluster - run: tests/scripts/github-action-helper.sh deploy_cluster two_osds_in_device + run: | + tests/scripts/github-action-helper.sh deploy_cluster two_osds_in_device + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster - name: wait for prepare pod run: tests/scripts/github-action-helper.sh wait_for_prepare_pod 2 @@ -482,6 +487,7 @@ jobs: - name: deploy cluster run: | tests/scripts/github-action-helper.sh deploy_cluster osd_with_metadata_partition_device + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster - name: wait for prepare pod run: tests/scripts/github-action-helper.sh wait_for_prepare_pod 1 @@ -537,7 +543,9 @@ jobs: tests/scripts/github-action-helper.sh create_LV_on_disk $(sudo losetup --find --show test-rook.img) - name: deploy cluster - run: tests/scripts/github-action-helper.sh deploy_cluster osd_with_metadata_device + run: | + tests/scripts/github-action-helper.sh deploy_cluster osd_with_metadata_device + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster - name: wait for prepare pod run: tests/scripts/github-action-helper.sh wait_for_prepare_pod 1 @@ -587,7 +595,9 @@ jobs: tests/scripts/create-bluestore-partitions.sh --disk "$BLOCK" --wipe-only - name: deploy cluster - run: tests/scripts/github-action-helper.sh deploy_cluster encryption + run: | + tests/scripts/github-action-helper.sh deploy_cluster encryption + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster encryption - name: wait for prepare pod run: tests/scripts/github-action-helper.sh wait_for_prepare_pod 1 @@ -642,7 +652,9 @@ jobs: tests/scripts/github-action-helper.sh create_LV_on_disk $BLOCK - name: deploy cluster - run: tests/scripts/github-action-helper.sh deploy_cluster lvm + run: | + tests/scripts/github-action-helper.sh deploy_cluster lvm + tests/scripts/github-action-helper.sh deploy_all_additional_resources_on_cluster - name: wait for prepare pod run: tests/scripts/github-action-helper.sh wait_for_prepare_pod 1 diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index 99c4e63f5d97..62ae7cc07b33 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -20,6 +20,8 @@ set -xeEo pipefail # VARIABLES # ############# +REPO_DIR="$(readlink -f -- "${BASH_SOURCE%/*}/../..")" + function find_extra_block_dev() { # shellcheck disable=SC2005 # redirect doesn't work with sudo, so use echo echo "$(sudo lsblk)" >/dev/stderr # print lsblk output to stderr for debugging in case of future errors @@ -257,6 +259,7 @@ function deploy_manifest_with_local_build() { # Deploy toolbox with same ceph version as the cluster-test for ci function deploy_toolbox() { + cd "${REPO_DIR}/deploy/examples" sed -i 's/image: quay\.io\/ceph\/ceph:.*/image: quay.io\/ceph\/ceph:v18/' toolbox.yaml kubectl create -f toolbox.yaml } @@ -271,9 +274,15 @@ function replace_ceph_image() { sed -i "s|image: .*ceph/ceph:.*|image: ${ceph_image}|g" "${file}" } +# Deploy the operator, a CephCluster, and the toolbox. This is intended to be a +# minimal deployment generic enough to be used by most canary tests. Each +# canary test should be installing its own set of resources as a job step or +# using dedicated helper functions. function deploy_cluster() { - cd deploy/examples + cd "${REPO_DIR}/deploy/examples" + deploy_manifest_with_local_build operator.yaml + if [ $# == 0 ]; then sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}|g" cluster-test.yaml elif [ "$1" = "two_osds_in_device" ]; then @@ -281,8 +290,8 @@ function deploy_cluster() { elif [ "$1" = "osd_with_metadata_device" ]; then sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n metadataDevice: /dev/test-rook-vg/test-rook-lv|g" cluster-test.yaml elif [ "$1" = "osd_with_metadata_partition_device" ]; then - yq w -i -d0 cluster-test.yaml spec.storage.devices[0].name ${BLOCK}2 - yq w -i -d0 cluster-test.yaml spec.storage.devices[0].config.metadataDevice ${BLOCK}1 + yq w -i -d0 cluster-test.yaml spec.storage.devices[0].name "${BLOCK}2" + yq w -i -d0 cluster-test.yaml spec.storage.devices[0].config.metadataDevice "${BLOCK}1" elif [ "$1" = "encryption" ]; then sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n encryptedDevice: \"true\"|g" cluster-test.yaml elif [ "$1" = "lvm" ]; then @@ -294,13 +303,28 @@ function deploy_cluster() { echo "invalid argument: $*" >&2 exit 1 fi + # enable monitoring yq w -i -d0 cluster-test.yaml spec.monitoring.enabled true kubectl create -f https://raw.githubusercontent.com/coreos/prometheus-operator/v0.71.1/bundle.yaml kubectl create -f monitoring/rbac.yaml - # create the cluster resources kubectl create -f cluster-test.yaml + + deploy_toolbox +} + +# These resources were extracted from the original deploy_cluster(), which was +# deploying a smorgasbord of resources used by multiple canary tests. +# +# Use of this function is discouraged. Existing users should migrate away and +# deploy only the necessary resources for the test scenario in their own job +# steps. +# +# The addition of new resources this function is forbidden! +function deploy_all_additional_resources_on_cluster() { + cd "${REPO_DIR}/deploy/examples" + kubectl create -f object-shared-pools-test.yaml kubectl create -f object-a.yaml kubectl create -f object-b.yaml @@ -312,7 +336,6 @@ function deploy_cluster() { kubectl create -f filesystem-mirror.yaml kubectl create -f nfs-test.yaml kubectl create -f subvolumegroup.yaml - deploy_toolbox } function deploy_csi_hostnetwork_disabled_cluster() { From 581fd5c197cf502d5e6731b8ff8b3b4c98bbac58 Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Tue, 1 Oct 2024 17:50:19 -0700 Subject: [PATCH 50/54] test: convert all github-action-helper functs to $REPO_DIR This allows all functions to be called in any order without concern for the CWD. Signed-off-by: Joshua Hoblitt --- tests/scripts/github-action-helper.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index 62ae7cc07b33..f33cc4f874e0 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -215,7 +215,7 @@ function build_rook_all() { } function validate_yaml() { - cd deploy/examples + cd "${REPO_DIR}/deploy/examples" kubectl create -f crds.yaml -f common.yaml -f csi/nfs/rbac.yaml # create the volume replication CRDs @@ -242,7 +242,7 @@ function validate_yaml() { function create_cluster_prerequisites() { # this might be called from another function that has already done a cd - (cd deploy/examples && kubectl create -f crds.yaml -f common.yaml -f csi/nfs/rbac.yaml) + (cd "${REPO_DIR}/deploy/examples" && kubectl create -f crds.yaml -f common.yaml -f csi/nfs/rbac.yaml) } function deploy_manifest_with_local_build() { @@ -340,7 +340,7 @@ function deploy_all_additional_resources_on_cluster() { function deploy_csi_hostnetwork_disabled_cluster() { create_cluster_prerequisites - cd deploy/examples + cd "${REPO_DIR}/deploy/examples" sed -i 's/.*CSI_ENABLE_HOST_NETWORK:.*/ CSI_ENABLE_HOST_NETWORK: \"false\"/g' operator.yaml deploy_manifest_with_local_build operator.yaml if [ $# == 0 ]; then @@ -447,7 +447,7 @@ function deploy_first_rook_cluster() { DEVICE_NAME="$(tests/scripts/github-action-helper.sh find_extra_block_dev)" export BLOCK="/dev/${DEVICE_NAME}" create_cluster_prerequisites - cd deploy/examples/ + cd "${REPO_DIR}/deploy/examples" deploy_manifest_with_local_build operator.yaml yq w -i -d0 cluster-test.yaml spec.dashboard.enabled false @@ -460,7 +460,7 @@ function deploy_first_rook_cluster() { function deploy_second_rook_cluster() { DEVICE_NAME="$(tests/scripts/github-action-helper.sh find_extra_block_dev)" export BLOCK="/dev/${DEVICE_NAME}" - cd deploy/examples/ + cd "${REPO_DIR}/deploy/examples" NAMESPACE=rook-ceph-secondary envsubst s3cfg [default] host_bucket = no.way @@ -643,7 +643,7 @@ EOF } function deploy_multus_cluster() { - cd deploy/examples + cd "${REPO_DIR}/deploy/examples" sed -i 's/.*ROOK_CSI_ENABLE_NFS:.*/ ROOK_CSI_ENABLE_NFS: \"true\"/g' operator.yaml deploy_manifest_with_local_build operator.yaml deploy_toolbox @@ -662,7 +662,7 @@ function test_multus_connections() { } function create_operator_toolbox() { - cd deploy/examples + cd "${REPO_DIR}/deploy/examples" sed -i "s|image: docker.io/rook/ceph:.*|image: docker.io/rook/ceph:local-build|g" toolbox-operator-image.yaml kubectl create -f toolbox-operator-image.yaml } @@ -689,7 +689,7 @@ EOF } function test_csi_rbd_workload { - cd deploy/examples/csi/rbd + cd "${REPO_DIR}/deploy/examples/csi/rbd" sed -i 's|size: 3|size: 1|g' storageclass.yaml sed -i 's|requireSafeReplicaSize: true|requireSafeReplicaSize: false|g' storageclass.yaml kubectl create -f storageclass.yaml @@ -704,7 +704,7 @@ function test_csi_rbd_workload { } function test_csi_cephfs_workload { - cd deploy/examples/csi/cephfs + cd "${REPO_DIR}/deploy/examples/csi/cephfs" kubectl create -f storageclass.yaml kubectl create -f pvc.yaml kubectl create -f pod.yaml @@ -717,7 +717,7 @@ function test_csi_cephfs_workload { } function test_csi_nfs_workload { - cd deploy/examples/csi/nfs + cd "${REPO_DIR}/deploy/examples/csi/nfs" sed -i "s|#- debug|- nolock|" storageclass.yaml kubectl create -f storageclass.yaml kubectl create -f pvc.yaml From 76fa776795745be801e3041e85348720cd6ce7cc Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Wed, 2 Oct 2024 10:25:03 -0700 Subject: [PATCH 51/54] rgw: change CephObjectZone.spec.{dataPool,metadataPool} to optional These fields must be optional in order to allow usage of pre-existing pools managed by CephBlockPool CR(s). Signed-off-by: Joshua Hoblitt --- Documentation/CRDs/specification.md | 4 ++++ deploy/charts/rook-ceph/templates/resources.yaml | 2 -- deploy/examples/crds.yaml | 2 -- pkg/apis/ceph.rook.io/v1/types.go | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Documentation/CRDs/specification.md b/Documentation/CRDs/specification.md index ebd043d22f6e..9a1efffc7b2c 100644 --- a/Documentation/CRDs/specification.md +++ b/Documentation/CRDs/specification.md @@ -2180,6 +2180,7 @@ PoolSpec +(Optional)

The metadata pool settings

@@ -2193,6 +2194,7 @@ PoolSpec +(Optional)

The data pool settings

@@ -10367,6 +10369,7 @@ PoolSpec +(Optional)

The metadata pool settings

@@ -10380,6 +10383,7 @@ PoolSpec +(Optional)

The data pool settings

diff --git a/deploy/charts/rook-ceph/templates/resources.yaml b/deploy/charts/rook-ceph/templates/resources.yaml index 0092ad799fad..bd2989590acb 100644 --- a/deploy/charts/rook-ceph/templates/resources.yaml +++ b/deploy/charts/rook-ceph/templates/resources.yaml @@ -13323,8 +13323,6 @@ spec: description: The display name for the ceph users type: string required: - - dataPool - - metadataPool - zoneGroup type: object status: diff --git a/deploy/examples/crds.yaml b/deploy/examples/crds.yaml index aa8759c17784..0d57c5108a95 100644 --- a/deploy/examples/crds.yaml +++ b/deploy/examples/crds.yaml @@ -13311,8 +13311,6 @@ spec: description: The display name for the ceph users type: string required: - - dataPool - - metadataPool - zoneGroup type: object status: diff --git a/pkg/apis/ceph.rook.io/v1/types.go b/pkg/apis/ceph.rook.io/v1/types.go index d06c20081f95..170fb237f4ee 100755 --- a/pkg/apis/ceph.rook.io/v1/types.go +++ b/pkg/apis/ceph.rook.io/v1/types.go @@ -2128,10 +2128,12 @@ type ObjectZoneSpec struct { ZoneGroup string `json:"zoneGroup"` // The metadata pool settings + // +optional // +nullable MetadataPool PoolSpec `json:"metadataPool"` // The data pool settings + // +optional // +nullable DataPool PoolSpec `json:"dataPool"` From d30111468078f1d25cefbbe639b4efdca472bca2 Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Thu, 3 Oct 2024 11:06:59 -0700 Subject: [PATCH 52/54] test: do not always run `sudo lsblk` in github-action-helper.sh This removes the execution of `sudo lsblk` three times for every single invocation of the script. Usage of the BLOCK var is replaced with functions which memoize the result of probing for block devices. Signed-off-by: Joshua Hoblitt --- tests/scripts/github-action-helper.sh | 88 ++++++++++++++------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index f33cc4f874e0..26a2b59e0646 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -21,6 +21,14 @@ set -xeEo pipefail ############# REPO_DIR="$(readlink -f -- "${BASH_SOURCE%/*}/../..")" +NETWORK_ERROR="connection reset by peer" +SERVICE_UNAVAILABLE_ERROR="Service Unavailable" +INTERNAL_ERROR="INTERNAL_ERROR" +INTERNAL_SERVER_ERROR="500 Internal Server Error" + +############# +# FUNCTIONS # +############# function find_extra_block_dev() { # shellcheck disable=SC2005 # redirect doesn't work with sudo, so use echo @@ -37,19 +45,19 @@ function find_extra_block_dev() { echo "$extra_dev" # output of function } -: "${BLOCK:=$(find_extra_block_dev)}" -# by definition, in this file, BLOCK should only contain the "sdX" portion of the block device name -# some external scripts export BLOCK as the full "/dev/sdX" path, which this script must handle -BLOCK="$(basename $BLOCK)" +function block_dev() { + declare -g DEFAULT_BLOCK_DEV + : "${DEFAULT_BLOCK_DEV:=/dev/$(block_dev_basename)}" -NETWORK_ERROR="connection reset by peer" -SERVICE_UNAVAILABLE_ERROR="Service Unavailable" -INTERNAL_ERROR="INTERNAL_ERROR" -INTERNAL_SERVER_ERROR="500 Internal Server Error" + echo "$DEFAULT_BLOCK_DEV" +} -############# -# FUNCTIONS # -############# +function block_dev_basename() { + declare -g DEFAULT_BLOCK_DEV_BASENAME + : "${DEFAULT_BLOCK_DEV_BASENAME:=$(find_extra_block_dev)}" + + echo "$DEFAULT_BLOCK_DEV_BASENAME" +} function install_deps() { sudo wget https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64 -O /usr/local/bin/yq @@ -79,7 +87,7 @@ function prepare_loop_devices() { } function use_local_disk() { - BLOCK_DATA_PART="/dev/${BLOCK}1" + BLOCK_DATA_PART="$(block_dev)1" sudo apt purge snapd -y sudo dmsetup version || true sudo swapoff --all --verbose @@ -89,9 +97,9 @@ function use_local_disk() { sudo wipefs --all --force "$BLOCK_DATA_PART" else # it's the hosted runner! - sudo sgdisk --zap-all -- "/dev/${BLOCK}" - sudo dd if=/dev/zero of="/dev/${BLOCK}" bs=1M count=10 oflag=direct,dsync - sudo parted -s "/dev/${BLOCK}" mklabel gpt + sudo sgdisk --zap-all -- "$(block_dev)" + sudo dd if=/dev/zero of="$(block_dev)" bs=1M count=10 oflag=direct,dsync + sudo parted -s "$(block_dev)" mklabel gpt fi sudo lsblk } @@ -103,7 +111,7 @@ function use_local_disk_for_integration_test() { sudo umount /mnt sudo sed -i.bak '/\/mnt/d' /etc/fstab # search for the device since it keeps changing between sda and sdb - PARTITION="/dev/${BLOCK}1" + PARTITION="$(block_dev)1" sudo wipefs --all --force "$PARTITION" sudo dd if=/dev/zero of="${PARTITION}" bs=1M count=1 sudo lsblk --bytes @@ -112,7 +120,7 @@ function use_local_disk_for_integration_test() { # for more details see: https://github.com/rook/rook/issues/7405 echo "SUBSYSTEM==\"block\", ATTR{size}==\"29356032\", ACTION==\"add\", RUN+=\"/bin/chown 167:167 $PARTITION\"" | sudo tee -a /etc/udev/rules.d/01-rook.rules # for below, see: https://access.redhat.com/solutions/1465913 - echo "ACTION==\"add|change\", KERNEL==\"${BLOCK}\", OPTIONS:=\"nowatch\"" | sudo tee -a /etc/udev/rules.d/99-z-rook-nowatch.rules + echo "ACTION==\"add|change\", KERNEL==\"$(block_dev_basename)\", OPTIONS:=\"nowatch\"" | sudo tee -a /etc/udev/rules.d/99-z-rook-nowatch.rules # The partition is still getting reloaded occasionally during operation. See https://github.com/rook/rook/issues/8975 # Try issuing some disk-inspection commands to jog the system so it won't reload the partitions # during OSD provisioning. @@ -120,31 +128,31 @@ function use_local_disk_for_integration_test() { sudo udevadm trigger || true time sudo udevadm settle || true sudo partprobe || true - sudo lsblk --noheadings --pairs "/dev/${BLOCK}" || true - sudo sgdisk --print "/dev/${BLOCK}" || true - sudo udevadm info --query=property "/dev/${BLOCK}" || true + sudo lsblk --noheadings --pairs "$(block_dev)" || true + sudo sgdisk --print "$(block_dev)" || true + sudo udevadm info --query=property "$(block_dev)" || true sudo lsblk --noheadings --pairs "${PARTITION}" || true journalctl -o short-precise --dmesg | tail -40 || true cat /etc/fstab || true } function create_partitions_for_osds() { - tests/scripts/create-bluestore-partitions.sh --disk "/dev/$BLOCK" --osd-count 2 + tests/scripts/create-bluestore-partitions.sh --disk "$(block_dev)" --osd-count 2 sudo lsblk } function create_bluestore_partitions_and_pvcs() { - BLOCK_PART="/dev/$BLOCK"2 - DB_PART="/dev/$BLOCK"1 - tests/scripts/create-bluestore-partitions.sh --disk "/dev/$BLOCK" --bluestore-type block.db --osd-count 1 + BLOCK_PART="$(block_dev)2" + DB_PART="$(block_dev)1" + tests/scripts/create-bluestore-partitions.sh --disk "$(block_dev)" --bluestore-type block.db --osd-count 1 tests/scripts/localPathPV.sh "$BLOCK_PART" "$DB_PART" } function create_bluestore_partitions_and_pvcs_for_wal() { - BLOCK_PART="/dev/$BLOCK"3 - DB_PART="/dev/$BLOCK"1 - WAL_PART="/dev/$BLOCK"2 - tests/scripts/create-bluestore-partitions.sh --disk "/dev/$BLOCK" --bluestore-type block.wal --osd-count 1 + BLOCK_PART="$(block_dev)3" + DB_PART="$(block_dev)1" + WAL_PART="$(block_dev)2" + tests/scripts/create-bluestore-partitions.sh --disk "$(block_dev)" --bluestore-type block.wal --osd-count 1 tests/scripts/localPathPV.sh "$BLOCK_PART" "$DB_PART" "$WAL_PART" } @@ -284,21 +292,21 @@ function deploy_cluster() { deploy_manifest_with_local_build operator.yaml if [ $# == 0 ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)|g" cluster-test.yaml elif [ "$1" = "two_osds_in_device" ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n osdsPerDevice: \"2\"|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)\n config:\n osdsPerDevice: \"2\"|g" cluster-test.yaml elif [ "$1" = "osd_with_metadata_device" ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n metadataDevice: /dev/test-rook-vg/test-rook-lv|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)\n config:\n metadataDevice: /dev/test-rook-vg/test-rook-lv|g" cluster-test.yaml elif [ "$1" = "osd_with_metadata_partition_device" ]; then - yq w -i -d0 cluster-test.yaml spec.storage.devices[0].name "${BLOCK}2" - yq w -i -d0 cluster-test.yaml spec.storage.devices[0].config.metadataDevice "${BLOCK}1" + yq w -i -d0 cluster-test.yaml spec.storage.devices[0].name "$(block_dev_basename)2" + yq w -i -d0 cluster-test.yaml spec.storage.devices[0].config.metadataDevice "$(block_dev_basename)1" elif [ "$1" = "encryption" ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n encryptedDevice: \"true\"|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)\n config:\n encryptedDevice: \"true\"|g" cluster-test.yaml elif [ "$1" = "lvm" ]; then sed -i "s|#deviceFilter:|devices:\n - name: \"/dev/test-rook-vg/test-rook-lv\"|g" cluster-test.yaml elif [ "$1" = "loop" ]; then # add both /dev/sdX1 and loop device to test them at the same time - sed -i "s|#deviceFilter:|devices:\n - name: \"${BLOCK}\"\n - name: \"/dev/loop1\"|g" cluster-test.yaml + sed -i "s|#deviceFilter:|devices:\n - name: \"$(block_dev_basename)\"\n - name: \"/dev/loop1\"|g" cluster-test.yaml else echo "invalid argument: $*" >&2 exit 1 @@ -344,11 +352,11 @@ function deploy_csi_hostnetwork_disabled_cluster() { sed -i 's/.*CSI_ENABLE_HOST_NETWORK:.*/ CSI_ENABLE_HOST_NETWORK: \"false\"/g' operator.yaml deploy_manifest_with_local_build operator.yaml if [ $# == 0 ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)|g" cluster-test.yaml elif [ "$1" = "two_osds_in_device" ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n osdsPerDevice: \"2\"|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)\n config:\n osdsPerDevice: \"2\"|g" cluster-test.yaml elif [ "$1" = "osd_with_metadata_device" ]; then - sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\//}\n config:\n metadataDevice: /dev/test-rook-vg/test-rook-lv|g" cluster-test.yaml + sed -i "s|#deviceFilter:|deviceFilter: $(block_dev_basename)\n config:\n metadataDevice: /dev/test-rook-vg/test-rook-lv|g" cluster-test.yaml fi kubectl create -f nfs-test.yaml kubectl create -f cluster-test.yaml @@ -445,7 +453,6 @@ function create_LV_on_disk() { function deploy_first_rook_cluster() { DEVICE_NAME="$(tests/scripts/github-action-helper.sh find_extra_block_dev)" - export BLOCK="/dev/${DEVICE_NAME}" create_cluster_prerequisites cd "${REPO_DIR}/deploy/examples" @@ -459,7 +466,6 @@ function deploy_first_rook_cluster() { function deploy_second_rook_cluster() { DEVICE_NAME="$(tests/scripts/github-action-helper.sh find_extra_block_dev)" - export BLOCK="/dev/${DEVICE_NAME}" cd "${REPO_DIR}/deploy/examples" NAMESPACE=rook-ceph-secondary envsubst Date: Thu, 3 Oct 2024 08:37:39 -0600 Subject: [PATCH 53/54] mds: fix liveness probe timeout When the MDS liveness probe times out, it should not fail the probe. If the cluster has a network partition or other issue that causes the Ceph mon cluster to become unstable, `ceph ...` commands can hang and cause a timeout. In this case, the MDS should not be restarted so as to not cause cascading cluster disruption. Signed-off-by: Blaine Gardner --- pkg/operator/ceph/file/mds/livenessprobe.go | 5 ++--- pkg/operator/ceph/file/mds/livenessprobe.sh | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/operator/ceph/file/mds/livenessprobe.go b/pkg/operator/ceph/file/mds/livenessprobe.go index beec3882ac5d..6f318d6bab89 100644 --- a/pkg/operator/ceph/file/mds/livenessprobe.go +++ b/pkg/operator/ceph/file/mds/livenessprobe.go @@ -3,7 +3,6 @@ package mds import ( "bytes" _ "embed" - "fmt" "html/template" "github.com/pkg/errors" @@ -38,6 +37,7 @@ type mdsLivenessProbeConfig struct { MdsId string FilesystemName string Keyring string + CmdTimeout int32 } func renderProbe(mdsLivenessProbeConfigValue mdsLivenessProbeConfig) (string, error) { @@ -64,6 +64,7 @@ func generateMDSLivenessProbeExecDaemon(daemonID, filesystemName, keyring string MdsId: daemonID, FilesystemName: filesystemName, Keyring: keyring, + CmdTimeout: mdsCmdTimeout, } mdsLivenessProbeCmd, err := renderProbe(mdsLivenessProbeConfigValue) @@ -75,8 +76,6 @@ func generateMDSLivenessProbeExecDaemon(daemonID, filesystemName, keyring string ProbeHandler: v1.ProbeHandler{ Exec: &v1.ExecAction{ Command: []string{ - "timeout", - fmt.Sprintf("%d", mdsCmdTimeout), "sh", "-c", mdsLivenessProbeCmd, diff --git a/pkg/operator/ceph/file/mds/livenessprobe.sh b/pkg/operator/ceph/file/mds/livenessprobe.sh index 97ad139bdbeb..5cddfac15f32 100644 --- a/pkg/operator/ceph/file/mds/livenessprobe.sh +++ b/pkg/operator/ceph/file/mds/livenessprobe.sh @@ -5,8 +5,9 @@ MDS_ID="{{ .MdsId }}" FILESYSTEM_NAME="{{ .FilesystemName }}" KEYRING="{{ .Keyring }}" +CMD_TIMEOUT="{{ .CmdTimeout }}" -outp="$(ceph fs dump --mon-host="$ROOK_CEPH_MON_HOST" --mon-initial-members="$ROOK_CEPH_MON_INITIAL_MEMBERS" --keyring "$KEYRING" --format json)" +outp="$(ceph fs dump --mon-host="$ROOK_CEPH_MON_HOST" --mon-initial-members="$ROOK_CEPH_MON_INITIAL_MEMBERS" --keyring "$KEYRING" --connect-timeout="$CMD_TIMEOUT" --format json)" rc=$? if [ $rc -ne 0 ]; then echo "ceph MDS dump check failed with the following output:" From 158565285a2a0a8f169bcd7797c211a840131d90 Mon Sep 17 00:00:00 2001 From: Ceph Jenkins Date: Mon, 7 Oct 2024 01:06:03 -0400 Subject: [PATCH 54/54] csv: add additional csv changes that other commits bring add generated csv changes Signed-off-by: Ceph Jenkins --- build/csv/ceph/ceph.rook.io_cephobjectzones.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml b/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml index deb02663feb5..52a8209f1ef8 100644 --- a/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml +++ b/build/csv/ceph/ceph.rook.io_cephobjectzones.yaml @@ -356,8 +356,6 @@ spec: zoneGroup: type: string required: - - dataPool - - metadataPool - zoneGroup type: object status: