diff --git a/.github/workflows/ui-tests.yaml b/.github/workflows/ui-tests.yaml new file mode 100644 index 000000000..56a776f75 --- /dev/null +++ b/.github/workflows/ui-tests.yaml @@ -0,0 +1,43 @@ +# Jobs defined in this file are responsible for things that do not require container image +# but still relevant to the codebase such as unit tests, linting etc + +name: Pull Request + +on: + pull_request: + types: [ synchronize, opened, reopened, ready_for_review ] + paths: + - 'config/ui-extensions/**' + - 'config/crd/**' + - 'tests/ui/**' + - '.github/workflows/ui-tests.yaml' + branches: + - "main" + - 'release-**' + +permissions: + contents: read + +jobs: + run-ui-tests: + name: Run UI tests + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-go@v4 + with: + go-version-file: 'go.mod' + - name: Run tests + run: | + sudo echo "127.0.0.1 local.kyma.dev" | sudo tee -a /etc/hosts + wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | sudo bash + IMG=europe-docker.pkg.dev/kyma-project/dev/istio-manager:PR-${{ github.event.number }} ./tests/ui/scripts/k3d-ci-kyma-dashboard-integration.sh + - uses: actions/upload-artifact@v3 + if: always() + name: Export Cypress output + with: + name: cypress + path: tests/ui/cypress/ diff --git a/config/ui-extensions/authorizationpolicies/dataSources b/config/ui-extensions/authorizationpolicies/dataSources new file mode 100644 index 000000000..6fd8ac330 --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/dataSources @@ -0,0 +1,5 @@ +podSelector: + resource: + kind: Pod + version: v1 + filter: $matchByLabelSelector($item, $root.spec.selector.matchLabels) \ No newline at end of file diff --git a/config/ui-extensions/authorizationpolicies/details b/config/ui-extensions/authorizationpolicies/details new file mode 100644 index 000000000..0962263df --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/details @@ -0,0 +1,149 @@ +header: + - source: spec.action + name: spec.action + - source: spec.provider + widget: Labels + name: spec.provider +resourceGraph: + colorVariant: 3 + dataSources: + - source: podSelector +body: + - widget: Table + name: spec.rules + source: spec.rules + showHeader: false + visibility: $exists($value) + collapsibleTitle: '"Rule #" & $string($index + 1) & (" " & $join($keys($item), " "))' + collapsible: + - source: $item.from + widget: Table + name: spec.rules.from + disablePadding: true + showHeader: false + visibility: $exists($value) + collapsibleTitle: '"From #" & $string($index + 1) & (" " & $join($keys($item.source), " "))' + collapsible: + - source: source + widget: Panel + name: spec.rules.from.source + children: + - source: principals + name: spec.rules.from.source.principals + widget: JoinedArray + visibility: $exists($value) + - source: notPrincipals + name: spec.rules.from.source.notPrincipals + widget: Labels + visibility: $exists($value) + - source: requestPrincipals + name: spec.rules.from.source.requestPrincipals + widget: Labels + visibility: $exists($value) + - source: notRequestPrincipals + name: spec.rules.from.source.notRequestPrincipals + widget: Labels + visibility: $exists($value) + - source: namespaces + name: spec.rules.from.source.namespaces + widget: Labels + visibility: $exists($value) + - source: notNamespaces + name: spec.rules.from.source.notNamespaces + widget: Labels + visibility: $exists($value) + - source: ipBlocks + name: spec.rules.from.source.ipBlocks + widget: Labels + visibility: $exists($value) + - source: notIpBlocks + name: spec.rules.from.source.notIpBlocks + widget: Labels + visibility: $exists($value) + - source: remoteIpBlocks + name: spec.rules.from.source.remoteIpBlocks + widget: Labels + visibility: $exists($value) + - source: notRemoteIpBlocks + name: spec.rules.from.source.notRemoteIpBlocks + widget: Labels + visibility: $exists($value) + - source: $item.to + widget: Table + name: spec.rules.to + disablePadding: true + showHeader: false + visibility: $exists($value) + collapsibleTitle: '"To #" & $string($index + 1) & (" " & $join($keys($item.operation), " "))' + collapsible: + - source: operation + widget: Panel + name: spec.rules.to.operation + children: + - source: Hosts + name: spec.rules.to.operation.hosts + widget: Labels + visibility: $exists($value) + - source: notHosts + name: spec.rules.to.operation.notHosts + widget: Labels + visibility: $exists($value) + - source: ports + name: spec.rules.to.operation.ports + widget: Labels + visibility: $exists($value) + - source: notPorts + name: spec.rules.to.operation.notPorts + widget: Labels + visibility: $exists($value) + - source: methods + name: spec.rules.to.operation.methods + widget: Labels + visibility: $exists($value) + - source: notMethods + name: spec.rules.to.operation.notMethods + widget: Labels + visibility: $exists($value) + - source: paths + name: spec.rules.to.operation.paths + widget: Labels + visibility: $exists($value) + - source: notPaths + name: spec.rules.to.operation.notPaths + widget: Labels + visibility: $exists($value) + - source: when + widget: Table + name: spec.rules.when + visibility: $exists($value) + children: + - source: key + name: spec.rules.when.key + visibility: $exists($value) + - source: values + name: spec.rules.when.values + widget: JoinedArray + separator: break + visibility: $exists($value) + - source: notValues + name: spec.rules.when.notValues + widget: JoinedArray + separator: break + visibility: $exists($value) + - widget: Panel + name: spec.selector.matchLabels + disablePadding: true + children: + - source: $podSelector() + widget: ResourceList + disableCreate: true + visibility: $exists($root.spec.selector.matchLabels) and $boolean($root.spec.selector.matchLabels) + - source: spec.selector + widget: Panel + name: selector.matchesAllPods + visibility: $not($exists($value)) or $not($boolean($value)) + header: + - source: spec.selector.matchLabels + widget: Labels + name: spec.selector.matchLabels + visibility: $exists($value) and $boolean($value) diff --git a/config/ui-extensions/authorizationpolicies/form b/config/ui-extensions/authorizationpolicies/form new file mode 100644 index 000000000..709a6b2c4 --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/form @@ -0,0 +1,181 @@ +- path: spec.selector.matchLabels + widget: KeyValuePair + defaultExpanded: true +- path: spec.action + placeholder: placeholders.dropdown + simple: true + description: description.action +- path: spec.provider + widget: FormGroup + children: + - path: name +- path: spec.rules + widget: GenericList + simple: true + children: + - path: '[].from' + simple: true + widget: GenericList + children: + - path: '[].source' + simple: true + widget: FormGroup + defaultExpanded: true + children: + - path: principals + simple: true + widget: SimpleList + description: description.rules.from.principals + children: + - path: '[]' + simple: true + - path: notPrincipals + simple: true + widget: SimpleList + description: description.rules.from.notPrincipals + children: + - path: '[]' + simple: true + - path: requestPrincipals + simple: true + widget: SimpleList + description: description.rules.from.requestPrincipals + children: + - path: '[]' + simple: true + - path: notRequestPrincipals + simple: true + widget: SimpleList + description: description.rules.from.notRequestPrincipals + children: + - path: '[]' + simple: true + - path: namespaces + simple: true + widget: SimpleList + description: description.rules.from.namespaces + children: + - path: '[]' + simple: true + - path: notNamespaces + simple: true + widget: SimpleList + description: description.rules.from.notNamespaces + children: + - path: '[]' + simple: true + - path: ipBlocks + simple: true + widget: SimpleList + description: description.rules.from.ipBlocks + children: + - path: '[]' + simple: true + - path: notIpBlocks + simple: true + widget: SimpleList + description: description.rules.from.notIpBlocks + children: + - path: '[]' + simple: true + - path: remoteIpBlocks + simple: true + widget: SimpleList + description: description.rules.from.remoteIpBlocks + children: + - path: '[]' + simple: true + - path: notRemoteIpBlocks + simple: true + widget: SimpleList + description: description.rules.from.notRemoteIpBlocks + children: + - path: '[]' + simple: true + - path: '[].to' + simple: true + widget: GenericList + children: + - path: '[].operation' + simple: true + widget: FormGroup + defaultExpanded: true + children: + - path: hosts + simple: true + widget: SimpleList + description: description.rules.to.hosts + children: + - path: '[]' + simple: true + - path: notHosts + simple: true + widget: SimpleList + description: description.rules.to.notHosts + children: + - path: '[]' + simple: true + - path: ports + simple: true + widget: SimpleList + description: description.rules.to.ports + children: + - path: '[]' + simple: true + - path: notPorts + simple: true + widget: SimpleList + description: description.rules.to.notPorts + children: + - path: '[]' + simple: true + - path: methods + simple: true + widget: SimpleList + description: description.rules.to.methods + children: + - path: '[]' + simple: true + - path: notMethods + simple: true + widget: SimpleList + description: description.rules.to.notMethods + children: + - path: '[]' + simple: true + - path: paths + simple: true + widget: SimpleList + description: description.rules.to.paths + children: + - path: '[]' + simple: true + - path: notPaths + simple: true + widget: SimpleList + description: description.rules.to.notPaths + children: + - path: '[]' + simple: true + - path: '[].when' + simple: true + widget: GenericList + children: + - path: '[].key' + simple: true + widget: Text + description: description.rules.when.key + - path: '[].values' + simple: true + widget: SimpleList + description: description.rules.when.values + children: + - path: '[]' + simple: true + - path: '[].notValues' + simple: true + widget: SimpleList + description: description.rules.when.notValues + children: + - path: '[]' + simple: true diff --git a/config/ui-extensions/authorizationpolicies/general b/config/ui-extensions/authorizationpolicies/general new file mode 100644 index 000000000..61038458a --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/general @@ -0,0 +1,12 @@ +resource: + kind: AuthorizationPolicy + group: security.istio.io + version: v1beta1 +name: Authorization Policies +category: Istio +urlPath: authorizationpolicies +scope: namespace +description: >- + {{[Istio Authorization + Policy](https://istio.io/latest/docs/reference/config/security/authorization-policy/)}} + allows for workload access management in the mesh. \ No newline at end of file diff --git a/config/ui-extensions/authorizationpolicies/kustomization.yaml b/config/ui-extensions/authorizationpolicies/kustomization.yaml new file mode 100644 index 000000000..43c2b5713 --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/kustomization.yaml @@ -0,0 +1,16 @@ +configMapGenerator: +- name: authorizationpolicies-ui.operator.kyma-project.io + namespace: kyma-system + files: + - general + - form + - list + - details + - translations + - dataSources + options: + disableNameSuffixHash: true + labels: + app.kubernetes.io/name: istios.operator.kyma-project.io + busola.io/extension: resource + busola.io/extension-version: "0.5" \ No newline at end of file diff --git a/config/ui-extensions/authorizationpolicies/list b/config/ui-extensions/authorizationpolicies/list new file mode 100644 index 000000000..ca9ae56aa --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/list @@ -0,0 +1,2 @@ +- name: action + source: spec.action \ No newline at end of file diff --git a/config/ui-extensions/authorizationpolicies/translations b/config/ui-extensions/authorizationpolicies/translations new file mode 100644 index 000000000..40782b3d0 --- /dev/null +++ b/config/ui-extensions/authorizationpolicies/translations @@ -0,0 +1,55 @@ +en: + description.action: Optional. The action to take if the request is matched with the rules. Default is ALLOW if not specified. + description.rules.from.principals: Optional. A list of peer identities derived from the peer certificate. The peer identity is in the format of ' /ns/ /sa/ ', for example, 'cluster.local/ns/default/sa/productpage'. If not set, any principal is allowed. + description.rules.from.notPrincipals: Optional. A list of negative match of peer identities. + description.rules.from.requestPrincipals: Optional. A list of request identities derived from the JWT. The request identity is in the format of '/', for example, 'example.com/sub-1'. If not set, any request principal is allowed. + description.rules.from.notRequestPrincipals: Optional. A list of negative match of request identities. + description.rules.from.namespaces: Optional. A list of namespaces derived from the peer certificate. If not set, any namespace is allowed. + description.rules.from.notNamespaces: Optional. A list of negative match of namespaces. + description.rules.from.ipBlocks: Optional. A list of IP blocks, populated from the source address of the IP packet. Single IP (e.g. '1.2.3.4') and CIDR (e.g. '1.2.3.0/24') are supported. If not set, any IP is allowed. + description.rules.from.notIpBlocks: Optional. A list of negative match of IP blocks. + description.rules.from.remoteIpBlocks: Optional. A list of IP blocks, populated from X-Forwarded-For header or proxy protocol. To make use of this field, you must configure the numTrustedProxies field of the gatewayTopology under the meshConfig when you install Istio or using an annotation on the ingress gateway. If not set, any IP is allowed. + description.rules.from.notRemoteIpBlocks: Optional. A list of negative match of remote IP blocks. + description.rules.to.hosts: Optional. A list of hosts as specified in the HTTP request. The match is case-insensitive. If not set, any host is allowed. Must be used only with HTTP. + description.rules.to.notHosts: Optional. A list of negative match of hosts as specified in the HTTP request. The match is case-insensitive. + description.rules.to.ports: Optional. A list of ports as specified in the connection. If not set, any port is allowed. + description.rules.to.notPorts: Optional. A list of negative match of ports as specified in the connection. + description.rules.to.methods: Optional. A list of methods as specified in the HTTP request. If not set, any method is allowed. Must be used only with HTTP. + description.rules.to.notMethods: Optional. A list of negative match of methods as specified in the HTTP request. + description.rules.to.paths: Optional. A list of paths as specified in the HTTP request. If not set, any path is allowed. Must be used only with HTTP. + description.rules.to.notPaths: Optional. A list of negative match of paths. + description.rules.when.key: The name of an Istio attribute. + description.rules.when.values: Optional. A list of allowed values for the attribute. At least one of values or notValues must be set. + description.rules.when.notValues: Optional. A list of negative match of values for the attribute. At least one of values or notValues must be set. + placeholders.dropdown: Type or choose an option. + spec.action: Action + spec.provider: Provider + spec.rules: Rules + spec.rules.from: From + spec.rules.from.source: Source + spec.rules.from.source.principals: Principals + spec.rules.from.source.notPrincipals: NotPrincipals + spec.rules.from.source.requestPrincipals: RequestPrincipals + spec.rules.from.source.notRequestPrincipals: NotRequestPrincipals + spec.rules.from.source.namespaces: Namespaces + spec.rules.from.source.notNamespaces: NotNamespaces + spec.rules.from.source.ipBlocks: IpBlocks + spec.rules.from.source.notIpBlocks: NotIpBlocks + spec.rules.from.source.remoteIpBlocks: RemoteIpBlocks + spec.rules.from.source.notRemoteIpBlocks: NotRemoteIpBlocks + spec.rules.to: To + spec.rules.to.operation: Operation + spec.rules.to.operation.hosts: Hosts + spec.rules.to.operation.notHosts: NotHosts + spec.rules.to.operation.ports: Ports + spec.rules.to.operation.notPorts: NotPorts + spec.rules.to.operation.methods: Methods + spec.rules.to.operation.notMethods: NotMethods + spec.rules.to.operation.paths: Paths + spec.rules.to.operation.notPaths: NotPaths + spec.rules.when: When + spec.rules.when.key: Key + spec.rules.when.values: Values + spec.rules.when.notValues: NotValues + spec.selector.matchLabels: Selector + selector.matchesAllPods: Matches all Pods in the Namespace diff --git a/config/ui-extensions/destinationrules/details b/config/ui-extensions/destinationrules/details new file mode 100644 index 000000000..3b0972909 --- /dev/null +++ b/config/ui-extensions/destinationrules/details @@ -0,0 +1,969 @@ +header: [] +body: + - name: References + widget: Panel + children: + - source: spec.host + name: Host + - source: spec.exportTo + widget: Labels + name: Export To + visibility: $exists($value) + - source: spec.workloadSelector.matchLabels + widget: Labels + name: Workload Selector Match Labels + visibility: $exists($value) + - source: spec.trafficPolicy + name: Traffic Policy + disablePadding: true + visibility: $exists($value) + widget: Panel + children: + - source: loadBalancer + name: Load Balancer + visibility: $exists($value) + widget: Panel + children: + - source: simple + name: Simple + visibility: $exists($value) + widget: Badge + - source: warmupDurationSecs + name: Warmup Duration Secs + visibility: $exists($value) + - source: consistentHash + name: Consistent Hash + visibility: $exists($value) + widget: Panel + children: + - source: httpHeaderName + name: HTTP Header Name + visibility: $exists($value) + - source: useSourceIp + name: Use Source IP + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: httpQueryParameterName + name: HTTP Query Parameter Name + visibility: $exists($value) + - source: minimumRingSize + name: Minimum Ring Size + visibility: $exists($value) + - source: httpCookie + name: HTTP Cookie + visibility: $exists($value) + widget: Panel + children: + - source: name + name: Name + - source: path + name: Path + - source: ttl + name: TTL + - source: localityLbSetting + name: Locality LB Settings + visibility: $exists($value) + widget: Panel + children: + - name: Enabled + source: enabled + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - widget: Table + disablePadding: true + name: Distribute + visibility: $exists($value) + source: distribute + children: + - source: $item.from + name: From + - source: $item.to + name: To + widget: Labels + - widget: Table + disablePadding: true + name: Failover + visibility: $exists($value) + source: failover + children: + - source: $item.from + name: From + - source: $item.to + name: To + - name: Failover Priority + source: failoverPriority + widget: JoinedArray + visibility: $exists($value) + - source: connectionPool + name: Connection Pool + visibility: $exists($value) + widget: Panel + children: + - source: tcp + name: TCP + visibility: $exists($value) + widget: Panel + children: + - source: maxConnections + name: Max Connections + visibility: $exists($value) + - source: connectTimeout + name: Connect Timeout + visibility: $exists($value) + - source: tcpKeepalive + name: TCP Keep Alive + visibility: $exists($value) + widget: Panel + children: + - source: probes + name: Probes + - source: time + name: Time + - source: interval + name: Interval + - source: http + name: HTTP + visibility: $exists($value) + widget: Panel + children: + - source: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + visibility: $exists($value) + - source: http2MaxRequests + name: HTTP2 Max Requests + visibility: $exists($value) + - source: maxRequestsPerConnection + name: Max Requests Per Connection + visibility: $exists($value) + - source: maxRetries + name: Max Retries + visibility: $exists($value) + - source: idleTimeout + name: Idle Timeout + visibility: $exists($value) + - source: h2UpgradePolicy + name: H2 Upgrade Policy + visibility: $exists($value) + widget: Badge + - source: useClientProtocol + name: Use Client Protocol + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: outlierDetection + name: outlierDetection + visibility: $exists($value) + widget: Panel + children: + - source: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + visibility: $exists($value) + - source: consecutiveGatewayErrors + name: Consecutive Gateway Errors + visibility: $exists($value) + type: number + - source: consecutive5xxErrors + name: Consecutive 5xx Errors + visibility: $exists($value) + - source: interval + name: Interval + visibility: $exists($value) + - source: baseEjectionTime + name: Base Ejection Time + visibility: $exists($value) + - source: maxEjectionPercent + name: Max Ejection Percent + visibility: $exists($value) + - source: minHealthPercent + name: Min Health Percent + visibility: $exists($value) + - source: tls + name: TLS + visibility: $exists($value) + widget: Panel + children: + - source: mode + name: Mode + visibility: $exists($value) + widget: Badge + - source: clientCertificate + name: Client Certificate + visibility: $exists($value) + - source: privateKey + name: Private Key + visibility: $exists($value) + type: number + - source: caCertificates + name: CA Certificates + visibility: $exists($value) + - source: credentialName + name: Credential Name + visibility: $exists($value) + - source: subjectAltNames + name: Subject Alt Names + visibility: $exists($value) + widget: Labels + - source: sni + name: SNI + visibility: $exists($value) + - source: insecureSkipVerify + name: Insecure Skip Verify + visibility: $exists($value) + widget: Badge + - source: portLevelSettings + name: portLevelSettings + widget: Table + disablePadding: true + children: + - source: $item.port.number + name: port + visibility: $exists($value) + collapsible: + - source: $item.loadBalancer + name: Load Balancer + visibility: $exists($value) + widget: Panel + children: + - source: simple + name: Simple + visibility: $exists($value) + widget: Badge + - source: warmupDurationSecs + name: Warmup Duration Secs + visibility: $exists($value) + - source: consistentHash + name: Consistent Hash + visibility: $exists($value) + widget: Panel + children: + - source: httpHeaderName + name: HTTP Header Name + visibility: $exists($value) + - source: useSourceIp + name: Use Source IP + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: httpQueryParameterName + name: HTTP Query Parameter Name + visibility: $exists($value) + - source: minimumRingSize + name: Minimum Ring Size + visibility: $exists($value) + - source: httpCookie + name: HTTP Cookie + visibility: $exists($value) + widget: Panel + children: + - source: name + name: Name + - source: path + name: Path + - source: ttl + name: TTL + - source: localityLbSetting + name: Locality LB Settings + visibility: $exists($value) + widget: Panel + children: + - name: Enabled + source: enabled + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - widget: Table + disablePadding: true + name: Distribute + visibility: $exists($value) + source: distribute + children: + - source: $item.from + name: From + - source: $item.to + name: To + widget: Labels + - widget: Table + disablePadding: true + name: Failover + visibility: $exists($value) + source: failover + children: + - source: $item.from + name: From + - source: $item.to + name: To + - name: Failover Priority + source: failoverPriority + widget: JoinedArray + visibility: $exists($value) + - source: $item.connectionPool + name: Connection Pool + visibility: $exists($value) + widget: Panel + children: + - source: tcp + name: TCP + visibility: $exists($value) + widget: Panel + children: + - source: maxConnections + name: Max Connections + visibility: $exists($value) + - source: connectTimeout + name: Connect Timeout + visibility: $exists($value) + - source: tcpKeepalive + name: TCP Keep Alive + visibility: $exists($value) + widget: Panel + children: + - source: probes + name: Probes + - source: time + name: Time + - source: interval + name: Interval + - source: http + name: HTTP + visibility: $exists($value) + widget: Panel + children: + - source: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + visibility: $exists($value) + - source: http2MaxRequests + name: HTTP2 Max Requests + visibility: $exists($value) + - source: maxRequestsPerConnection + name: Max Requests Per Connection + visibility: $exists($value) + - source: maxRetries + name: Max Retries + visibility: $exists($value) + - source: idleTimeout + name: Idle Timeout + visibility: $exists($value) + - source: h2UpgradePolicy + name: H2 Upgrade Policy + visibility: $exists($value) + widget: Badge + - source: useClientProtocol + name: Use Client Protocol + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: $item.outlierDetection + name: outlierDetection + visibility: $exists($value) + widget: Panel + children: + - source: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + visibility: $exists($value) + - source: consecutiveGatewayErrors + name: Consecutive Gateway Errors + visibility: $exists($value) + type: number + - source: consecutive5xxErrors + name: Consecutive 5xx Errors + visibility: $exists($value) + - source: interval + name: Interval + visibility: $exists($value) + - source: baseEjectionTime + name: Base Ejection Time + visibility: $exists($value) + - source: maxEjectionPercent + name: Max Ejection Percent + visibility: $exists($value) + - source: minHealthPercent + name: Min Health Percent + visibility: $exists($value) + - source: $item.tls + name: TLS + visibility: $exists($value) + widget: Panel + children: + - source: mode + name: Mode + visibility: $exists($value) + widget: Badge + - source: clientCertificate + name: Client Certificate + visibility: $exists($value) + - source: privateKey + name: Private Key + visibility: $exists($value) + type: number + - source: caCertificates + name: CA Certificates + visibility: $exists($value) + - source: credentialName + name: Credential Name + visibility: $exists($value) + - source: subjectAltNames + name: Subject Alt Names + visibility: $exists($value) + widget: Labels + - source: sni + name: SNI + visibility: $exists($value) + - source: insecureSkipVerify + name: Insecure Skip Verify + visibility: $exists($value) + widget: Badge + - source: $item.tunnel + name: Tunnel + visibility: $exists($value) + widget: Panel + children: + - source: protocol + name: Protocol + visibility: $exists($value) + widget: Badge + - source: targetHost + name: Target Host + visibility: $exists($value) + - source: targetPort + name: Target Port + visibility: $exists($value) + - source: tunnel + name: Tunnel + visibility: $exists($value) + widget: Panel + children: + - source: protocol + name: Protocol + visibility: $exists($value) + widget: Badge + - source: targetHost + name: Target Host + visibility: $exists($value) + - source: targetPort + name: Target Port + visibility: $exists($value) + - source: spec.subsets + name: Subsets + widget: Table + disablePadding: true + visibility: $exists($value) + children: + - source: $item.name + name: Name + - source: $item.labels + name: Labels + widget: Labels + collapsible: + - source: $item.trafficPolicy + name: Traffic Policy + disablePadding: true + visibility: $exists($value) + widget: Panel + children: + - source: loadBalancer + name: Load Balancer + visibility: $exists($value) + widget: Panel + children: + - source: simple + name: Simple + visibility: $exists($value) + widget: Badge + - source: warmupDurationSecs + name: Warmup Duration Secs + visibility: $exists($value) + - source: consistentHash + name: Consistent Hash + visibility: $exists($value) + widget: Panel + children: + - source: httpHeaderName + name: HTTP Header Name + visibility: $exists($value) + - source: useSourceIp + name: Use Source IP + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: httpQueryParameterName + name: HTTP Query Parameter Name + visibility: $exists($value) + - source: minimumRingSize + name: Minimum Ring Size + visibility: $exists($value) + - source: httpCookie + name: HTTP Cookie + visibility: $exists($value) + widget: Panel + children: + - source: name + name: Name + - source: path + name: Path + - source: ttl + name: TTL + - source: localityLbSetting + name: Locality LB Settings + visibility: $exists($value) + widget: Panel + children: + - name: Enabled + source: enabled + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - widget: Table + disablePadding: true + name: Distribute + visibility: $exists($value) + source: distribute + children: + - source: $item.from + name: From + - source: $item.to + name: To + widget: Labels + - widget: Table + disablePadding: true + name: Failover + visibility: $exists($value) + source: failover + children: + - source: $item.from + name: From + - source: $item.to + name: To + - name: Failover Priority + source: failoverPriority + widget: JoinedArray + visibility: $exists($value) + - source: connectionPool + name: Connection Pool + visibility: $exists($value) + widget: Panel + children: + - source: tcp + name: TCP + visibility: $exists($value) + widget: Panel + children: + - source: maxConnections + name: Max Connections + visibility: $exists($value) + - source: connectTimeout + name: Connect Timeout + visibility: $exists($value) + - source: tcpKeepalive + name: TCP Keep Alive + visibility: $exists($value) + widget: Panel + children: + - source: probes + name: Probes + - source: time + name: Time + - source: interval + name: Interval + - source: http + name: HTTP + visibility: $exists($value) + widget: Panel + children: + - source: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + visibility: $exists($value) + - source: http2MaxRequests + name: HTTP2 Max Requests + visibility: $exists($value) + - source: maxRequestsPerConnection + name: Max Requests Per Connection + visibility: $exists($value) + - source: maxRetries + name: Max Retries + visibility: $exists($value) + - source: idleTimeout + name: Idle Timeout + visibility: $exists($value) + - source: h2UpgradePolicy + name: H2 Upgrade Policy + visibility: $exists($value) + widget: Badge + - source: useClientProtocol + name: Use Client Protocol + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: outlierDetection + name: outlierDetection + visibility: $exists($value) + widget: Panel + children: + - source: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + visibility: $exists($value) + - source: consecutiveGatewayErrors + name: Consecutive Gateway Errors + visibility: $exists($value) + type: number + - source: consecutive5xxErrors + name: Consecutive 5xx Errors + visibility: $exists($value) + - source: interval + name: Interval + visibility: $exists($value) + - source: baseEjectionTime + name: Base Ejection Time + visibility: $exists($value) + - source: maxEjectionPercent + name: Max Ejection Percent + visibility: $exists($value) + - source: minHealthPercent + name: Min Health Percent + visibility: $exists($value) + - source: tls + name: TLS + visibility: $exists($value) + widget: Panel + children: + - source: mode + name: Mode + visibility: $exists($value) + widget: Badge + - source: clientCertificate + name: Client Certificate + visibility: $exists($value) + - source: privateKey + name: Private Key + visibility: $exists($value) + type: number + - source: caCertificates + name: CA Certificates + visibility: $exists($value) + - source: credentialName + name: Credential Name + visibility: $exists($value) + - source: subjectAltNames + name: Subject Alt Names + visibility: $exists($value) + widget: Labels + - source: sni + name: SNI + visibility: $exists($value) + - source: insecureSkipVerify + name: Insecure Skip Verify + visibility: $exists($value) + widget: Badge + - source: portLevelSettings + name: portLevelSettings + widget: Table + disablePadding: true + children: + - source: $item.port.number + name: port + visibility: $exists($value) + collapsible: + - source: $item.loadBalancer + name: Load Balancer + visibility: $exists($value) + widget: Panel + children: + - source: simple + name: Simple + visibility: $exists($value) + widget: Badge + - source: warmupDurationSecs + name: Warmup Duration Secs + visibility: $exists($value) + - source: consistentHash + name: Consistent Hash + visibility: $exists($value) + widget: Panel + children: + - source: httpHeaderName + name: HTTP Header Name + visibility: $exists($value) + - source: useSourceIp + name: Use Source IP + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: httpQueryParameterName + name: HTTP Query Parameter Name + visibility: $exists($value) + - source: minimumRingSize + name: Minimum Ring Size + visibility: $exists($value) + - source: httpCookie + name: HTTP Cookie + visibility: $exists($value) + widget: Panel + children: + - source: name + name: Name + - source: path + name: Path + - source: ttl + name: TTL + - source: localityLbSetting + name: Locality LB Settings + visibility: $exists($value) + widget: Panel + children: + - name: Enabled + source: enabled + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - widget: Table + disablePadding: true + name: Distribute + visibility: $exists($value) + source: distribute + children: + - source: $item.from + name: From + - source: $item.to + name: To + widget: Labels + - widget: Table + disablePadding: true + name: Failover + visibility: $exists($value) + source: failover + children: + - source: $item.from + name: From + - source: $item.to + name: To + - name: Failover Priority + source: failoverPriority + widget: JoinedArray + visibility: $exists($value) + - source: $item.connectionPool + name: Connection Pool + visibility: $exists($value) + widget: Panel + children: + - source: tcp + name: TCP + visibility: $exists($value) + widget: Panel + children: + - source: maxConnections + name: Max Connections + visibility: $exists($value) + - source: connectTimeout + name: Connect Timeout + visibility: $exists($value) + - source: tcpKeepalive + name: TCP Keep Alive + visibility: $exists($value) + widget: Panel + children: + - source: probes + name: Probes + - source: time + name: Time + - source: interval + name: Interval + - source: http + name: HTTP + visibility: $exists($value) + widget: Panel + children: + - source: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + visibility: $exists($value) + - source: http2MaxRequests + name: HTTP2 Max Requests + visibility: $exists($value) + - source: maxRequestsPerConnection + name: Max Requests Per Connection + visibility: $exists($value) + - source: maxRetries + name: Max Retries + visibility: $exists($value) + - source: idleTimeout + name: Idle Timeout + visibility: $exists($value) + - source: h2UpgradePolicy + name: H2 Upgrade Policy + visibility: $exists($value) + widget: Badge + - source: useClientProtocol + name: Use Client Protocol + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: $item.outlierDetection + name: outlierDetection + visibility: $exists($value) + widget: Panel + children: + - source: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + visibility: $exists($value) + widget: Badge + highlights: + positive: + - 'true' + negative: + - 'false' + - source: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + visibility: $exists($value) + - source: consecutiveGatewayErrors + name: Consecutive Gateway Errors + visibility: $exists($value) + type: number + - source: consecutive5xxErrors + name: Consecutive 5xx Errors + visibility: $exists($value) + - source: interval + name: Interval + visibility: $exists($value) + - source: baseEjectionTime + name: Base Ejection Time + visibility: $exists($value) + - source: maxEjectionPercent + name: Max Ejection Percent + visibility: $exists($value) + - source: minHealthPercent + name: Min Health Percent + visibility: $exists($value) + - source: $item.tls + name: TLS + visibility: $exists($value) + widget: Panel + children: + - source: mode + name: Mode + visibility: $exists($value) + widget: Badge + - source: clientCertificate + name: Client Certificate + visibility: $exists($value) + - source: privateKey + name: Private Key + visibility: $exists($value) + type: number + - source: caCertificates + name: CA Certificates + visibility: $exists($value) + - source: credentialName + name: Credential Name + visibility: $exists($value) + - source: subjectAltNames + name: Subject Alt Names + visibility: $exists($value) + widget: Labels + - source: sni + name: SNI + visibility: $exists($value) + - source: insecureSkipVerify + name: Insecure Skip Verify + visibility: $exists($value) + widget: Badge + - source: $item.tunnel + name: Tunnel + visibility: $exists($value) + widget: Panel + children: + - source: protocol + name: Protocol + visibility: $exists($value) + widget: Badge + - source: targetHost + name: Target Host + visibility: $exists($value) + - source: targetPort + name: Target Port + visibility: $exists($value) + - source: tunnel + name: Tunnel + visibility: $exists($value) + widget: Panel + children: + - source: protocol + name: Protocol + visibility: $exists($value) + widget: Badge + - source: targetHost + name: Target Host + visibility: $exists($value) + - source: targetPort + name: Target Port + visibility: $exists($value) diff --git a/config/ui-extensions/destinationrules/form b/config/ui-extensions/destinationrules/form new file mode 100644 index 000000000..bd5e50276 --- /dev/null +++ b/config/ui-extensions/destinationrules/form @@ -0,0 +1,781 @@ +- simple: true + path: spec.host + name: Host + required: true +- widget: FormGroup + path: spec.trafficPolicy + name: Traffic Policy + children: + - widget: FormGroup + path: loadBalancer + name: Load Balancer + children: + - var: mainloadBalancerSelector + name: ChooseLoadBalancerSelector + type: string + enum: + - simple + - consistentHash + - path: simple + name: Simple + required: true + visibility: $mainloadBalancerSelector = 'simple' + - widget: FormGroup + path: consistentHash + name: Consistent Hash + visibility: $mainloadBalancerSelector = 'consistentHash' + children: + - var: mainconsistentHashSelector + name: ChooseConsistentHashSelector + type: string + enum: + - httpHeaderName + - httpCookie + - useSourceIp + - httpQueryParameterName + - path: httpHeaderName + name: HTTP Header Name + required: true + visibility: $mainconsistentHashSelector = 'httpHeaderName' + - path: httpCookie + name: HTTP Cookie + widget: FormGroup + visibility: $mainconsistentHashSelector = 'httpCookie' + children: + - path: name + name: Name + required: true + - path: path + name: Path + - path: ttl + name: TTL + required: true + - path: useSourceIp + name: Use Source IP + required: true + visibility: $mainconsistentHashSelector = 'useSourceIp' + - path: httpQueryParameterName + name: HTTP Query Parameter Name + required: true + visibility: $mainconsistentHashSelector= 'httpQueryParameterName' + - path: minimumRingSize + name: Minimum Ring Size + - path: localityLbSetting + name: Locality LB Settings + widget: FormGroup + children: + - path: enabled + name: Enabled + type: boolean + - var: mainLbSelector + name: ChooseLbSelector + type: string + enum: + - distribute + - failover + - path: distribute + name: Distribute + widget: GenericList + visibility: $mainLbSelector = 'distribute' + - path: distribute[].from + name: From + - path: distribute[].to + name: To + widget: KeyValuePair + value: + type: number + - path: failover + name: Failover + widget: GenericList + visibility: $mainLbSelector = 'failover' + - path: failover[].from + name: From + - path: failover[].to + name: To + - path: failoverPriority + name: Failover Priority + visibility: $mainLbSelector = 'failover' + widget: SimpleList + children: + - path: '[]' + - path: warmupDurationSecs + name: Warmup Duration Secs + - path: connectionPool + name: Connection Pool + widget: FormGroup + children: + - path: tcp + name: TCP + widget: FormGroup + children: + - path: maxConnections + name: Max Connections + - path: connectTimeout + name: Connect Timeout + - path: tcpKeepalive + name: TCP Keep Alive + widget: FormGroup + children: + - path: probes + name: Probes + - path: time + name: Time + - path: interval + name: Interval + - path: http + name: HTTP + widget: FormGroup + children: + - path: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + - path: http2MaxRequests + name: HTTP2 Max Requests + - path: maxRequestsPerConnection + name: Max Requests Per Connection + - path: maxRetries + name: Max Retries + - path: idleTimeout + name: Idle Timeout + - path: h2UpgradePolicy + name: H2 Upgrade Policy + - path: useClientProtocol + name: Use Client Protocol + - path: outlierDetection + widget: FormGroup + children: + - path: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + - path: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + type: number + - path: consecutiveGatewayErrors + name: Consecutive Gateway Errors + type: number + - path: consecutive5xxErrors + name: Consecutive 5xx Errors + type: number + - path: interval + name: Interval + - path: baseEjectionTime + name: Base Ejection Time + - path: maxEjectionPercent + name: Max Ejection Percent + - path: minHealthPercent + name: Min Health Percent + - path: tls + name: TLS + widget: FormGroup + children: + - path: mode + name: Mode + - path: clientCertificate + name: Client Certificate + - path: privateKey + name: Private Key + - path: caCertificates + name: CA Certificates + - path: credentialName + name: Credential Name + - path: subjectAltNames + name: Subject Alt Names + widget: SimpleList + children: + - path: '[]' + - path: sni + name: SNI + - path: insecureSkipVerify + name: Insecure Skip Verify + - path: portLevelSettings + name: Port Level Settings + widget: GenericList + children: + - path: '[].port.number' + name: Port Number + - widget: FormGroup + path: '[].loadBalancer' + name: Load Balancer + children: + - var: portLevelloadBalancerSelector + name: ChooseLoadBalancerSelector + type: string + enum: + - simple + - consistentHash + - path: simple + name: Simple + required: true + visibility: $portLevelloadBalancerSelector = 'simple' + - widget: FormGroup + path: consistentHash + name: Consistent Hash + visibility: $portLevelloadBalancerSelector = 'consistentHash' + children: + - var: portLevelconsistentHashSelector + name: ChooseConsistentHashSelector + type: string + enum: + - httpHeaderName + - httpCookie + - useSourceIp + - httpQueryParameterName + - path: httpHeaderName + name: HTTP Header Name + required: true + visibility: $portLevelconsistentHashSelector = 'httpHeaderName' + - path: httpCookie + name: HTTP Cookie + widget: FormGroup + visibility: $portLevelconsistentHashSelector = 'httpCookie' + children: + - path: name + name: Name + required: true + - path: path + name: Path + - path: ttl + name: TTL + required: true + - path: useSourceIp + name: Use Source IP + required: true + visibility: $portLevelconsistentHashSelector = 'useSourceIp' + - path: httpQueryParameterName + name: HTTP Query Parameter Name + required: true + visibility: $portLevelconsistentHashSelector= 'httpQueryParameterName' + - path: minimumRingSize + name: Minimum Ring Size + - path: localityLbSetting + name: Locality LB Settings + widget: FormGroup + children: + - path: enabled + name: Enabled + type: boolean + - var: portLevelLbSelector + name: ChooseLbSelector + type: string + enum: + - distribute + - failover + - path: distribute + name: Distribute + widget: GenericList + visibility: $portLevelLbSelector = 'distribute' + - path: distribute[].from + name: From + - path: distribute[].to + name: To + widget: KeyValuePair + value: + type: number + - path: failover + name: Failover + widget: GenericList + visibility: $portLevelLbSelector = 'failover' + - path: failover[].from + name: From + - path: failover[].to + name: To + - path: failoverPriority + name: Failover Priority + visibility: $portLevelLbSelector = 'failover' + widget: SimpleList + children: + - path: '[]' + - path: warmupDurationSecs + name: Warmup Duration Secs + - path: '[].connectionPool' + name: Connection Pool + widget: FormGroup + children: + - path: tcp + name: TCP + widget: FormGroup + children: + - path: maxConnections + name: Max Connections + - path: connectTimeout + name: Connect Timeout + - path: tcpKeepalive + name: TCP Keep Alive + widget: FormGroup + children: + - path: probes + name: Probes + - path: time + name: Time + - path: interval + name: Interval + - path: http + name: HTTP + widget: FormGroup + children: + - path: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + - path: http2MaxRequests + name: HTTP2 Max Requests + - path: maxRequestsPerConnection + name: Max Requests Per Connection + - path: maxRetries + name: Max Retries + - path: idleTimeout + name: Idle Timeout + - path: h2UpgradePolicy + name: H2 Upgrade Policy + - path: useClientProtocol + name: Use Client Protocol + - path: '[].outlierDetection' + widget: FormGroup + children: + - path: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + - path: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + type: number + - path: consecutiveGatewayErrors + name: Consecutive Gateway Errors + type: number + - path: consecutive5xxErrors + name: Consecutive 5xx Errors + type: number + - path: interval + name: Interval + - path: baseEjectionTime + name: Base Ejection Time + - path: maxEjectionPercent + name: Max Ejection Percent + - path: minHealthPercent + name: Min Health Percent + - path: '[].tls' + name: TLS + widget: FormGroup + children: + - path: mode + name: Mode + - path: clientCertificate + name: Client Certificate + - path: privateKey + name: Private Key + - path: caCertificates + name: CA Certificates + - path: credentialName + name: Credential Name + - path: subjectAltNames + name: Subject Alt Names + widget: SimpleList + children: + - path: '[]' + - path: sni + name: SNI + - path: insecureSkipVerify + name: Insecure Skip Verify + - path: tunnel + name: Tunnel + widget: FormGroup + children: + - path: protocol + name: Protocol + - path: targetHost + name: Target Host + - path: targetPort + name: Target Port +- path: spec.subsets + name: Subsets + widget: GenericList + children: + - path: '[].name' + name: Name + - path: '[].labels' + name: Labels + widget: KeyValuePair + - path: '[].trafficPolicy' + name: Traffic Policy + children: + - widget: FormGroup + path: loadBalancer + name: Load Balancer + children: + - var: subsetsloadBalancerSelector + name: ChooseLoadBalancerSelector + type: string + enum: + - simple + - consistentHash + - path: simple + name: Simple + required: true + visibility: $subsetsloadBalancerSelector = 'simple' + - widget: FormGroup + path: consistentHash + name: Consistent Hash + visibility: $subsetsloadBalancerSelector = 'consistentHash' + children: + - var: subsetsconsistentHashSelector + name: ChooseConsistentHashSelector + type: string + enum: + - httpHeaderName + - httpCookie + - useSourceIp + - httpQueryParameterName + - path: httpHeaderName + name: HTTP Header Name + required: true + visibility: $subsetsconsistentHashSelector = 'httpHeaderName' + - path: httpCookie + name: HTTP Cookie + widget: FormGroup + visibility: $subsetsconsistentHashSelector = 'httpCookie' + children: + - path: name + name: Name + required: true + - path: path + name: Path + - path: ttl + name: TTL + required: true + - path: useSourceIp + name: Use Source IP + required: true + visibility: $subsetsconsistentHashSelector = 'useSourceIp' + - path: httpQueryParameterName + name: HTTP Query Parameter Name + required: true + visibility: $subsetsconsistentHashSelector= 'httpQueryParameterName' + - path: minimumRingSize + name: Minimum Ring Size + - path: localityLbSetting + name: Locality LB Settings + widget: FormGroup + children: + - path: enabled + name: Enabled + type: boolean + - var: subsetsLbSelector + name: ChooseLbSelector + type: string + enum: + - distribute + - failover + - path: distribute + name: Distribute + widget: GenericList + visibility: $subsetsLbSelector = 'distribute' + - path: distribute[].from + name: From + - path: distribute[].to + name: To + widget: KeyValuePair + value: + type: number + - path: failover + name: Failover + widget: GenericList + visibility: $subsetsLbSelector = 'failover' + - path: failover[].from + name: From + - path: failover[].to + name: To + - path: failoverPriority + name: Failover Priority + visibility: $subsetsLbSelector = 'failover' + widget: SimpleList + children: + - path: '[]' + - path: warmupDurationSecs + name: Warmup Duration Secs + - path: connectionPool + name: Connection Pool + widget: FormGroup + children: + - path: tcp + name: TCP + widget: FormGroup + children: + - path: maxConnections + name: Max Connections + - path: connectTimeout + name: Connect Timeout + - path: tcpKeepalive + name: TCP Keep Alive + widget: FormGroup + children: + - path: probes + name: Probes + - path: time + name: Time + - path: interval + name: Interval + - path: http + name: HTTP + widget: FormGroup + children: + - path: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + - path: http2MaxRequests + name: HTTP2 Max Requests + - path: maxRequestsPerConnection + name: Max Requests Per Connection + - path: maxRetries + name: Max Retries + - path: idleTimeout + name: Idle Timeout + - path: h2UpgradePolicy + name: H2 Upgrade Policy + - path: useClientProtocol + name: Use Client Protocol + - path: outlierDetection + widget: FormGroup + children: + - path: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + - path: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + type: number + - path: consecutiveGatewayErrors + name: Consecutive Gateway Errors + type: number + - path: consecutive5xxErrors + name: Consecutive 5xx Errors + type: number + - path: interval + name: Interval + - path: baseEjectionTime + name: Base Ejection Time + - path: maxEjectionPercent + name: Max Ejection Percent + - path: minHealthPercent + name: Min Health Percent + - path: tls + name: TLS + widget: FormGroup + children: + - path: mode + name: Mode + - path: clientCertificate + name: Client Certificate + - path: privateKey + name: Private Key + - path: caCertificates + name: CA Certificates + - path: credentialName + name: Credential Name + - path: subjectAltNames + name: Subject Alt Names + widget: SimpleList + children: + - path: '[]' + - path: sni + name: SNI + - path: insecureSkipVerify + name: Insecure Skip Verify + - path: portLevelSettings + name: Port Level Settings + widget: GenericList + children: + - path: '[].port.number' + name: Port Number + - widget: FormGroup + path: '[].loadBalancer' + name: Load Balancer + children: + - var: subsetPortLevelloadBalancerSelector + name: ChooseLoadBalancerSelector + type: string + enum: + - simple + - consistentHash + - path: simple + name: Simple + required: true + visibility: $subsetPortLevelloadBalancerSelector = 'simple' + - widget: FormGroup + path: consistentHash + name: Consistent Hash + visibility: $subsetPortLevelloadBalancerSelector = 'consistentHash' + children: + - var: subsetPortLevelconsistentHashSelector + name: ChooseConsistentHashSelector + type: string + enum: + - httpHeaderName + - httpCookie + - useSourceIp + - httpQueryParameterName + - path: httpHeaderName + name: HTTP Header Name + required: true + visibility: >- + $subsetPortLevelconsistentHashSelector = + 'httpHeaderName' + - path: httpCookie + name: HTTP Cookie + widget: FormGroup + visibility: $subsetPortLevelconsistentHashSelector = 'httpCookie' + children: + - path: name + name: Name + required: true + - path: path + name: Path + - path: ttl + name: TTL + required: true + - path: useSourceIp + name: Use Source IP + required: true + visibility: $subsetPortLevelconsistentHashSelector = 'useSourceIp' + - path: httpQueryParameterName + name: HTTP Query Parameter Name + required: true + visibility: >- + $subsetPortLevelconsistentHashSelector= + 'httpQueryParameterName' + - path: minimumRingSize + name: Minimum Ring Size + - path: localityLbSetting + name: Locality LB Settings + widget: FormGroup + children: + - path: enabled + name: Enabled + type: boolean + - var: subsetPortLevelLbSelector + name: ChooseLbSelector + type: string + enum: + - distribute + - failover + - path: distribute + name: Distribute + widget: GenericList + visibility: $subsetPortLevelLbSelector = 'distribute' + - path: distribute[].from + name: From + - path: distribute[].to + name: To + widget: KeyValuePair + value: + type: number + - path: failover + name: Failover + widget: GenericList + visibility: $subsetPortLevelLbSelector = 'failover' + - path: failover[].from + name: From + - path: failover[].to + name: To + - path: failoverPriority + name: Failover Priority + visibility: $subsetPortLevelLbSelector = 'failover' + widget: SimpleList + children: + - path: '[]' + - path: warmupDurationSecs + name: Warmup Duration Secs + - path: '[].connectionPool' + name: Connection Pool + widget: FormGroup + children: + - path: tcp + name: TCP + widget: FormGroup + children: + - path: maxConnections + name: Max Connections + - path: connectTimeout + name: Connect Timeout + - path: tcpKeepalive + name: TCP Keep Alive + widget: FormGroup + children: + - path: probes + name: Probes + - path: time + name: Time + - path: interval + name: Interval + - path: http + name: HTTP + widget: FormGroup + children: + - path: http1MaxPendingRequests + name: HTTP1 Max Pending Requests + - path: http2MaxRequests + name: HTTP2 Max Requests + - path: maxRequestsPerConnection + name: Max Requests Per Connection + - path: maxRetries + name: Max Retries + - path: idleTimeout + name: Idle Timeout + - path: h2UpgradePolicy + name: H2 Upgrade Policy + - path: useClientProtocol + name: Use Client Protocol + - path: '[].outlierDetection' + widget: FormGroup + children: + - path: splitExternalLocalOriginErrors + name: Split External Local Origin Errors + - path: consecutiveLocalOriginFailures + name: Consecutive Local Origin Failures + type: number + - path: consecutiveGatewayErrors + name: Consecutive Gateway Errors + type: number + - path: consecutive5xxErrors + name: Consecutive 5xx Errors + type: number + - path: interval + name: Interval + - path: baseEjectionTime + name: Base Ejection Time + - path: maxEjectionPercent + name: Max Ejection Percent + - path: minHealthPercent + name: Min Health Percent + - path: '[].tls' + name: TLS + widget: FormGroup + children: + - path: mode + name: Mode + - path: clientCertificate + name: Client Certificate + - path: privateKey + name: Private Key + - path: caCertificates + name: CA Certificates + - path: credentialName + name: Credential Name + - path: subjectAltNames + name: Subject Alt Names + widget: SimpleList + children: + - path: '[]' + - path: sni + name: SNI + - path: insecureSkipVerify + name: Insecure Skip Verify + - path: tunnel + name: Tunnel + widget: FormGroup + children: + - path: protocol + name: Protocol + - path: targetHost + name: Target Host + - path: targetPort + name: Target Port +- path: spec.exportTo + name: Export To + widget: SimpleList + children: + - path: '[]' +- path: spec.workloadSelector.matchLabels + defaultExpanded: true + name: Workload Selector Match Labels + widget: KeyValuePair diff --git a/config/ui-extensions/destinationrules/general b/config/ui-extensions/destinationrules/general new file mode 100644 index 000000000..5d3269d80 --- /dev/null +++ b/config/ui-extensions/destinationrules/general @@ -0,0 +1,9 @@ +resource: + kind: DestinationRule + group: networking.istio.io + version: v1beta1 +name: Destination Rules +category: Istio +urlPath: destinationrules +scope: namespace +description: resource.description \ No newline at end of file diff --git a/config/ui-extensions/destinationrules/kustomization.yaml b/config/ui-extensions/destinationrules/kustomization.yaml new file mode 100644 index 000000000..ced42b863 --- /dev/null +++ b/config/ui-extensions/destinationrules/kustomization.yaml @@ -0,0 +1,15 @@ +configMapGenerator: +- name: destinationrules-ui.operator.kyma-project.io + namespace: kyma-system + files: + - general + - form + - list + - details + - translations + options: + disableNameSuffixHash: true + labels: + app.kubernetes.io/name: istios.operator.kyma-project.io + busola.io/extension: resource + busola.io/extension-version: "0.5" \ No newline at end of file diff --git a/config/ui-extensions/destinationrules/list b/config/ui-extensions/destinationrules/list new file mode 100644 index 000000000..2e238a156 --- /dev/null +++ b/config/ui-extensions/destinationrules/list @@ -0,0 +1,2 @@ +- source: spec.host + name: Host \ No newline at end of file diff --git a/config/ui-extensions/destinationrules/translations b/config/ui-extensions/destinationrules/translations new file mode 100644 index 000000000..57715ba02 --- /dev/null +++ b/config/ui-extensions/destinationrules/translations @@ -0,0 +1,83 @@ +en: + metadata.annotations: Annotations + metadata.labels: Labels + metadata.creationTimestamp: Created at + resource.description: >- + {{[Destination + Rule](https://istio.io/latest/docs/reference/config/networking/destination-rule)}} + specifies rules that apply to traffic intended for a service after routing. + References: References + probes: Probes + Export To: Export To + Workload Selector Match Labels: Workload Selector Match Labels + Traffic Policy: Traffic Policy + Interval: Interval + Name: Name + time: Time + interval: Interval + Host: Host + Connection Pool: Connection Pool + TCP Keep Alive: TCP Keep Alive + Probes: Probes + Time: Time + TCP: TCP + HTTP: HTTP + HTTP1 Max Pending Requests: HTTP1 Max Pending Requests + Max Connections: Max Connections + Connect Timeout: Connect Timeout + HTTP2 Max Requests: HTTP2 Max Requests + Max Requests Per Connection: Max Requests Per Connection + Max Retries: Max Retries + Idle Timeout: Idle Timeout + H2 Upgrade Policy: H2 Upgrade Policy + Use Client Protocol: Use Client Protocol + Locality LB Settings: Locality LB Settings + Enabled: Enabled + Distribute: Distribute + From: From + To: To + Failover: Failover + Failover Priority: Failover Priority + HTTP Cookie: HTTP Cookie + Path: Path + TTL: TTL + Consistent Hash: Consistent Hash + HTTP Header Name: HTTP Header Name + Use Source IP: Use Source IP + HTTP Query Parameter Name: HTTP Query Parameter Name + Minimum Ring Size: Minimum Ring Size + Load Balancer: Load Balancer + Simple: Simple + Warmup Duration Secs: Warmup Duration Secs + ChooseConsistentHashSelector: Select Hash Type + ChooseLoadBalancerSelector: Select Balancer Type + ChooseLbSelector: Select LB Settings + Split External Local Origin Errors: Split External Local Origin Errors + Consecutive Local Origin Failures: Consecutive Local Origin Failures + Consecutive Gateway Errors: Consecutive Gateway Errors + Consecutive 5xx Errors: Consecutive 5xx Errors + Base Ejection Time: Base Ejection Time + Max Ejection Percent: Max Ejection Percent + Min Health Percent: Min Health Percent + Port Level Settings: Port Level Settings + Port Number: Port Number + TLS: TLS + Mode: Mode + Client Certificate: Client Certificate + Private Key: Private Key + CA Certificates: CA Certificates + Credential Name: Credential Name + Subject Alt Names: Subject Alt Names + SNI: SNI + Insecure Skip Verify: Insecure Skip Verify + Tunnel: Tunnel + Protocol: Protocol + Target Host: Target Host + Target Port: Target Port + Subsets: Subsets + Labels: Labels + consistentHash: Consistent Hash + simple: Simple + failover: Failover + distribute: Distribute + diff --git a/config/ui-extensions/gateways/dataSources b/config/ui-extensions/gateways/dataSources new file mode 100644 index 000000000..3d2b9214f --- /dev/null +++ b/config/ui-extensions/gateways/dataSources @@ -0,0 +1,18 @@ +podSelector: + resource: + kind: Pod + version: v1 + namespace: null + filter: $matchByLabelSelector($item, $root.spec.selector) +relatedVirtualServices: + resource: + kind: VirtualService + group: networking.istio.io + version: v1beta1 + namespace: null + filter: >- + $filter($item.spec.gateways, function($g){$contains($g,'/') ? + ($substringBefore($g,'/') = $root.metadata.namespace and $substringAfter($g, + '/') = $root.metadata.name) : ($substringBefore($g, '.') = + $root.metadata.name and $substringBefore($substringAfter($g, '.'), '.') = + $root.metadata.namespace) }) \ No newline at end of file diff --git a/config/ui-extensions/gateways/details b/config/ui-extensions/gateways/details new file mode 100644 index 000000000..4f6288d77 --- /dev/null +++ b/config/ui-extensions/gateways/details @@ -0,0 +1,50 @@ +header: + - source: spec.selector + widget: Labels + name: spec.selector +body: + - widget: Table + source: spec.servers + name: spec.servers + children: + - source: port.name + name: spec.servers.port.name + - widget: JoinedArray + separator: break + source: hosts + name: spec.servers.hosts + - source: port.number + name: spec.servers.port.number + - source: port.protocol + name: spec.servers.port.protocol + - source: tls.mode + name: spec.servers.tls.mode + - widget: ResourceLink + source: tls.credentialName + name: spec.servers.tls.credentialName + resource: + name: tls.credentialName + namespace: '"istio-system"' + kind: '"Secret"' + - widget: Panel + name: spec.selector + disablePadding: true + children: + - source: $podSelector() + widget: ResourceList + disableCreate: true + visibility: $exists($root.spec.selector) and $boolean($root.spec.selector) + - source: spec.selector + widget: Panel + name: selector.matchesAllPods + visibility: $not($exists($value)) or $not($boolean($value)) + header: + - source: spec.selector + widget: Labels + name: spec.selector + visibility: $exists($value) and $boolean($value) +resourceGraph: + depth: 1 + colorVariant: 1 + dataSources: + - source: relatedVirtualServices \ No newline at end of file diff --git a/config/ui-extensions/gateways/form b/config/ui-extensions/gateways/form new file mode 100644 index 000000000..c8024dd39 --- /dev/null +++ b/config/ui-extensions/gateways/form @@ -0,0 +1,88 @@ +- path: spec.selector + widget: KeyValuePair + simple: true + required: true + defaultExpanded: true +- path: spec.servers + widget: GenericList + simple: true + required: true + children: + - widget: FormGroup + simple: true + path: '[].port' + defaultExpanded: true + children: + - path: number + simple: true + required: true + inputInfo: inputInfo.spec.servers.port.number + - path: name + widget: Name + inputInfo: null + simple: true + required: true + - path: protocol + simple: true + enum: + - HTTP + - HTTPS + - HTTP2 + - GRPC + - GRPC-WEB + - MONGO + - REDIS + - MYSQL + - TCP + required: true + placeholder: placeholders.dropdown + - widget: FormGroup + simple: true + path: '[].tls' + visibility: $item.port.protocol = 'HTTP' or $item.port.protocol = 'HTTPS' + children: + - path: httpsRedirect + simple: true + visibility: $item.port.protocol = 'HTTP' + - path: mode + simple: true + visibility: $item.port.protocol = 'HTTPS' + required: true + placeholder: placeholders.dropdown + - path: credentialName + simple: true + widget: Resource + resource: + kind: Secret + version: v1 + namespace: istio-system + scope: namespace + filter: >- + $item.type = 'kubernetes.io/tls' or ($item.type = 'Opaque' and + $contains($item.data, 'key') and $contains($item.data, 'cert')) + visibility: $item.port.protocol = 'HTTPS' + - path: serverCertificate + simple: true + visibility: $item.port.protocol = 'HTTPS' + placeholder: placeholders.serverCertificate + - path: privateKey + simple: true + visibility: $item.port.protocol = 'HTTPS' + placeholder: placeholders.privateKey + - path: caCertificates + simple: true + visibility: $item.port.protocol = 'HTTPS' + placeholder: placeholders.caCertificates + - simple: true + widget: Alert + type: warning + alert: '"alert.tls.https"' + visibility: $item.port.protocol = 'HTTPS' + - widget: SimpleList + path: '[].hosts' + required: true + simple: true + placeholder: placeholders.hosts + children: + - path: '[]' + simple: true \ No newline at end of file diff --git a/config/ui-extensions/gateways/general b/config/ui-extensions/gateways/general new file mode 100644 index 000000000..d92a9bb23 --- /dev/null +++ b/config/ui-extensions/gateways/general @@ -0,0 +1,12 @@ +resource: + kind: Gateway + group: networking.istio.io + version: v1beta1 +urlPath: gateways +category: Istio +name: Gateways +scope: namespace +description: >- + {{[Gateways](https://istio.io/latest/docs/reference/config/networking/gateway/)}} + describes a load balancer that operates at the edge of the mesh and receives + incoming or outgoing HTTP/TCP connections. \ No newline at end of file diff --git a/config/ui-extensions/gateways/kustomization.yaml b/config/ui-extensions/gateways/kustomization.yaml new file mode 100644 index 000000000..a426116d7 --- /dev/null +++ b/config/ui-extensions/gateways/kustomization.yaml @@ -0,0 +1,17 @@ +configMapGenerator: +- name: gateways-ui.operator.kyma-project.io + namespace: kyma-system + files: + - general + - form + - list + - details + - translations + - presets + - dataSources + options: + disableNameSuffixHash: true + labels: + app.kubernetes.io/name: istios.operator.kyma-project.io + busola.io/extension: resource + busola.io/extension-version: "0.5" \ No newline at end of file diff --git a/config/ui-extensions/gateways/list b/config/ui-extensions/gateways/list new file mode 100644 index 000000000..29b6cc10c --- /dev/null +++ b/config/ui-extensions/gateways/list @@ -0,0 +1,3 @@ +- name: spec.selector + source: spec.selector + widget: Labels \ No newline at end of file diff --git a/config/ui-extensions/gateways/presets b/config/ui-extensions/gateways/presets new file mode 100644 index 000000000..7b095ff15 --- /dev/null +++ b/config/ui-extensions/gateways/presets @@ -0,0 +1,24 @@ +- name: Default Gateway + default: true + value: + spec: + selector: + istio: ingressgateway +- name: Ingress Gateway + value: + metadata: + name: httpbin-gateway + labels: + app.kubernetes.io/name: httpbin-gateway + spec: + selector: + istio: ingressgateway + servers: + - port: + number: 443 + name: https + protocol: HTTPS + tls: + mode: SIMPLE + credentialName: '' + hosts: [] \ No newline at end of file diff --git a/config/ui-extensions/gateways/translations b/config/ui-extensions/gateways/translations new file mode 100644 index 000000000..6fe97fef8 --- /dev/null +++ b/config/ui-extensions/gateways/translations @@ -0,0 +1,25 @@ +en: + alert.tls.https: TLS Server of mode SIMPLE or MUTUAL needs either credential name, or private key and server certificate pair. + spec.selector: Selector + spec.gateways: Gateways + spec.servers: Servers + spec.servers.port: Port + spec.servers.port.name: Port Name + spec.servers.port.protocol: Protocol + spec.servers.port.targetPort: Target Port + spec.servers.port.number: Port Number + spec.servers.tls: TLS + spec.servers.tls.mode: TLS Mode + spec.servers.tls.httpsRedirect: HTTP Redirect + spec.servers.tls.credentialName: Credential Name + spec.servers.tls.serverCertificate: Server Certificate + spec.servers.tls.privateKey: Private Key + spec.servers.tls.caCertificates: CA Certificate + spec.servers.hosts: Hosts + selector.matchesAllPods: Matches all Pods in the Namespace + placeholders.dropdown: Type or choose an option + placeholders.serverCertificate: Enter the certificate path + placeholders.privateKey: Enter the private key path + placeholders.caCertificates: Enter the CA certificates path + placeholders.hosts: For example, *.api.mydomain.com + inputInfo.spec.servers.port.number: Must be a on-negative number. \ No newline at end of file diff --git a/config/ui-extensions/kustomization.yaml b/config/ui-extensions/kustomization.yaml index c506d7dad..e62544542 100644 --- a/config/ui-extensions/kustomization.yaml +++ b/config/ui-extensions/kustomization.yaml @@ -1,2 +1,8 @@ resources: - istios +- gateways +- virtualservices +- destinationrules +- serviceentries +- authorizationpolicies +- sidecars \ No newline at end of file diff --git a/config/ui-extensions/serviceentries/dataSources b/config/ui-extensions/serviceentries/dataSources new file mode 100644 index 000000000..6dfd2237e --- /dev/null +++ b/config/ui-extensions/serviceentries/dataSources @@ -0,0 +1,5 @@ +podSelector: + resource: + kind: Pod + version: v1 + filter: $matchByLabelSelector($item, $root.spec.workloadSelector.labels) diff --git a/config/ui-extensions/serviceentries/details b/config/ui-extensions/serviceentries/details new file mode 100644 index 000000000..81dfcfd18 --- /dev/null +++ b/config/ui-extensions/serviceentries/details @@ -0,0 +1,84 @@ +header: + - source: spec.location + name: spec.location + - source: spec.resolution + name: spec.resolution +resourceGraph: + colorVariant: 2 + dataSources: + - source: podSelector +body: + - name: configuration + widget: Panel + source: spec + visibility: >- + $boolean($exists($value.hosts) or $exists($value.addresses) or + $exists($value.subjectAltNames)) + children: + - name: spec.hosts + source: hosts + widget: JoinedArray + visibility: $exists($value) + - name: spec.addresses + source: addresses + widget: JoinedArray + visibility: $exists($value) + - name: spec.exportTo + source: exportTo + widget: Labels + placeholder: Exported to all Namespaces + - name: spec.subjectAltNames + source: subjectAltNames + widget: JoinedArray + visibility: $exists($value) + - name: spec.ports + widget: Table + source: spec.ports + visibility: $exists($value) + children: + - name: spec.ports.number + source: number + sort: true + - name: spec.ports.protocol + source: protocol + sort: true + - name: spec.ports.name + source: name + sort: true + - name: spec.ports.targetPort + source: targetPort + sort: true + - name: spec.endpoints + widget: Table + source: spec.endpoints + visibility: $exists($value) + children: + - name: spec.endpoints.address + source: address + sort: true + - name: spec.endpoints.ports + source: ports + widget: Labels + - name: spec.endpoints.labels + source: labels + widget: Labels + - name: spec.endpoints.network + source: network + sort: true + - name: spec.endpoints.weight + source: weight + - name: spec.endpoints.serviceAccount + source: serviceAccount + - name: spec.workloadSelector + widget: Panel + source: spec.workloadSelector.labels + visibility: $exists($value) + disablePadding: true + children: + - source: $podSelector() + widget: ResourceList + disableCreate: true + header: + - widget: Labels + source: spec.workloadSelector.labels + visibility: $exists($value) \ No newline at end of file diff --git a/config/ui-extensions/serviceentries/form b/config/ui-extensions/serviceentries/form new file mode 100644 index 000000000..5a1f34d4e --- /dev/null +++ b/config/ui-extensions/serviceentries/form @@ -0,0 +1,80 @@ +- path: spec.hosts + name: spec.hosts + widget: SimpleList + simple: true + required: true + children: + - path: '[]' + simple: true +- path: spec.addresses + name: spec.addresses + widget: SimpleList + placeholder: placeholders.addreses + children: + - path: '[]' +- path: spec.ports + name: Ports + widget: GenericList + children: + - path: '[].number' + name: spec.ports.number + required: true + - path: '[].protocol' + name: spec.ports.protocol + required: true + placeholder: placeholders.dropdown + enum: + - HTTP + - HTTPS + - GRPC + - HTTP2 + - MONGO + - TCP + - TLS + - path: '[].name' + name: spec.ports.name + required: true + - path: '[].targetPort' + name: spec.ports.targetPort +- path: spec.location + name: spec.location + placeholder: placeholders.dropdown +- path: spec.resolution + name: spec.resolution + placeholder: placeholders.dropdown +- path: spec.endpoints + name: spec.endpoints + widget: GenericList + children: + - path: '[].address' + name: spec.endpoints.address + - path: '[].ports' + name: spec.endpoints.ports + widget: KeyValuePair + value: + type: number + - path: '[].labels' + name: spec.endpoints.labels + widget: KeyValuePair + - path: '[].network' + name: spec.endpoints.network + - path: '[].locality' + name: spec.endpoints.locality + - path: '[].weight' + name: spec.endpoints.weight + - path: '[].serviceAccount' + name: spec.endpoints.serviceAccount +- path: spec.workloadSelector.labels + name: spec.workloadSelector + widget: KeyValuePair + defaultExpanded: true +- path: spec.exportTo + name: spec.exportTo + widget: SimpleList + children: + - path: '[]' +- path: spec.subjectAltNames + name: spec.subjectAltNames + widget: SimpleList + children: + - path: '[]' \ No newline at end of file diff --git a/config/ui-extensions/serviceentries/general b/config/ui-extensions/serviceentries/general new file mode 100644 index 000000000..27d8015c9 --- /dev/null +++ b/config/ui-extensions/serviceentries/general @@ -0,0 +1,11 @@ +resource: + kind: ServiceEntry + group: networking.istio.io + version: v1beta1 +urlPath: serviceentries +category: Istio +name: Service Entries +scope: namespace +description: >- + {{[ServiceEntry](https://istio.io/latest/docs/reference/config/networking/service-entry/)}} + allows for adding more entries to the internal service registry of Istio. \ No newline at end of file diff --git a/config/ui-extensions/serviceentries/kustomization.yaml b/config/ui-extensions/serviceentries/kustomization.yaml new file mode 100644 index 000000000..48c129d16 --- /dev/null +++ b/config/ui-extensions/serviceentries/kustomization.yaml @@ -0,0 +1,16 @@ +configMapGenerator: +- name: serviceentries-ui.operator.kyma-project.io + namespace: kyma-system + files: + - general + - form + - list + - details + - dataSources + - translations + options: + disableNameSuffixHash: true + labels: + app.kubernetes.io/name: istios.operator.kyma-project.io + busola.io/extension: resource + busola.io/extension-version: "0.5" \ No newline at end of file diff --git a/config/ui-extensions/serviceentries/list b/config/ui-extensions/serviceentries/list new file mode 100644 index 000000000..4cd28099d --- /dev/null +++ b/config/ui-extensions/serviceentries/list @@ -0,0 +1,6 @@ +- source: spec.location + name: spec.location + sort: true +- source: spec.resolution + name: spec.resolution + sort: true \ No newline at end of file diff --git a/config/ui-extensions/serviceentries/translations b/config/ui-extensions/serviceentries/translations new file mode 100644 index 000000000..878f85681 --- /dev/null +++ b/config/ui-extensions/serviceentries/translations @@ -0,0 +1,24 @@ +en: + configuration: Configuration + spec.hosts: Hosts + spec.addresses: Addresses + spec.ports: Ports + spec.ports.number: Number + spec.ports.protocol: Protocol + spec.ports.name: Name + spec.ports.targetPort: Target Port + spec.location: Location + spec.resolution: Resolution + spec.endpoints: Endpoints + spec.endpoints.address: Address + spec.endpoints.ports: Ports + spec.endpoints.labels: Labels + spec.endpoints.network: Network + spec.endpoints.locality: Locality + spec.endpoints.weight: Weight + spec.endpoints.serviceAccount: Service Account + spec.workloadSelector: Workload Selector + spec.exportTo: Export To + spec.subjectAltNames: Subject Alt Names + placeholders.dropdown: Type or choose an option + placeholders.addreses: For example, 127.0.0.1 \ No newline at end of file diff --git a/config/ui-extensions/sidecars/dataSources b/config/ui-extensions/sidecars/dataSources new file mode 100644 index 000000000..eb55db93b --- /dev/null +++ b/config/ui-extensions/sidecars/dataSources @@ -0,0 +1,5 @@ +podSelector: + resource: + kind: Pod + version: v1 + filter: $matchByLabelSelector($item, $root.spec.workloadSelector.labels) \ No newline at end of file diff --git a/config/ui-extensions/sidecars/details b/config/ui-extensions/sidecars/details new file mode 100644 index 000000000..432ea39e7 --- /dev/null +++ b/config/ui-extensions/sidecars/details @@ -0,0 +1,79 @@ +header: + - name: Outbound Traffic Policy Mode + source: spec.outboundTrafficPolicy.mode +body: + - widget: Table + source: spec.egress + name: Egress + visibility: $exists($value) + children: + - source: port + name: Port + widget: Panel + visibility: $exists($value) + children: + - source: number + name: Number + - source: name + name: Name + - source: protocol + name: Protocol + - source: targetPoint + name: Target Point + - source: bind + name: Bind + - source: captureMode + name: Capture Mode + - source: hosts + name: Hosts + widget: Labels + - widget: Table + source: spec.ingress + name: Ingress + visibility: $exists($value) + children: + - source: port + name: Port + widget: Panel + visibility: $exists($value) + children: + - source: number + name: Number + - source: name + name: Name + - source: protocol + name: Protocol + - source: targetPoint + name: Target Point + - source: $parent.tls.mode + name: TLS Mode + - source: bind + name: Bind + - source: captureMode + name: Capture Mode + - source: defaultEndpoint + name: Default Endpoint + widget: Labels + - widget: Panel + name: Workload Selector + disablePadding: true + children: + - source: $podSelector() + widget: ResourceList + disableCreate: true + isCompact: true + visibility: $exists($root.spec.workloadSelector.labels) and $boolean($root.spec.workloadSelector.labels) + - source: spec.workloadSelector.labels + widget: Panel + name: Matches all Pods in the Namespace + visibility: $not($exists($value)) or $not($boolean($value)) + header: + - source: spec.workloadSelector.labels + widget: Labels + name: Workload Selector + visibility: $exists($value) and $boolean($value) +resourceGraph: + depth: 1 + colorVariant: 1 + dataSources: + - source: podSelector \ No newline at end of file diff --git a/config/ui-extensions/sidecars/form b/config/ui-extensions/sidecars/form new file mode 100644 index 000000000..b670ecabd --- /dev/null +++ b/config/ui-extensions/sidecars/form @@ -0,0 +1,120 @@ +- path: spec.workloadSelector.labels + name: Workload Selector + widget: KeyValuePair +- widget: FormGroup + path: spec.egress[].port + simple: true + children: + - path: number + simple: true + placeholder: Enter the port number + - path: name + widget: Name + inputInfo: null + simple: true + - path: protocol + simple: true + enum: + - HTTP + - HTTPS + - HTTP2 + - GRPC + - MONGO + - TCP + - TLS + placeholder: Type or choose an option +- path: spec.egress[].bind + placeholder: Enter the IPv4 or IPv6 + simple: true +- path: spec.egress[].captureMode + simple: true + enum: + - DEFAULT + - IPTABLES + - NONE + placeholder: Type or choose an option +- widget: SimpleList + path: spec.egress[].hosts + required: true + simple: true + placeholder: For example, *.api.mydomain.com + children: + - path: '[]' + simple: true +- widget: FormGroup + path: spec.ingress[].port + required: true + simple: true + children: + - path: number + simple: true + required: true + placeholder: Enter the port number + - path: name + widget: Name + inputInfo: null + simple: true + required: true + - path: protocol + simple: true + enum: + - HTTP + - HTTPS + - HTTP2 + - GRPC + - MONGO + - TCP + - TLS + required: true + placeholder: Type or choose an option +- path: spec.ingress[].bind + placeholder: Enter the IPv4 or IPv6 + simple: true +- path: spec.ingress[].captureMode + enum: + - DEFAULT + - IPTABLES + - NONE + simple: true + placeholder: Type or choose an option +- path: spec.ingress[].defaultEndpoint + placeholder: For example, 127.0.0.1:PORT + required: true + simple: true +- widget: FormGroup + simple: true + path: spec.ingress[].tls + name: TLS + visibility: $item.port.protocol = 'HTTPS' + children: + - path: mode + name: TLS Mode + simple: true + visibility: $item.port.protocol = 'HTTPS' + required: true + placeholder: Type or choose an option + - path: serverCertificate + name: Server Certificate + simple: true + visibility: $item.port.protocol = 'HTTPS' + placeholder: Enter the certificate path + - path: privateKey + name: Private Key + simple: true + visibility: $item.port.protocol = 'HTTPS' + placeholder: Enter the private key path + - path: caCertificates + name: CA Certificate + simple: true + visibility: $item.port.protocol = 'HTTPS' + placeholder: Enter the CA certificates path +- widget: FormGroup + path: spec.outboundTrafficPolicy + name: Outbound Traffic Policy + children: + - path: mode + name: Outbound Traffic Policy Mode + enum: + - REGISTRY_ONLY + - ALLOW_ANY + placeholder: Type or choose an option \ No newline at end of file diff --git a/config/ui-extensions/sidecars/general b/config/ui-extensions/sidecars/general new file mode 100644 index 000000000..2b21f5ee3 --- /dev/null +++ b/config/ui-extensions/sidecars/general @@ -0,0 +1,12 @@ +resource: + kind: Sidecar + group: networking.istio.io + version: v1beta1 +urlPath: sidecars +category: Istio +name: Sidecars +scope: namespace +description: >- + {{[Sidecar](https://istio.io/latest/docs/reference/config/networking/sidecar/)}} + manages the incoming and outgoing communication in a workload it is attached + to. \ No newline at end of file diff --git a/config/ui-extensions/sidecars/kustomization.yaml b/config/ui-extensions/sidecars/kustomization.yaml new file mode 100644 index 000000000..84ea37338 --- /dev/null +++ b/config/ui-extensions/sidecars/kustomization.yaml @@ -0,0 +1,15 @@ +configMapGenerator: +- name: sidecars-ui.operator.kyma-project.io + namespace: kyma-system + files: + - general + - form + - list + - details + - dataSources + options: + disableNameSuffixHash: true + labels: + app.kubernetes.io/name: istios.operator.kyma-project.io + busola.io/extension: resource + busola.io/extension-version: "0.5" \ No newline at end of file diff --git a/config/ui-extensions/sidecars/list b/config/ui-extensions/sidecars/list new file mode 100644 index 000000000..cf9258107 --- /dev/null +++ b/config/ui-extensions/sidecars/list @@ -0,0 +1,5 @@ +- source: spec.outboundTrafficPolicy.mode + name: Outbound Traffic Policy Mode +- source: spec.workloadSelector.labels + name: Workload Selector Labels + widget: Labels \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/dataSources b/config/ui-extensions/virtualservices/dataSources new file mode 100644 index 000000000..46bc04ecb --- /dev/null +++ b/config/ui-extensions/virtualservices/dataSources @@ -0,0 +1,21 @@ +relatedGateways: + resource: + kind: Gateway + group: networking.istio.io + version: v1beta1 + namespace: null + filter: >- + $filter($root.spec.gateways, function($g){$contains($g,'/') ? + ($substringBefore($g,'/') = $item.metadata.namespace and $substringAfter($g, + '/') = $item.metadata.name) : ($substringBefore($g, '.') = + $item.metadata.name and $substringBefore($substringAfter($g, '.'), '.') = + $item.metadata.namespace) }) +relatedServices: + resource: + kind: Service + version: v1 + namespace: null + filter: >- + $filter($root.spec.http.route, function($r) { $filter($r.destination.host, + function($h){($substringBefore($h, '.') = $item.metadata.name) and + ($split($substringAfter($h, '.'),'.')[0] = $item.metadata.namespace)} ) }) \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/details b/config/ui-extensions/virtualservices/details new file mode 100644 index 000000000..a304620a2 --- /dev/null +++ b/config/ui-extensions/virtualservices/details @@ -0,0 +1,376 @@ +resourceGraph: + dataSources: + - source: relatedGateways + - source: relatedServices +body: + - widget: Table + source: spec.gateways[] + name: gateways + visibility: $exists($value) + children: + - source: $item + name: t-name + widget: ResourceLink + resource: + kind: '"Gateway"' + name: >- + $contains($item,'/') ? $substringAfter($item, '/') : + $substringBefore($item, '.') + namespace: >- + $contains($item,'/') ? $substringBefore($item, '/'): + $substringBefore($substringAfter($item, '.'), '.') + - name: summary + widget: Panel + source: spec + visibility: $boolean($exists($value.exportTo) or $exists($value.hosts)) + children: + - name: exportTo + source: exportTo + widget: Labels + visibility: $exists($value) + - name: hosts + source: hosts + widget: JoinedArray + visibility: $exists($value) + - widget: Table + source: spec.http + name: http + visibility: $exists($value) + children: + - source: name + name: t-name + - source: timeout + name: timeout + - source: mirrorPercentage.value + name: mirrorPercentage + collapsible: + - source: match + name: matches + widget: Table + visibility: $exists($value) + children: + - source: name + name: t-name + - source: uri + name: uri + widget: Labels + - source: scheme + name: scheme + widget: Labels + - source: method + name: method + widget: Labels + - source: authority + name: authority + widget: Labels + - source: headers + name: headers + - source: port + name: port + - source: sourceLabels + name: sourceLabels + widget: Labels + - source: gateways + name: gateways + widget: JoinedArray + - source: queryParams + name: queryParams + - source: ignoreUriCase + name: ignoreUriCase + - source: withoutHeaders + name: withoutHeaders + - source: sourceNamespace + name: sourceNamespace + - source: statPrefix + name: statPrefix + - source: route + name: routes + widget: Table + visibility: $exists($value) + children: + - source: destination + name: destination + widget: Panel + visibility: $exists($value) + children: + - source: host + name: host + - source: subset + name: subset + - source: port.number + name: port.number + - source: weight + name: weight + - source: headers + name: headers + widget: Panel + visibility: $exists($value) + children: + - source: request + name: request + widget: Panel + visibility: $exists($value) + children: + - source: set + name: set + widget: Labels + - source: add + name: add + widget: Labels + - source: remove + name: remove + widget: JoinedArray + - source: response + name: response + widget: Panel + visibility: $exists($value) + children: + - source: set + name: set + widget: Labels + - source: add + name: add + widget: Labels + - source: remove + name: remove + widget: JoinedArray + - source: redirect + name: redirect + widget: Panel + visibility: $exists($value) + children: + - source: uri + name: uri + - source: authority + name: authority + - source: port + name: port + - source: derivePort + name: derivePort + widget: Labels + - source: scheme + name: scheme + - source: redirectCode + name: redirectCode + - source: directResponse + name: directResponse + widget: Panel + visibility: $exists($value) + children: + - source: status + name: status + - source: body + name: body + widget: Panel + visibility: $exists($value) + children: + - source: string + name: string + - source: bytes + name: bytes + - source: delegate + name: delegate + widget: Panel + visibility: $exists($value) + children: + - source: name + name: t-name + - source: namespace + name: namespace + - source: rewrite + name: rewrite + widget: Panel + visibility: $exists($value) + children: + - source: uri + name: uri + - source: authority + name: authority + - source: retries + name: retries + widget: Panel + visibility: $exists($value) + children: + - source: attempts + name: attempts + - source: perTryTimeout + name: perTryTimeout + - source: retryOn + name: retryOn + - source: retryRemoteLocalities + name: retryRemoteLocalities + - source: fault + name: fault + widget: Panel + visibility: $exists($value) + children: + - source: delay + name: delay + widget: Panel + visibility: $exists($value) + children: + - source: fixedDelay + name: fixedDelay + - source: percentage.value + name: percentage.value + - source: percent + name: percent + - source: abort + name: Abort + widget: Panel + visibility: $exists($value) + children: + - source: httpStatus + name: httpStatus + - source: percentage.value + name: percentage.value + - source: mirror + name: Mirror + widget: Panel + visibility: $exists($value) + children: + - source: host + name: host + - source: subset + name: subset + - source: port.number + name: port.number + - source: corsPolicy + name: corsPolicy + widget: Panel + visibility: $exists($value) + children: + - source: allowOrigins + name: allowOrigins + - source: allowMethods + name: allowMethods + widget: JoinedArray + - source: allowHeaders + name: allowHeaders + widget: JoinedArray + - source: exposeHeaders + name: exposeHeaders + widget: JoinedArray + - source: maxAge + name: maxAge + - source: allowCredentials + name: allowCredentials + - source: headers + name: headers + widget: Panel + visibility: $exists($value) + children: + - source: request + name: request + widget: Panel + visibility: $exists($value) + children: + - source: set + name: set + widget: Labels + - source: add + name: add + widget: Labels + - source: remove + name: remove + widget: JoinedArray + - source: response + name: response + widget: Panel + visibility: $exists($value) + children: + - source: set + name: set + widget: Labels + - source: add + name: add + widget: Labels + - source: remove + name: remove + widget: JoinedArray + - widget: Table + source: spec.tcp + name: tcp + visibility: $exists($value) + children: + - source: match + name: matches + widget: Table + visibility: $exists($value) + children: + - source: destinationSubnets + name: destinationSubnets + widget: JoinedArray + - source: port + name: port + - source: sourceLabels + name: sourceLabels + widget: Labels + - source: gateways + name: gateways + widget: JoinedArray + - source: sourceNamespace + name: sourceNamespace + collapsible: + - source: route + name: routes + widget: Table + visibility: $exists($value) + children: + - source: destination + name: destination + widget: Panel + visibility: $exists($value) + children: + - source: host + name: host + - source: subset + name: subset + - source: port.number + name: port + - source: weight + name: weight + - widget: Table + source: spec.tls + name: tls + visibility: $exists($value) + children: + - source: match + name: matches + widget: Table + visibility: $exists($value) + children: + - source: sniHosts + name: sniHosts + widget: JoinedArray + - source: destinationSubnets + name: destinationSubnets + widget: JoinedArray + - source: port + name: port + - source: sourceLabels + name: sourceLabels + widget: Labels + - source: gateways + name: gateways + widget: JoinedArray + - source: sourceNamespace + name: sourceNamespace + collapsible: + - source: route + name: routes + widget: Table + visibility: $exists($value) + children: + - source: destination + name: destination + widget: Panel + children: + - source: host + name: host + - source: subset + name: subset + - source: port.number + name: port.number + - source: weight + name: weight \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/form b/config/ui-extensions/virtualservices/form new file mode 100644 index 000000000..a2a3c5fc1 --- /dev/null +++ b/config/ui-extensions/virtualservices/form @@ -0,0 +1,480 @@ +- path: spec.tls + widget: GenericList + name: tls + children: + - path: '[].match' + widget: GenericList + name: matches + children: + - path: '[].sniHosts' + widget: SimpleList + name: sniHosts + children: + - path: '[]' + - path: '[].sourceNamespace' + name: sourceNamespace + - path: '[].port' + name: port + - path: '[].destinationSubnets' + widget: SimpleList + name: destinationSubnets + children: + - path: '[]' + - path: '[].sourceLabels' + widget: KeyValuePair + name: sourceLabels + - path: '[].gateways' + widget: SimpleList + name: gateways + children: + - path: '[]' + - path: '[].route' + widget: GenericList + name: routes + children: + - path: '[].destination' + widget: FormGroup + name: destination + children: + - path: host + name: host + - path: subset + name: subset + - path: port.number + name: port.number + - path: '[].weight' + name: weight +- path: spec.tcp + name: tcp + widget: GenericList + children: + - path: '[].match' + name: matches + children: + - path: '[].sourceNamespace' + name: sourceNamespace + - path: '[].port' + name: port + - path: '[].sniHosts' + widget: SimpleList + name: sniHosts + children: + - path: '[]' + - path: '[].destinationSubnets' + widget: SimpleList + name: destinationSubnets + children: + - path: '[]' + - path: '[].sourceLabels' + name: sourceLabels + widget: KeyValuePair + - path: '[].gateways' + widget: SimpleList + name: gateways + children: + - path: '[]' + - path: '[].route' + name: routes + children: + - path: '[].destination' + widget: FormGroup + name: destination + children: + - path: host + name: host + - path: subset + name: subset + - path: port.number + name: port.number + - path: '[].weight' + name: weight +- path: spec.http + simple: true + name: http + widget: GenericList + children: + - path: '[].match' + simple: true + name: matches + widget: GenericList + children: + - path: '[].name' + simple: true + name: t-name + - path: '[].uri' + simple: true + name: uri + widget: KeyValuePair + keyEnum: + - prefix + - exact + - regex + - path: '[].scheme' + simple: true + name: scheme + widget: KeyValuePair + keyEnum: + - prefix + - exact + - regex + - path: '[].method' + simple: true + name: method + widget: KeyValuePair + keyEnum: + - prefix + - exact + - regex + - path: '[].authority' + simple: true + name: authority + widget: KeyValuePair + keyEnum: + - prefix + - exact + - regex + - path: '[].headers' + simple: true + name: headers + defaultExpanded: true + widget: KeyValuePair + value: + type: object + keyEnum: + - prefix + - exact + - regex + - path: '[].port' + simple: true + name: port + - path: '[].sourceLabels' + simple: true + name: sourceLabels + widget: KeyValuePair + - path: '[].gateways' + simple: true + name: gateways + widget: SimpleList + children: + - path: '[]' + - path: '[].queryParams' + simple: true + name: queryParams + widget: KeyValuePair + value: + type: object + keyEnum: + - prefix + - exact + - regex + - path: '[].ignoreUriCase' + simple: true + name: ignoreUriCase + - path: '[].withoutHeaders' + simple: true + name: withoutHeaders + widget: KeyValuePair + value: + type: object + keyEnum: + - prefix + - exact + - regex + - path: '[].sourceNamespace' + simple: true + name: sourceNamespace + - path: '[].statPrefix' + simple: true + name: statPrefix + - path: '[].route' + simple: true + name: routes + children: + - path: '[].destination' + simple: true + name: destination + widget: FormGroup + children: + - path: host + name: host + - path: subset + name: subset + - path: port.number + name: port.number + - path: '[].weight' + simple: true + name: weight + - path: '[].headers' + simple: true + name: headers + widget: FormGroup + children: + - path: response + simple: true + name: response + widget: FormGroup + children: + - path: set + simple: true + name: set + widget: KeyValuePair + - path: add + simple: true + name: add + widget: KeyValuePair + - path: remove + simple: true + name: remove + widget: SimpleList + children: + - path: '[]' + simple: true + - path: request + simple: true + name: request + widget: FormGroup + children: + - path: set + simple: true + name: set + widget: KeyValuePair + - path: add + simple: true + name: add + widget: KeyValuePair + - path: remove + simple: true + name: remove + widget: SimpleList + children: + - path: '[]' + simple: true + - path: '[].redirect' + simple: true + name: redirect + widget: FormGroup + children: + - path: uri + simple: true + name: uri + - path: authority + simple: true + name: authority + - path: port + simple: true + name: port + - path: derivePort + simple: true + name: derivePort + - path: scheme + simple: true + name: scheme + - path: redirectCode + simple: true + name: redirectCode + - path: '[].directResponse' + simple: true + name: directResponse + widget: FormGroup + children: + - path: status + simple: true + name: status + - path: body + simple: true + name: body + widget: FormGroup + children: + - path: string + simple: true + name: string + - path: bytes + simple: true + name: bytes + - path: '[].delegate' + simple: true + name: delegate + widget: FormGroup + children: + - path: name + simple: true + name: name + - path: namespace + simple: true + name: namespace + - path: '[].rewrite' + simple: true + name: rewrite + widget: FormGroup + children: + - path: uri + simple: true + name: uri + - path: authority + simple: true + name: authority + - path: '[].timeout' + simple: true + name: timeout + - path: '[].retries' + simple: true + name: retries + widget: FormGroup + children: + - path: attempts + simple: true + name: attempts + - path: perTryTimeout + simple: true + name: perTryTimeout + - path: retryOn + simple: true + name: retryOn + - path: retryRemoteLocalities + simple: true + name: retryRemoteLocalities + - path: '[].fault' + simple: true + name: fault + widget: FormGroup + children: + - path: delay + simple: true + name: delay + widget: FormGroup + children: + - path: fixedDelay + simple: true + name: fixedDelay + - path: percentage.value + simple: true + name: percentage.value + - path: percent + simple: true + name: percent + - path: abort + simple: true + name: abort + widget: FormGroup + children: + - path: httpStatus + simple: true + name: httpStatus + - path: grpcStatus + simple: true + name: grpcStatus + - path: percentage.value + simple: true + name: percentage.value + - path: '[].mirror' + simple: true + name: mirror + widget: FormGroup + children: + - path: host + simple: true + name: host + - path: subset + simple: true + name: subset + - path: port.number + simple: true + name: port.number + - path: '[].mirrorPercentage.value' + simple: true + name: mirrorPercentage + - path: '[].corsPolicy' + simple: true + name: corsPolicy + widget: FormGroup + children: + - path: allowCredentials + simple: true + name: allowCredentials + type: boolean + - path: allowMethods + simple: true + name: allowMethods + widget: SimpleList + placeholder: allowMethods.placeholder + children: + - path: '[]' + simple: true + - path: allowHeaders + simple: true + name: allowHeaders + widget: SimpleList + children: + - path: '[]' + simple: true + - path: exposeHeaders + simple: true + name: exposeHeaders + widget: SimpleList + children: + - path: '[]' + simple: true + - path: maxAge + simple: true + name: maxAge + placeholder: maxAge.placeholder + - path: '[].headers' + simple: true + name: headers + widget: FormGroup + children: + - path: response + simple: true + name: response + widget: FormGroup + children: + - path: set + simple: true + name: set + widget: KeyValuePair + - path: add + simple: true + name: add + widget: KeyValuePair + - path: remove + simple: true + name: remove + widget: SimpleList + children: + - path: '[]' + simple: true + - path: request + simple: true + name: request + widget: FormGroup + children: + - path: set + simple: true + name: set + widget: KeyValuePair + - path: add + simple: true + name: add + widget: KeyValuePair + - path: remove + simple: true + name: remove + widget: SimpleList + children: + - path: '[]' + simple: true +- path: spec.hosts + name: hosts + widget: SimpleList + children: + - path: '[]' +- path: spec.gateways + name: gateways + widget: SimpleList + children: + - path: '[]' +- path: spec.exportTo + name: exportTo + widget: SimpleList + children: + - path: '[]' \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/general b/config/ui-extensions/virtualservices/general new file mode 100644 index 000000000..102d61d49 --- /dev/null +++ b/config/ui-extensions/virtualservices/general @@ -0,0 +1,11 @@ +resource: + kind: VirtualService + group: networking.istio.io + version: v1beta1 +urlPath: virtualservices +category: Istio +name: Virtual Services +scope: namespace +description: >- + {{[VirtualService](https://istio.io/latest/docs/reference/config/networking/virtual-service/)}} + describes a configuration that affects traffic routing. . \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/kustomization.yaml b/config/ui-extensions/virtualservices/kustomization.yaml new file mode 100644 index 000000000..049c6fbbe --- /dev/null +++ b/config/ui-extensions/virtualservices/kustomization.yaml @@ -0,0 +1,16 @@ +configMapGenerator: +- name: virtualservices-ui.operator.kyma-project.io + namespace: kyma-system + files: + - general + - form + - list + - details + - translations + - dataSources + options: + disableNameSuffixHash: true + labels: + app.kubernetes.io/name: istios.operator.kyma-project.io + busola.io/extension: resource + busola.io/extension-version: "0.5" \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/list b/config/ui-extensions/virtualservices/list new file mode 100644 index 000000000..aba49cc33 --- /dev/null +++ b/config/ui-extensions/virtualservices/list @@ -0,0 +1,6 @@ +- name: hosts + source: spec.hosts + widget: JoinedArray +- name: gateways + source: spec.gateways + widget: JoinedArray \ No newline at end of file diff --git a/config/ui-extensions/virtualservices/translations b/config/ui-extensions/virtualservices/translations new file mode 100644 index 000000000..18ea0908d --- /dev/null +++ b/config/ui-extensions/virtualservices/translations @@ -0,0 +1,71 @@ +en: + t-name: Name + gateways: Gateways + hosts: Hosts + exportTo: Export to + summary: Summary + http: HTTP + tls: TLS + tcp: TCP + mirror: Mirror + mirrorPercentage: Mirror Percentage + timeout: Timeout + matches: Matches + uri: URI + scheme: Scheme + method: Method + authority: Authority + headers: Headers + port: Port + sourceLabels: Source Labels + queryParams: Query Params + ignoreUriCase: Ignore URI Case + withoutHeaders: Without Headers + sourceNamespace: Source Namespace + statPrefix: Stat Prefix + routes: Routes + destination: Destination + host: Host + subset: Subset + port.number: Port Number + weight: Weight + request: Request + response: Response + set: Set + add: Add + remove: Remove + redirect: Redirect + derivePort: Derive Port + redirectCode: Redirect Code + directResponse: Direct Response + status: Status + body: Body + string: String + bytes: Bytes + delegate: Delegate + namespace: Namespace + rewrite: Rewrite + retries: Retries + attempts: Attempts + perTryTimeout: Per Try Timeout + retryOn: Retry On + retryRemoteLocalities: Retry Remote Localities + fault: Fault + delay: Delay + fixedDelay: Fixed Delay + abort: Abort + percentage.value: Percentage Value + percent: Percent + httpStatus: HTTP Status + grpcStatus: GRPC Status + corsPolicy: CORS Policy + allowOrigins: Allow Origins + allowMethods: Allow Methods + allowMethods.placeholder: For example, GET + allowHeaders: Allow Headers + exposeHeaders: Expose Headers + maxAge: Max Age + maxAge.placeholder: For example, 24h + allowCredentials: Allow Credentials + destinationSubnets: Destination Subnets + sniHosts: SNI Hosts \ No newline at end of file diff --git a/tests/ui/.gitignore b/tests/ui/.gitignore new file mode 100644 index 000000000..90a61352f --- /dev/null +++ b/tests/ui/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ +cypress/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +dist +extensions-local +statics-local +wizards-local + +.DS_Store + +environments/**/Dockerfile* +kubeconfig.yaml diff --git a/tests/ui/README.md b/tests/ui/README.md new file mode 100644 index 000000000..d95e3d060 --- /dev/null +++ b/tests/ui/README.md @@ -0,0 +1,66 @@ +# Tests + +## Overview + +This folder contains Istio integration tests for Kyma dashboard. + +## Prerequisites + +If you want to use an existing cluster, you must copy your cluster's kubeconfig file to `fixtures/kubeconfig.yaml`. + +## Installation + +To install the dependencies, run the `npm clean install` command. + +## Test Development Using Headless Mode with Chrome Browser + +### Using a Local Kyma Dashboard Instance + +Start a k3d cluster: + +```bash +npm run start-k3d +``` + +Start the local Kyma Dashboard instance: + +```bash +npm run start-dashboard +``` + +#### Run Tests + +```bash +npm run test +``` + +#### Run Cypress UI Tests in the Test Runner Mode + +```bash +npm run start +``` + +### Using a Remote Kyma Dashboard Instance + +#### Optional: Log In to a Cluster Using OIDC + +If a cluster requires OIDC authentication, include the additional arguments **CYPRESS_OIDC_PASS** and **CYPRESS_OIDC_USER** while running the npm scripts. + +#### Run Tests +```bash +CYPRESS_OIDC_PASS={YOUR_PASSWORD} CYPRESS_OIDC_USER={YOUR_USERNAME} CYPRESS_DOMAIN={REMOTE_CLUSTER_DASHBOARD_DOMAIN} npm run test +``` + +#### Run Cypress UI Tests in the Test Runner Mode + +```bash +CYPRESS_OIDC_PASS={YOUR_PASSWORD} CYPRESS_OIDC_USER={YOUR_USERNAME} CYPRESS_DOMAIN={REMOTE_CLUSTER_DASHBOARD_DOMAIN} npm run start +``` + +## Run Tests in Continuous Integration System + +Start a k3d cluster and run the tests: + +```bash +./scripts/k3d-ci-kyma-dashboard-integration.sh +``` diff --git a/tests/ui/config.js b/tests/ui/config.js new file mode 100644 index 000000000..80469150c --- /dev/null +++ b/tests/ui/config.js @@ -0,0 +1,5 @@ +const defaultKymaDashboardAddress = "http://localhost:3001"; + +export default { + clusterAddress: Cypress.env("DOMAIN") || defaultKymaDashboardAddress +}; diff --git a/tests/ui/cypress.config.js b/tests/ui/cypress.config.js new file mode 100644 index 000000000..f9b5d6168 --- /dev/null +++ b/tests/ui/cypress.config.js @@ -0,0 +1,36 @@ +const { defineConfig } = require('cypress'); + +module.exports = defineConfig({ + includeShadowDom: true, + defaultCommandTimeout: 60000, + execTimeout: 60000, + taskTimeout: 60000, + pageLoadTimeout: 10000, + requestTimeout: 10000, + responseTimeout: 10000, + fixturesFolder: 'fixtures', + chromeWebSecurity: false, + viewportWidth: 1500, + viewportHeight: 1500, + video: true, + videoCompression: false, + screenshotsFolder: process?.env?.ARTIFACTS + ? `${process.env?.ARTIFACTS}/screenshots` + : 'cypress/screenshots', + videosFolder: process?.env?.ARTIFACTS + ? `${process.env?.ARTIFACTS}/videos` + : 'cypress/videos', + experimentalInteractiveRunEvents: true, + numTestsKeptInMemory: 0, + e2e: { + testIsolation: false, + experimentalRunAllSpecs: true, + setupNodeEvents(on, config) { + return require('./plugins')(on, config); + }, + specPattern: [ + 'tests/**/*.spec.js', + ], + supportFile: 'support/index.js', + }, +}); diff --git a/tests/ui/fixtures/.gitignore b/tests/ui/fixtures/.gitignore new file mode 100644 index 000000000..a6e080a56 --- /dev/null +++ b/tests/ui/fixtures/.gitignore @@ -0,0 +1,3 @@ +# As we currently have no fixtures and this folder is only used as a source for the kubeconfig, we add a dummy gitignore file +# so that it is committed to git +kubeconfig.yaml \ No newline at end of file diff --git a/tests/ui/package-lock.json b/tests/ui/package-lock.json new file mode 100644 index 000000000..19a656a0b --- /dev/null +++ b/tests/ui/package-lock.json @@ -0,0 +1,3229 @@ +{ + "name": "ui-tests", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "ui-tests", + "devDependencies": { + "cypress-file-upload": "^5.0.8", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "cypress": "^12.3.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cypress/request": { + "version": "2.88.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", + "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", + "devOptional": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "devOptional": true, + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "devOptional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@types/node": { + "version": "14.18.36", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", + "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==", + "devOptional": true + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "devOptional": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "devOptional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "devOptional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "devOptional": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "devOptional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "devOptional": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "devOptional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "devOptional": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "devOptional": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "devOptional": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "devOptional": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "devOptional": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "devOptional": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "devOptional": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "devOptional": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "devOptional": true, + "engines": { + "node": "*" + } + }, + "node_modules/cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "devOptional": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "devOptional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "devOptional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ci-info": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "devOptional": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "devOptional": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "devOptional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "devOptional": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "devOptional": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "devOptional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "devOptional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "devOptional": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "devOptional": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cypress": { + "version": "12.17.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.0.tgz", + "integrity": "sha512-nq0ug8Zrjq/2khHU1PTNxg+3/n1oqtmAFCxwQhS6QzkQ4mR6RLitX+cGIOuIMfnEbDAtVub0hZh661FOA16JxA==", + "devOptional": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^2.88.10", + "@cypress/xvfb": "^1.2.4", + "@types/node": "^14.14.31", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.6.0", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.0", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^14.0.0 || ^16.0.0 || >=18.0.0" + } + }, + "node_modules/cypress-file-upload": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz", + "integrity": "sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g==", + "dev": true, + "engines": { + "node": ">=8.2.1" + }, + "peerDependencies": { + "cypress": ">3.0.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "devOptional": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==", + "devOptional": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "devOptional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "devOptional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "devOptional": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "devOptional": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "devOptional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "devOptional": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "devOptional": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "devOptional": true + }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "devOptional": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "devOptional": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "devOptional": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "devOptional": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "devOptional": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "devOptional": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "devOptional": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "devOptional": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "devOptional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "devOptional": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "devOptional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "devOptional": true, + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "devOptional": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "devOptional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "devOptional": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "devOptional": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "devOptional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "devOptional": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "devOptional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "devOptional": true + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "devOptional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "devOptional": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "devOptional": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "devOptional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "devOptional": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "devOptional": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "devOptional": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "devOptional": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "devOptional": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "devOptional": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "devOptional": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "devOptional": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "devOptional": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "devOptional": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "devOptional": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "devOptional": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "devOptional": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "devOptional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "devOptional": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "devOptional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "devOptional": true + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "devOptional": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "devOptional": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "devOptional": true + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "devOptional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "devOptional": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "devOptional": true + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "devOptional": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "devOptional": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "devOptional": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "devOptional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "devOptional": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "devOptional": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "devOptional": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "devOptional": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "devOptional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rxjs": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "devOptional": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "devOptional": true + }, + "node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "devOptional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "devOptional": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "devOptional": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "devOptional": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "devOptional": true + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "devOptional": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "devOptional": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "devOptional": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "devOptional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "devOptional": true + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "devOptional": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "devOptional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "devOptional": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "devOptional": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + }, + "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true + }, + "@cypress/request": { + "version": "2.88.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", + "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", + "devOptional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + } + }, + "@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "devOptional": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "devOptional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@types/node": { + "version": "14.18.36", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", + "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==", + "devOptional": true + }, + "@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "devOptional": true + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "devOptional": true + }, + "@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "devOptional": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "devOptional": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "devOptional": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "devOptional": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "devOptional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "devOptional": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "devOptional": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "devOptional": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "devOptional": true + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "devOptional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "devOptional": true + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "devOptional": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "devOptional": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "devOptional": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "devOptional": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "devOptional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "devOptional": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "devOptional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "devOptional": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "devOptional": true + }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "devOptional": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "devOptional": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "devOptional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "devOptional": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "devOptional": true + }, + "ci-info": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "devOptional": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "devOptional": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "devOptional": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "devOptional": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "devOptional": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "devOptional": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "devOptional": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "devOptional": true + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "devOptional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "devOptional": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "devOptional": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "devOptional": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cypress": { + "version": "12.17.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.0.tgz", + "integrity": "sha512-nq0ug8Zrjq/2khHU1PTNxg+3/n1oqtmAFCxwQhS6QzkQ4mR6RLitX+cGIOuIMfnEbDAtVub0hZh661FOA16JxA==", + "devOptional": true, + "requires": { + "@cypress/request": "^2.88.10", + "@cypress/xvfb": "^1.2.4", + "@types/node": "^14.14.31", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.6.0", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.0", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + } + }, + "cypress-file-upload": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz", + "integrity": "sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g==", + "dev": true, + "requires": {} + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "devOptional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==", + "devOptional": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "devOptional": true, + "requires": { + "ms": "2.1.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "devOptional": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "devOptional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "devOptional": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "devOptional": true, + "requires": { + "once": "^1.4.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "devOptional": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "devOptional": true + }, + "eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "devOptional": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "devOptional": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "devOptional": true, + "requires": { + "pify": "^2.2.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "devOptional": true + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "devOptional": true, + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "devOptional": true + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "devOptional": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "devOptional": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "devOptional": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "devOptional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "devOptional": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "devOptional": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "devOptional": true, + "requires": { + "async": "^3.2.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "devOptional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "devOptional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "devOptional": true, + "requires": { + "ini": "2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "devOptional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "devOptional": true + }, + "http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "devOptional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "devOptional": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "devOptional": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "devOptional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "devOptional": true + }, + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "devOptional": true + }, + "is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "devOptional": true, + "requires": { + "ci-info": "^3.2.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "devOptional": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "devOptional": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "devOptional": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "devOptional": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "devOptional": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "devOptional": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "devOptional": true + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "devOptional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "devOptional": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "devOptional": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "devOptional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "devOptional": true + }, + "listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "devOptional": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "devOptional": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "devOptional": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "devOptional": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "devOptional": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "devOptional": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "devOptional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "devOptional": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "devOptional": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "devOptional": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "devOptional": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "devOptional": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "devOptional": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "devOptional": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "devOptional": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "devOptional": true + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "devOptional": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "devOptional": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "devOptional": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "devOptional": true + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "devOptional": true + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "devOptional": true + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "devOptional": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "devOptional": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "devOptional": true + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "devOptional": true + }, + "request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "devOptional": true, + "requires": { + "throttleit": "^1.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "devOptional": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "devOptional": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "devOptional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "devOptional": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "devOptional": true + }, + "semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "devOptional": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "devOptional": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "devOptional": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "devOptional": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "devOptional": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", + "devOptional": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "devOptional": true + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "devOptional": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "devOptional": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "devOptional": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "devOptional": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "devOptional": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "devOptional": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "devOptional": true + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "devOptional": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "devOptional": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "devOptional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "devOptional": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "devOptional": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/tests/ui/package.json b/tests/ui/package.json new file mode 100644 index 000000000..17d310288 --- /dev/null +++ b/tests/ui/package.json @@ -0,0 +1,18 @@ +{ + "name": "ui-tests", + "description": "UI tests for Kyma-Dashboard", + "scripts": { + "start": "npx cypress open", + "test": "cypress run --browser chrome", + "test:ci": "cypress run --browser chromium", + "start-dashboard": "docker run --rm -it -p 3001:3001 -e DOCKER_DESKTOP_CLUSTER=true --pid=host --name kyma-dashboard europe-docker.pkg.dev/kyma-project/prod/kyma-dashboard-local-prod:latest", + "start-k3d": "./scripts/k3d-local-dev.sh" + }, + "devDependencies": { + "cypress-file-upload": "^5.0.8", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "cypress": "^12.3.0" + } +} diff --git a/tests/ui/plugins/index.js b/tests/ui/plugins/index.js new file mode 100644 index 000000000..e44f693f8 --- /dev/null +++ b/tests/ui/plugins/index.js @@ -0,0 +1,18 @@ +const fs = require('fs'); + +module.exports = (on, config) => { + on('after:spec', (spec, results) => { + if (results && results.video) { + // Do we have failures for any retry attempts? + const failures = results.tests.some((test) => + test.attempts.some((attempt) => attempt.state === 'failed') + ) + if (!failures) { + // delete the video if the spec passed and no tests retried + fs.unlinkSync(results.video) + } + } + }); + + return config; +}; diff --git a/tests/ui/scripts/k3d-ci-kyma-dashboard-integration.sh b/tests/ui/scripts/k3d-ci-kyma-dashboard-integration.sh new file mode 100755 index 000000000..8719f385f --- /dev/null +++ b/tests/ui/scripts/k3d-ci-kyma-dashboard-integration.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +set -ex +export CYPRESS_DOMAIN=http://localhost:3001 +export DASHBOARD_IMAGE="europe-docker.pkg.dev/kyma-project/prod/kyma-dashboard-local-prod:latest" + +sudo apt-get update -y +sudo apt-get install -y gettext-base + +function deploy_k3d (){ +echo "Provisioning k3d cluster" +sudo k3d cluster create kyma --port 80:80@loadbalancer --port 443:443@loadbalancer --k3s-arg "--disable=traefik@server:0" + +export KUBECONFIG=$(k3d kubeconfig merge kyma) + +make create-kyma-system-ns + +echo "Apply istio" +make deploy +kubectl apply -f ./config/samples/operator_v1alpha2_istio.yaml + +echo "Apply gardener resources" +echo "Certificates" +kubectl apply -f https://raw.githubusercontent.com/gardener/cert-management/master/pkg/apis/cert/crds/cert.gardener.cloud_certificates.yaml +echo "DNS Providers" +kubectl apply -f https://raw.githubusercontent.com/gardener/external-dns-management/master/pkg/apis/dns/crds/dns.gardener.cloud_dnsproviders.yaml +echo "DNS Entries" +kubectl apply -f https://raw.githubusercontent.com/gardener/external-dns-management/master/pkg/apis/dns/crds/dns.gardener.cloud_dnsentries.yaml +echo "Issuers" +kubectl apply -f https://raw.githubusercontent.com/gardener/cert-management/master/pkg/apis/cert/crds/cert.gardener.cloud_issuers.yaml + +cp $KUBECONFIG tests/ui/fixtures/kubeconfig.yaml +} + +function build_and_run_busola() { +echo "Create k3d registry..." +k3d registry create registry.localhost --port=5000 + +echo "Running kyma-dashboard..." +docker run -d --rm --net=host --pid=host --name kyma-dashboard "$DASHBOARD_IMAGE" + +echo "Waiting for the server to be up..." +while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' "$CYPRESS_DOMAIN")" != "200" ]]; do sleep 5; done +sleep 10 +} + +echo 'Waiting for deploy_k3d_kyma and build_and_run_busola' +deploy_k3d +echo "First process finished" +build_and_run_busola +echo "Second process finished" + +cd tests/ui +npm ci && npm run "test:ci" diff --git a/tests/ui/scripts/k3d-local-dev.sh b/tests/ui/scripts/k3d-local-dev.sh new file mode 100755 index 000000000..cd7b232a3 --- /dev/null +++ b/tests/ui/scripts/k3d-local-dev.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -ex + +echo "Provisioning k3d cluster" +kyma provision k3d + +export KUBECONFIG=$(k3d kubeconfig merge kyma) + +echo "Apply istio" +make create-kyma-system-ns +kubectl apply -f https://github.com/kyma-project/istio/releases/latest/download/istio-manager.yaml +kubectl apply -f https://github.com/kyma-project/istio/releases/latest/download/istio-default-cr.yaml + +echo "Apply gardener resources" +echo "Certificates" +kubectl apply -f https://raw.githubusercontent.com/gardener/cert-management/master/pkg/apis/cert/crds/cert.gardener.cloud_certificates.yaml +echo "DNS Providers" +kubectl apply -f https://raw.githubusercontent.com/gardener/external-dns-management/master/pkg/apis/dns/crds/dns.gardener.cloud_dnsproviders.yaml +echo "DNS Entries" +kubectl apply -f https://raw.githubusercontent.com/gardener/external-dns-management/master/pkg/apis/dns/crds/dns.gardener.cloud_dnsentries.yaml +echo "Issuers" +kubectl apply -f https://raw.githubusercontent.com/gardener/cert-management/master/pkg/apis/cert/crds/cert.gardener.cloud_issuers.yaml + +cp $KUBECONFIG fixtures/kubeconfig.yaml + diff --git a/tests/ui/support/combobox.js b/tests/ui/support/combobox.js new file mode 100644 index 000000000..5ea6a9667 --- /dev/null +++ b/tests/ui/support/combobox.js @@ -0,0 +1,14 @@ +export function chooseComboboxOption(selector, optionText) { + cy.get(`ui5-combobox${selector}:visible`) + .find('input:visible') + .filterWithNoValue() + .click({ force: true }) + .type(optionText, { force: true }); + cy.wait(200); + cy.get('ui5-li:visible', { timeout: 10000 }) + .contains(optionText) + .find('li') + .click({ force: true }); + + return cy.end(); +} \ No newline at end of file diff --git a/tests/ui/support/exceptions.js b/tests/ui/support/exceptions.js new file mode 100644 index 000000000..713be885f --- /dev/null +++ b/tests/ui/support/exceptions.js @@ -0,0 +1,29 @@ +Cypress.Commands.add('handleExceptions', () => { + Cypress.on('uncaught:exception', err => { + Cypress.log(err); + if ( + err.message.includes('Unexpected usage') || + err.message.includes( + "Cannot read properties of undefined (reading 'uri')", + ) || + err.message.includes('ResizeObserver loop limit exceeded') || + err.message.includes('502 Bad Gateway') || + err.message.includes( + 'ResizeObserver loop completed with undelivered notifications', + ) || + err.message.includes( + "Cannot read properties of null (reading 'sendError')", + ) || + err.message.includes( + "Uncaught NetworkError: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at", + ) || + err.message.includes( + "Cannot read properties of undefined (reading 'category')", + ) || + err.message.includes( + "Cannot read properties of null (reading 'querySelector')", + ) + ) + return false; + }); +}); diff --git a/tests/ui/support/filter.js b/tests/ui/support/filter.js new file mode 100644 index 000000000..5e3a2f8cc --- /dev/null +++ b/tests/ui/support/filter.js @@ -0,0 +1,26 @@ +Cypress.Commands.add('filterWithNoValue', { prevSubject: true }, $elements => + $elements.filter((_, e) => !e.value), +); + +Cypress.Commands.add('inspectList', (resource, resourceName) => { + const resourceUrl = resource.replace(/\s/g, '').toLowerCase(); + cy.navigateBackTo(resourceUrl, resource); + + cy.get('ui5-button[aria-label="open-search"]:visible') + .click() + .get('ui5-combobox[placeholder="Search"]') + .find('input') + .click() + .type(resourceName); + + cy.contains(resourceName).should('be.visible'); +}); + +Cypress.Commands.add('navigateBackTo', (resourceUrl, resourceName) => { + cy.get('ui5-breadcrumbs') + .find(`ui5-link[href*=${resourceUrl}]`) + .should('contain.text', resourceName) + .find(`a[href*=${resourceUrl}]`) + .click({ force: true }); +}); + diff --git a/tests/ui/support/index.js b/tests/ui/support/index.js new file mode 100644 index 000000000..f04c3be2e --- /dev/null +++ b/tests/ui/support/index.js @@ -0,0 +1,8 @@ +import './exceptions'; +import './login'; +import './navigation'; +import './loadFile'; +import './views'; +import './random'; +import './filter'; + diff --git a/tests/ui/support/loadFile.js b/tests/ui/support/loadFile.js new file mode 100644 index 000000000..fe81a932b --- /dev/null +++ b/tests/ui/support/loadFile.js @@ -0,0 +1,43 @@ +import jsyaml from 'js-yaml'; + +export function loadFile(FILE_NAME, single = true) { + const load = single ? jsyaml.load : jsyaml.loadAll; + return new Promise(resolve => { + cy.fixture(FILE_NAME).then(fileContent => resolve(load(fileContent))); + }); +} + +function parseYamlToJs(content) { + let object = null; + try { + object = jsyaml.load(content); + } catch (e) { + const message = 'A jsyaml.load() call failed, attempting jsyaml.loadAll()'; + cy.log(e, message); + console.log(e, message); + } + if (!object) { + try { + object = jsyaml.loadAll(content); + } catch (e) { + cy.log(e); + console.log(e); + } + } + return object; +} + +async function loadFiles(...fileNames) { + const getAFileFromDisk = fileName => + new Promise(resolve => + cy.fixture(fileName).then(content => resolve(parseYamlToJs(content))), + ); + const filesContent = await Promise.all(fileNames.map(getAFileFromDisk)); + + return filesContent.flat(); +} + +Cypress.Commands.add('loadFiles', (...fileNames) => { + cy.log('Load Files'); + return cy.wrap(loadFiles(...fileNames)); +}); diff --git a/tests/ui/support/login.js b/tests/ui/support/login.js new file mode 100644 index 000000000..1d7a8e564 --- /dev/null +++ b/tests/ui/support/login.js @@ -0,0 +1,139 @@ +import config from '../config'; +import { loadFile } from './loadFile'; + +const NO_VALUE = 'NO_VALUE'; // must be something, OIDC server doesn't accept empty strings +const USERNAME = Cypress.env('OIDC_USER'); +const PASSWORD = Cypress.env('OIDC_PASS'); + +Cypress.Commands.add('loginAndSelectCluster', function(params) { + cy.handleExceptions(); + + if (!params?.disableClear) { + sessionStorage.clear(); + cy.clearCookies(); + cy.clearLocalStorage(); + } + + const defaults = { + fileName: 'kubeconfig.yaml', + expectedLocation: /overview$/, + storage: null, + staticToken: false, + }; + const { fileName, expectedLocation, storage, staticToken } = { + ...defaults, + ...params, + }; + + cy.wrap(loadFile('kubeconfig.yaml')).then(kubeconfig => { + if (kubeconfig.users?.[0]?.user?.exec?.args) { + // conditionally logs in to OIDC + const URLelement = kubeconfig.users[0].user.exec.args.find(el => + el.includes('oidc-issuer-url'), + ); + // kubeconfig should only specify a scheme and a domain without the "/ui/protected/profilemanagement" part , i.e, https://apskyxzcl.accounts400.ondemand.com + const OICD_URL = /oidc-issuer-url=(?(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}))/.exec( + URLelement, + )?.groups?.url; + + // validating the input + if (!(OICD_URL && USERNAME && PASSWORD)) { + cy.log( + 'Either OIDC url, username or password is missing. URL is obtained from kubeconfig\'s "--oidc-issuer-url" field. Credentials are provided through Cypress env variables.', + ); + } + cy.wrap(OICD_URL && USERNAME && PASSWORD).should('be.ok'); + + cy.request(OICD_URL).then(res => { + const cookies = res.headers?.['set-cookie']; + + const xsrfCookie = cookies?.find(el => el.includes('XSRF')); + const xsrfToken = xsrfCookie + ? /XSRF_COOKIE="?(?.*?)"?;/.exec(xsrfCookie)?.groups?.token + : NO_VALUE; + + const jSessionIdCookie = cookies?.find(el => el.includes('JSESSIONID')); + const jSessionIdToken = jSessionIdCookie + ? /JSESSIONID="?(?.*?)"?;/.exec(jSessionIdCookie)?.groups + ?.token + : NO_VALUE; + + const body = res.body; + const spId = + /spid=['"](?.*?)['"]/.exec(body)?.groups?.spid || NO_VALUE; + const authenticityToken = + /authenticity_token.{1,10}value="(?.*?)"/.exec(body)?.groups + ?.auth || NO_VALUE; + + cy.log('Sending OIDC auth request'); + // if a response has status different from 2xx or 3xx, test will fail + cy.request({ + log: true, + url: `${OICD_URL}/saml2/idp/sso`, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Cookie: `JSESSIONID=${jSessionIdToken}; XSRF_COOKIE="${xsrfToken}"`, + }, + body: { + utf8: '✓', + authenticity_token: authenticityToken, + xsrfProtection: xsrfToken, + method: 'GET', + idpSSOEndpoint: `${OICD_URL}/saml2/idp/sso`, + sp: 'sp.accounts.sap.com', + RelayState: `${OICD_URL}/ui/protected/profilemanagement`, + targetUrl: '', + sourceUrl: '', + org: '', + spId: spId, + spName: 'sp.accounts.sap.com', + mobileSSOToken: '', + tfaToken: '', + css: '', + passwordlessAuthnSelected: '', + j_username: USERNAME, + j_password: PASSWORD, + }, + }).then(res => { + // assuming cookies are set only for successful login attempts + if (!res.headers?.['set-cookie']) { + cy.log('Failed OIDC login attempt!!'); + } + cy.wrap(res.headers?.['set-cookie']).should('be.ok'); + }); + }); + } + + cy.visit(`${config.clusterAddress}/clusters`) + .get('ui5-button:visible') + .contains('Connect cluster') + .click(); + + cy.contains('Drag your file here or click to upload').attachFile(fileName, { + subjectType: 'drag-n-drop', + }); + + cy.contains('Next').click(); + + if (staticToken) { + cy.contains('Next').click(); + } + + if (storage) { + cy.contains(storage) + .parent('ui5-radio-button') + .click(); + } + + cy.get(`[aria-label="last-step"]:visible`) + .contains('Connect cluster') + .click({ force: true }); + + cy.url().should('match', expectedLocation); + + if (expectedLocation == /overview$/) { + cy.contains('ui5-title', 'Cluster Details').should('be.visible'); + } + }); +}); diff --git a/tests/ui/support/navigation.js b/tests/ui/support/navigation.js new file mode 100644 index 000000000..5f76bd707 --- /dev/null +++ b/tests/ui/support/navigation.js @@ -0,0 +1,20 @@ +Cypress.Commands.add('navigateTo', (leftNav, resource) => { + // To check and probably remove after cypress bump + cy.wait(500); + + cy.getLeftNav() + .contains(leftNav) + .should('be.visible'); + + cy.getLeftNav() + .contains(leftNav) + .click(); + + cy.getLeftNav() + .contains(resource) + .click(); +}); + +Cypress.Commands.add('getLeftNav', () => { + return cy.get('aside', { timeout: 10000 }); +}); \ No newline at end of file diff --git a/tests/ui/support/random.js b/tests/ui/support/random.js new file mode 100644 index 000000000..e4674bd56 --- /dev/null +++ b/tests/ui/support/random.js @@ -0,0 +1,8 @@ +export function generateNamespaceName() { + return generateRandomName("a-busola-test"); +} + +export function generateRandomName(name) { + const random = Math.floor(Math.random() * 9999) + 1000; + return `${name}-${random}`; +} \ No newline at end of file diff --git a/tests/ui/support/views/index.js b/tests/ui/support/views/index.js new file mode 100644 index 000000000..a127ac19e --- /dev/null +++ b/tests/ui/support/views/index.js @@ -0,0 +1,3 @@ +import './namespace'; +import './service'; + diff --git a/tests/ui/support/views/namespace.js b/tests/ui/support/views/namespace.js new file mode 100644 index 000000000..42271899c --- /dev/null +++ b/tests/ui/support/views/namespace.js @@ -0,0 +1,37 @@ +Cypress.Commands.add('createNamespace', (namespaceName) => { + // Go to the details of namespace + cy.getLeftNav() + .contains('Namespaces') + .click(); + + cy.contains('ui5-button', 'Create Namespace').click(); + + cy.get('ui5-input[aria-label="Namespace name"]') + .find('input') + .type(namespaceName, { force: true }); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); +}); + +Cypress.Commands.add('deleteNamespace', (namespaceName) => { + cy.getLeftNav() + .contains('Namespaces', { includeShadowDom: true }) + .click(); + + cy.get('ui5-button[aria-label="open-search"]:visible') + .click() + .get('ui5-combobox[placeholder="Search"]') + .find('input') + .click() + .type(namespaceName); + + cy.get('ui5-table-row [aria-label="Delete"]').click({ force: true }); + + cy.contains(`delete Namespace ${namespaceName}`); + cy.get(`[header-text="Delete Namespace"]`) + .find('[data-testid="delete-confirmation"]') + .click(); +}); diff --git a/tests/ui/support/views/service.js b/tests/ui/support/views/service.js new file mode 100644 index 000000000..200a3c678 --- /dev/null +++ b/tests/ui/support/views/service.js @@ -0,0 +1,26 @@ +Cypress.Commands.add('createService', (serviceName) => { + cy.navigateTo('Discovery and Network', 'Services'); + + cy.contains('ui5-button', 'Create Service').click(); + + cy.get('ui5-input[aria-label="Service name"]') + .find('input') + .type(serviceName, { force: true }); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Add') + .should('be.visible') + .click(); + + cy.get('ui5-input[aria-label="Service name"]') + // Because the port name field has the same ariaLabel as the Service name field, we have + // to use the second element to fill in the port name. + .eq(1) + .find('input') + .type(serviceName, { force: true }); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); +}); diff --git a/tests/ui/tests/authorization-policies/test-authorization-policies.spec.js b/tests/ui/tests/authorization-policies/test-authorization-policies.spec.js new file mode 100644 index 000000000..2f0ef476e --- /dev/null +++ b/tests/ui/tests/authorization-policies/test-authorization-policies.spec.js @@ -0,0 +1,134 @@ +/// +import 'cypress-file-upload'; +import { chooseComboboxOption } from '../../support/combobox'; +import {generateNamespaceName, generateRandomName} from "../../support/random"; + +const AP_NAME = generateRandomName("test-ap") +const ACTION = 'AUDIT'; +const METHODS = 'GET'; +const PATHS = '/user/profile/*'; +const KEY = 'request.auth.claims[iss]'; +const VALUES = 'https://test-value.com'; + +context('Test Authorization Policies', () => { + const namespaceName = generateNamespaceName(); + + before(() => { + cy.loginAndSelectCluster(); + cy.createNamespace(namespaceName); + }); + + after(() => { + cy.loginAndSelectCluster(); + cy.deleteNamespace(namespaceName); + }); + + it('Create Authorization Policy', () => { + cy.navigateTo('Istio', 'Authorization Policies'); + + cy.contains('ui5-button', 'Create Authorization Policy').click(); + + cy.wait(500); + + // Action + chooseComboboxOption('[placeholder="Type or choose an option."]', ACTION); + + // Name + cy.get('ui5-dialog') + .find('[aria-label="AuthorizationPolicy name"]:visible') + .find('input') + .type(AP_NAME, { force: true }); + + // Rules + cy.get('[aria-label="expand Rules"]:visible', { log: false }) + .contains('Add') + .click(); + + // When + cy.get('[aria-label="expand When"]:visible', { log: false }) + .contains('Add') + .click(); + + cy.get('[data-testid="spec.rules.0.when.0.key"]:visible') + .find('input') + .type(KEY); + + cy.get('[aria-label="expand Values"]:visible', { log: false }).click(); + + cy.get('[data-testid="spec.rules.0.when.0.values.0"]:visible') + .find('input') + .type(VALUES); + + // To + cy.get('[aria-label="expand To"]:visible', { log: false }) + .contains('Add') + .click(); + + cy.get('[aria-label="expand Methods"]:visible', { log: false }).click(); + + cy.get('[data-testid="spec.rules.0.to.0.operation.methods.0"]:visible') + .find('input') + .type(METHODS); + + cy.get('[aria-label="expand Paths"]:visible', { log: false }).click(); + + cy.get('[data-testid="spec.rules.0.to.0.operation.paths.0"]:visible') + .find('input') + .type(PATHS); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); + }); + + it('Checking details', () => { + cy.contains(AP_NAME).should('be.visible'); + + cy.contains(ACTION).should('be.visible'); + + cy.contains('Matches all Pods in the Namespace').should('be.visible'); + + cy.contains('Rule #1 to when', { timeout: 10000 }).click(); + + cy.contains('To #1 methods paths', { timeout: 10000 }).click(); + + cy.contains(PATHS).should('be.visible'); + + cy.contains(KEY).should('be.visible'); + + cy.contains(VALUES).should('be.visible'); + + cy.contains('Operation').should('be.visible'); + + cy.contains(METHODS).should('be.visible'); + }); + + it('Edit and check changes', () => { + cy.contains('ui5-button', 'Edit').click(); + + cy.get('[placeholder="Enter key"]:visible', { log: false }) + .find('input') + .filterWithNoValue() + .type('sel', { force: true }); + + cy.get('[placeholder="Enter value"]:visible', { log: false }) + .find('input') + .filterWithNoValue() + .first() + .type('selector-value', { force: true }); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Update') + .should('be.visible') + .click(); + + cy.contains('sel=selector-value').should('be.visible'); + + cy.contains('Matches all Pods in the Namespace').should('not.exist'); + }); + + it('Inspect list', () => { + cy.inspectList('Authorization Policies', 'test-ap'); + }); +}); diff --git a/tests/ui/tests/destination-rules/test-destination-rules.spec.js b/tests/ui/tests/destination-rules/test-destination-rules.spec.js new file mode 100644 index 000000000..f2077ce44 --- /dev/null +++ b/tests/ui/tests/destination-rules/test-destination-rules.spec.js @@ -0,0 +1,86 @@ +/// +import 'cypress-file-upload'; +import {generateNamespaceName, generateRandomName} from "../../support/random"; + +const DR_NAME = generateRandomName('test-dr') +const HOST = 'ratings.prod.svc.cluster.local'; +const SELECTOR = 'selector=selector-value'; + +context('Test Destination Rules', () => { + const namespaceName = generateNamespaceName(); + + before(() => { + cy.loginAndSelectCluster(); + cy.createNamespace(namespaceName); + }); + + after(() => { + cy.loginAndSelectCluster(); + cy.deleteNamespace(namespaceName); + }); + + it('Create a Destination Rule', () => { + cy.navigateTo('Istio', 'Destination Rules'); + + cy.contains('ui5-button', 'Create Destination Rule').click(); + + cy.get('ui5-dialog') + .find('[aria-label="DestinationRule name"]:visible') + .find('input') + .type(DR_NAME, {force: true}); + + cy.get('[data-testid="spec.host"]:visible') + .find('input') + .click() + .type(HOST, {force: true}); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); + + cy.contains('ui5-title', DR_NAME).should('be.visible'); + }); + + it('Check Destination Rule details', () => { + cy.contains(HOST).should('be.visible'); + + cy.contains('Subsets').should('not.exist'); + + cy.contains('Workload Selector').should('not.exist'); + }); + + it('Edit Destination Rule', () => { + cy.contains('ui5-button', 'Edit').click(); + + cy.get('ui5-dialog') + .find('[aria-label="DestinationRule name"]:visible') + .find('input') + .should('have.attr', 'readonly'); + + // selector + cy.get('[placeholder="Enter key"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .type('selector', {force: true}); + + cy.get('[placeholder="Enter value"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .first() + .type('selector-value', {force: true}); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Update') + .should('be.visible') + .click(); + + // changed details + cy.contains(SELECTOR); + // After resolving: https://github.com/kyma-project/busola/issues/2088 we need to add checking loadBalancer value + }); + + it('Check the Destination Rule list', () => { + cy.inspectList('Destination Rules', DR_NAME); + }); +}); diff --git a/tests/ui/tests/gateway/test-gateways.spec.js b/tests/ui/tests/gateway/test-gateways.spec.js new file mode 100644 index 000000000..2a317d014 --- /dev/null +++ b/tests/ui/tests/gateway/test-gateways.spec.js @@ -0,0 +1,169 @@ +/// +import 'cypress-file-upload'; +import {chooseComboboxOption} from '../../support/combobox'; +import {generateNamespaceName, generateRandomName} from "../../support/random"; + +const GATEWAY_NAME = generateRandomName('test-gateway') + +const SERVER_NAME = GATEWAY_NAME + '-server'; +const PORT_NUMBER = 80; +const PORT_PROTOCOL = 'HTTP'; +const SELECTOR = 'selector=selector-value'; + +const KYMA_GATEWAY_CERTS = 'kyma-gateway-certs'; + +context('Test Gateways', () => { + const namespaceName = generateNamespaceName(); + const serviceName = generateRandomName("test-service"); + + before(() => { + cy.loginAndSelectCluster(); + cy.createNamespace(namespaceName); + cy.createService(serviceName); + }); + + after(() => { + cy.loginAndSelectCluster(); + cy.deleteNamespace(namespaceName); + }); + + it('Create Gateway', () => { + cy.navigateTo('Istio', 'Gateways'); + + cy.contains('ui5-button', 'Create Gateway').click(); + + // name + cy.get('ui5-dialog') + .find('[aria-label="Gateway name"]:visible') + .find('input') + .type(GATEWAY_NAME, {force: true}); + + // selector + cy.get('[placeholder="Enter key"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .type('selector', {force: true}); + + cy.get('[placeholder="Enter value"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .first() + .type('selector-value', {force: true}); + + // server + cy.get('[aria-label="expand Servers"]:visible', {log: false}) + .contains('Add') + .click(); + + cy.get('[data-testid="spec.servers.0.port.number"]:visible') + .find('input') + .type(PORT_NUMBER); + + chooseComboboxOption( + '[data-testid="spec.servers.0.port.protocol"]', + PORT_PROTOCOL, + ); + + cy.get('[aria-label^="Gateway name"]:visible', {log: false}) + .find('input') + .eq(1) + .type(SERVER_NAME, {force: true}); + + // hosts + cy.get('[aria-label="expand Hosts"]:visible', {log: false}).click(); + + cy.get('[placeholder="For example, *.api.mydomain.com"]:visible', { + log: false, + }) + .find('input') + .type('example.com'); + + cy.get('[placeholder="For example, *.api.mydomain.com"]:visible', { + log: false, + }) + .find('input') + .filterWithNoValue() + .type('*.example.com', {force: true}); + + // create + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); + }); + + it('Inspect details', () => { + cy.contains(GATEWAY_NAME); + cy.contains(SELECTOR); + // default selector + cy.contains('istio=ingressgateway'); + cy.contains(SERVER_NAME); + cy.contains(PORT_NUMBER); + // hosts + cy.contains('example.com'); + cy.contains('*.example.com'); + }); + + it('Edit Gateway', () => { + cy.contains('ui5-button', 'Edit').click(); + + cy.get('ui5-dialog') + .find('[aria-label="Gateway name"]:visible') + .find('input') + .should('have.attr', 'readonly'); + + cy.get('[aria-label="expand Servers"]:visible', { + log: false, + }).click(); + + // change server to HTTPS + cy.get(`ui5-combobox[data-testid="spec.servers.0.port.protocol"]`) + .find('input') + .click() + .clear() + .type('HTTPS'); + + cy.get('ui5-li:visible') + .contains('HTTPS') + .find('li') + .click({force: true}); + + cy.get('[data-testid="spec.servers.0.port.number"]:visible') + .find('input') + .click() + .clear() + .type('443'); + + cy.get('[aria-label="expand Port"]:visible', { + log: false, + }).click(); + + cy.get('[aria-label="expand TLS"]:visible', { + log: false, + }).click(); + + // secret + cy.get('[aria-label="Choose Secret"]:visible', { + log: false, + }) + .find('input') + .type(KYMA_GATEWAY_CERTS, {force: true}); + + chooseComboboxOption('[data-testid="spec.servers.0.tls.mode"]', 'SIMPLE'); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Update') + .should('be.visible') + .click(); + + // changed details + cy.contains('443'); + cy.contains('HTTPS'); + cy.contains(/simple/i); + cy.contains(KYMA_GATEWAY_CERTS); + }); + + it('Inspect list', () => { + cy.inspectList('Gateways', GATEWAY_NAME); + }); +}); diff --git a/tests/ui/tests/istio/test-virtual-services.spec.js b/tests/ui/tests/istio/test-virtual-services.spec.js new file mode 100644 index 000000000..7f5ad0948 --- /dev/null +++ b/tests/ui/tests/istio/test-virtual-services.spec.js @@ -0,0 +1,201 @@ +/// +import 'cypress-file-upload'; +import {generateNamespaceName} from "../../support/random"; + +const SERVICE_NAME = `test-virtual-service-${Math.floor(Math.random() * 9999) + +1000}`; +const MATCH_NAME = 'test-match'; +const URI_KEY = 'prefix'; +const URI_PREFIX = '/wpcatalog'; + +const HEADER_KEY = 'header'; +const HEADER_KEY1 = 'exact'; +const HEADER_VALUE = 'foo'; + +const REDIRECT_URI = '/v1/bookRatings'; +const REDIRECT_AUTHORITY = 'newratings.default.svc.cluster.local'; + +// to edit +const GATEWAY = + 'kyma-gateway-application-connector.kyma-system.svc.cluster.local'; +const HOST1 = 'host1.example.com'; +const HOST2 = 'host2.example.com'; + +context('Test Virtual Services', () => { + const namespaceName = generateNamespaceName(); + + before(() => { + cy.loginAndSelectCluster(); + cy.createNamespace(namespaceName); + cy.createService(SERVICE_NAME); + }); + + after(() => { + cy.loginAndSelectCluster(); + cy.deleteNamespace(namespaceName); + }); + + it('Create a Virtual Service', () => { + cy.navigateTo('Istio', 'Virtual Services'); + + cy.contains('ui5-button', 'Create Virtual Service').click(); + + // name + cy.get('ui5-dialog') + .find('[aria-label="VirtualService name"]:visible') + .find('input') + .click() + .type(SERVICE_NAME, {force: true}); + + // HTTP + cy.get('[aria-label="expand HTTP"]:visible', {log: false}) + .contains('Add') + .click(); + + // Matches + cy.get('[aria-label="expand Matches"]:visible', {log: false}) + .contains('Add') + .click(); + + cy.get('[data-testid="spec.http.0.match.0.name"]:visible') + .find('input') + .type(MATCH_NAME, {force: true}); + + // URIs + cy.get('[aria-label="expand Headers"]:visible', {log: false}).click(); + + cy.get('[aria-label="expand URI"]:visible', {log: false}).click(); + + cy.get('ui5-dialog') + .find('ui5-combobox[data-testid="select-dropdown"]') + .find('ui5-icon[accessible-name="Select Options"]:visible', { + log: false, + }) + .click(); + + cy.get('ui5-li:visible', {timeout: 10000}) + .contains(URI_KEY) + .find('li') + .click({force: true}); + + cy.get('[placeholder="Enter value"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .first() + .type(URI_PREFIX, {force: true}); + + cy.get('[aria-label="expand URI"]') + .first() + .click(); + + // Headers + cy.get('[aria-label="expand Headers"]').first().click(); + + cy.get('[placeholder="Enter key"]:visible', {log: false}) + .find('input') + .first() + .filterWithNoValue() + .type(HEADER_KEY, {force: true}); + + cy.get('ui5-dialog') + .find('ui5-combobox[data-testid="select-dropdown"]') + .find('ui5-icon[accessible-name="Select Options"]:visible', { + log: false, + }) + .eq(0) + .click(); + + cy.get('ui5-li:visible', {timeout: 10000}) + .contains(HEADER_KEY1) + .find('li') + .click({force: true}); + + cy.get('[placeholder="Enter value"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .first() + .type(HEADER_VALUE, {force: true}); + + cy.get('[aria-label="expand Headers"]').first().click(); + + // REDIRECT + cy.get('[aria-label="expand Redirect"]', {log: false}) + .first() + .click(); + + cy.get('[data-testid="spec.http.0.redirect.uri"]:visible') + .find('input') + .type(REDIRECT_URI, {force: true}); + + cy.get('[data-testid="spec.http.0.redirect.authority"]:visible') + .find('input') + .type(REDIRECT_AUTHORITY, {force: true}); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); + + cy.url().should('match', new RegExp(`/virtualservices/${SERVICE_NAME}$`)); + }); + + it('Inspect Virtual Service', () => { + cy.contains('ui5-title', SERVICE_NAME); + + cy.get('[data-testid="collapse-button-close"]', {timeout: 10000}).click(); + + cy.contains(MATCH_NAME); + cy.contains(`${URI_KEY}=${URI_PREFIX}`); + cy.contains(HEADER_KEY); + cy.contains(HEADER_KEY1); + cy.contains(HEADER_VALUE); + cy.contains(REDIRECT_URI); + cy.contains(REDIRECT_AUTHORITY); + }); + + it('Edit VS and check updates', () => { + cy.contains('ui5-button', 'Edit').click(); + + // Hosts + cy.get('[aria-label="expand Hosts"]:visible', { + log: false, + }).click(); + + cy.get('[data-testid="spec.hosts.0"]:visible') + .find('input') + .click() + .clear() + .type(HOST1, {force: true}); + + cy.get('[data-testid="spec.hosts.1"]:visible') + .find('input') + .click() + .clear() + .type(HOST2, {force: true}); + + // Gateways + cy.get('[aria-label="expand Gateways"]:visible', { + log: false, + }).click(); + + cy.get('[data-testid="spec.gateways.0"]:visible') + .find('input') + .click() + .clear() + .type(GATEWAY, {force: true}); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Update') + .should('be.visible') + .click(); + + // Changed details + cy.contains(HOST1); + cy.contains(HOST2); + cy.contains(GATEWAY); + }); + + it('Inspect service list', () => { + cy.inspectList('Virtual Services', SERVICE_NAME); + }); +}); diff --git a/tests/ui/tests/service-entries/test-service-entries.spec.js b/tests/ui/tests/service-entries/test-service-entries.spec.js new file mode 100644 index 000000000..40ef36ac3 --- /dev/null +++ b/tests/ui/tests/service-entries/test-service-entries.spec.js @@ -0,0 +1,92 @@ +/// +import 'cypress-file-upload'; +import {chooseComboboxOption} from '../../support/combobox'; +import {generateNamespaceName, generateRandomName} from "../../support/random"; + +const SE_NAME = generateRandomName('test') +const RESOLUTION = 'STATIC'; +const LOCATION = 'MESH_EXTERNAL'; +const HOST = 'test.com'; +const ADDRESS = '192.192.192.192/24'; +const WORKLOAD_SELECTOR_LABEL = 'test=selector-value'; + +context('Test Service Entries', () => { + const namespaceName = generateNamespaceName(); + + before(() => { + cy.loginAndSelectCluster(); + cy.createNamespace(namespaceName); + }); + + after(() => { + cy.loginAndSelectCluster(); + cy.deleteNamespace(namespaceName); + }); + + it('Create a Service Entry', () => { + cy.navigateTo('Istio', 'Service Entries'); + + cy.contains('ui5-button', 'Create Service Entry').click(); + + cy.contains('Advanced').click(); + + // Name + cy.get('ui5-dialog') + .find('[aria-label="ServiceEntry name"]:visible') + .find('input') + .click() + .type(SE_NAME, {force: true}); + + // Hosts + cy.get('[aria-label="expand Hosts"]:visible', {log: false}).click(); + + cy.get('[data-testid="spec.hosts.0"]:visible') + .find('input') + .type(HOST, {force: true}); + + chooseComboboxOption('[data-testid="spec.resolution"]', RESOLUTION); + + chooseComboboxOption('[data-testid="spec.location"]', LOCATION); + + cy.get('[aria-label="expand Addresses"]:visible', {log: false}).click(); + + cy.get('[placeholder="For example, 127.0.0.1"]:visible', { + log: false, + }) + .find('input') + .type(ADDRESS, {force: true}); + + cy.get('[placeholder="Enter key"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .type('test', {force: true}); + + cy.get('[placeholder="Enter value"]:visible', {log: false}) + .find('input') + .filterWithNoValue() + .first() + .type('selector-value', {force: true}); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); + + cy.contains('ui5-title', SE_NAME).should('be.visible'); + }); + + it('Check the Service Entry details', () => { + cy.get('#content-wrap') + .should('include.text', RESOLUTION) + .and('include.text', LOCATION) + .and('include.text', HOST) + .and('include.text', ADDRESS); + + cy.contains(WORKLOAD_SELECTOR_LABEL); + }); + + it('Check the Service Entries list', () => { + cy.inspectList('Service Entries', SE_NAME); + cy.contains(RESOLUTION); + }); +}); diff --git a/tests/ui/tests/sidecars/test-sidecars.spec.js b/tests/ui/tests/sidecars/test-sidecars.spec.js new file mode 100644 index 000000000..05ef3248d --- /dev/null +++ b/tests/ui/tests/sidecars/test-sidecars.spec.js @@ -0,0 +1,128 @@ +/// +import 'cypress-file-upload'; +import {chooseComboboxOption} from '../../support/combobox'; +import {generateNamespaceName, generateRandomName} from "../../support/random"; + +const SIDECAR_NAME = generateRandomName('test') + +const PORT_NUMBER = '81'; +const EGRESS_NAME = 'egresshttp'; +const IGRES_NAME = 'somename'; +const PORT_PROTOCOL = 'HTTP'; +const EGRESS_HOST = 'testhost/*'; +const DEFAULT_ENDPOINT = '127.0.0.1:8080'; + +context('Test Sidecars', () => { + const namespaceName = generateNamespaceName(); + + before(() => { + cy.loginAndSelectCluster(); + cy.createNamespace(namespaceName); + }); + + after(() => { + cy.loginAndSelectCluster(); + cy.deleteNamespace(namespaceName); + }); + + it('Create a Sidecar', () => { + cy.navigateTo('Istio', 'Sidecars'); + + cy.contains('ui5-button', 'Create Sidecar').click(); + + // Name + cy.get('ui5-dialog') + .find('[aria-label="Sidecar name"]:visible') + .find('input') + .click() + .type(SIDECAR_NAME, {force: true}); + + // Egress + cy.get('[aria-label="expand Egress"]:visible', {log: false}) + .contains('Add') + .click(); + + cy.get('[aria-label="expand Port"]:visible', {log: false}).click(); + + cy.get('[placeholder="Enter the port number"]:visible', { + log: false, + }) + .find('input') + .type(PORT_NUMBER, {force: true}); + + cy.get('ui5-dialog') + .find('[aria-label="Sidecar name"]:visible') + .find('input') + .filterWithNoValue() + .click() + .type(EGRESS_NAME, {force: true}); + + chooseComboboxOption( + '[data-testid="spec.egress.0.port.protocol"]', + PORT_PROTOCOL, + ); + + cy.get('[aria-label="expand Hosts"]:visible', {log: false}).click(); + + cy.get('[placeholder="For example, *.api.mydomain.com"]:visible', { + log: false, + }) + .find('input') + .type(EGRESS_HOST, {force: true}); + + cy.get('[aria-label="expand Egress"]:visible', {log: false}) + .first() + .click(); + + // Ingress + cy.get('[aria-label="expand Ingress"]:visible', {log: false}) + .contains('Add') + .click(); + + cy.get('[aria-label="expand Port"]:visible', {log: false}).click(); + + cy.get('[placeholder="Enter the port number"]:visible', { + log: false, + }) + .find('input') + .type(PORT_NUMBER, {force: true}); + + chooseComboboxOption( + '[data-testid="spec.ingress.0.port.protocol"]', + PORT_PROTOCOL, + ); + + cy.get('ui5-dialog') + .find('[aria-label="Sidecar name"]:visible') + .find('input') + .filterWithNoValue() + .click() + .type(IGRES_NAME, {force: true}); + + cy.get('[placeholder="For example, 127.0.0.1:PORT"]:visible', { + log: false, + }) + .find('input') + .type(DEFAULT_ENDPOINT, {force: true}); + + cy.get('ui5-dialog') + .contains('ui5-button', 'Create') + .should('be.visible') + .click(); + + cy.contains('ui5-title', SIDECAR_NAME).should('be.visible'); + }); + + it('Check the Sidecar details', () => { + cy.contains(PORT_NUMBER); + cy.contains(EGRESS_NAME); + cy.contains(IGRES_NAME); + cy.contains(PORT_PROTOCOL); + cy.contains(EGRESS_HOST); + cy.contains(DEFAULT_ENDPOINT); + }); + + it('Check the Sidecars list', () => { + cy.inspectList('Sidecars', SIDECAR_NAME); + }); +});