diff --git a/.drone.yml b/.drone.yml index 91b021398d2..1f9291533d2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -488,24 +488,26 @@ steps: token: from_secret: drone_token - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all - - /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64 + - go run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64 -a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu -a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7 - -a docker:grafana:linux/arm/v7:ubuntu --go-version=1.24.4 --yarn-cache=$$YARN_CACHE_FOLDER - --build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3 - --tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{ - .version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD - > packages.txt + -a docker:grafana:linux/arm/v7:ubuntu --yarn-cache=$$YARN_CACHE_FOLDER --build-id=$$DRONE_BUILD_NUMBER + --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3 --tag-format='{{ .version_base + }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{ .version_base }}-{{ .buildID + }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD > packages.txt - find ./dist -name '*docker*.tar.gz' -type f | xargs -n1 docker load -i depends_on: - yarn-install environment: _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: from_secret: dagger_token - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-package pull: always volumes: @@ -1772,24 +1774,26 @@ steps: image: node:22.11.0-alpine name: build-frontend-packages - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all - - /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64 + - go run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64 -a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu -a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7 - -a docker:grafana:linux/arm/v7:ubuntu --go-version=1.24.4 --yarn-cache=$$YARN_CACHE_FOLDER - --build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3 - --tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{ - .version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD - > packages.txt + -a docker:grafana:linux/arm/v7:ubuntu --yarn-cache=$$YARN_CACHE_FOLDER --build-id=$$DRONE_BUILD_NUMBER + --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3 --tag-format='{{ .version_base + }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{ .version_base }}-{{ .buildID + }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD > packages.txt - find ./dist -name '*docker*.tar.gz' -type f | xargs -n1 docker load -i depends_on: - update-package-json-version environment: _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: from_secret: dagger_token - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-package pull: always volumes: @@ -3626,9 +3630,12 @@ platform: services: [] steps: - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - export GRAFANA_DIR=$$(pwd) - export GITHUB_TOKEN=$(cat /github-app/token) - - cd /src && ./scripts/drone_build_main.sh + - ./pkg/build/daggerbuild/scripts/drone_build_main.sh environment: _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: from_secret: dagger_token @@ -3647,7 +3654,6 @@ steps: from_secret: grafana_api_key GCP_KEY_BASE64: from_secret: gcp_key_base64 - GO_VERSION: 1.24.4 GPG_PASSPHRASE: from_secret: packages_gpg_passphrase GPG_PRIVATE_KEY: @@ -3659,7 +3665,7 @@ steps: STORYBOOK_DESTINATION: from_secret: rgm_storybook_destination UBUNTU_BASE: ubuntu:22.04 - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-build pull: always volumes: @@ -3701,9 +3707,12 @@ platform: services: [] steps: - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - export GRAFANA_DIR=$$(pwd) - export GITHUB_TOKEN=$(cat /github-app/token) - - cd /src && ./scripts/drone_build_tag_grafana.sh + - ./pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh environment: _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: from_secret: dagger_token @@ -3722,7 +3731,6 @@ steps: from_secret: grafana_api_key GCP_KEY_BASE64: from_secret: gcp_key_base64 - GO_VERSION: 1.24.4 GPG_PASSPHRASE: from_secret: packages_gpg_passphrase GPG_PRIVATE_KEY: @@ -3734,7 +3742,7 @@ steps: STORYBOOK_DESTINATION: from_secret: rgm_storybook_destination UBUNTU_BASE: ubuntu:22.04 - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-build pull: always volumes: @@ -3818,9 +3826,12 @@ platform: services: [] steps: - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - export GRAFANA_DIR=$$(pwd) - export GITHUB_TOKEN=$(cat /github-app/token) - - cd /src && ./scripts/drone_build_tag_grafana.sh + - ./pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh environment: _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: from_secret: dagger_token @@ -3839,7 +3850,6 @@ steps: from_secret: grafana_api_key GCP_KEY_BASE64: from_secret: gcp_key_base64 - GO_VERSION: 1.24.4 GPG_PASSPHRASE: from_secret: packages_gpg_passphrase GPG_PRIVATE_KEY: @@ -3851,7 +3861,7 @@ steps: STORYBOOK_DESTINATION: from_secret: rgm_storybook_destination UBUNTU_BASE: ubuntu:22.04 - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-build pull: always volumes: @@ -4055,9 +4065,12 @@ platform: services: [] steps: - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - export GRAFANA_DIR=$$(pwd) - export GITHUB_TOKEN=$(cat /github-app/token) - - cd /src && ./scripts/drone_build_nightly_grafana.sh + - ./pkg/build/daggerbuild/scripts/drone_build_nightly_grafana.sh environment: _EXPERIMENTAL_DAGGER_CLOUD_TOKEN: from_secret: dagger_token @@ -4076,7 +4089,6 @@ steps: from_secret: grafana_api_key GCP_KEY_BASE64: from_secret: gcp_key_base64 - GO_VERSION: 1.24.4 GPG_PASSPHRASE: from_secret: packages_gpg_passphrase GPG_PRIVATE_KEY: @@ -4088,7 +4100,7 @@ steps: STORYBOOK_DESTINATION: from_secret: rgm_storybook_destination UBUNTU_BASE: ubuntu:22.04 - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-build pull: always volumes: @@ -4197,9 +4209,12 @@ steps: image: google/cloud-sdk:alpine name: rgm-copy - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - export GRAFANA_DIR=$$(pwd) - export GITHUB_TOKEN=$(cat /github-app/token) - - cd /src && ./scripts/drone_publish_nightly_grafana.sh + - ./pkg/build/daggerbuild/scripts/drone_publish_nightly_grafana.sh depends_on: - rgm-copy environment: @@ -4220,7 +4235,6 @@ steps: from_secret: grafana_api_key GCP_KEY_BASE64: from_secret: gcp_key_base64 - GO_VERSION: 1.24.4 GPG_PASSPHRASE: from_secret: packages_gpg_passphrase GPG_PRIVATE_KEY: @@ -4232,7 +4246,7 @@ steps: STORYBOOK_DESTINATION: from_secret: rgm_storybook_destination UBUNTU_BASE: ubuntu:22.04 - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-publish pull: always volumes: @@ -4324,10 +4338,12 @@ steps: - name: github-app path: /github-app - commands: + - wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz + | tar zx -C /bin + - apk add docker - export GITHUB_TOKEN=$(cat /github-app/token) - - dagger run --silent /src/grafana-build artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF} + - dagger run --silent ./pkg/build/cmd artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF} --enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --version=$${VERSION} - --go-version=1.24.4 depends_on: - github-app-generate-token environment: @@ -4348,7 +4364,6 @@ steps: from_secret: grafana_api_key GCP_KEY_BASE64: from_secret: gcp_key_base64 - GO_VERSION: 1.24.4 GPG_PASSPHRASE: from_secret: packages_gpg_passphrase GPG_PRIVATE_KEY: @@ -4360,7 +4375,7 @@ steps: STORYBOOK_DESTINATION: from_secret: rgm_storybook_destination UBUNTU_BASE: ubuntu:22.04 - image: grafana/grafana-build:main + image: golang:1.24.4-alpine name: rgm-build pull: always volumes: @@ -5190,6 +5205,6 @@ kind: secret name: gcr_credentials --- kind: signature -hmac: bcd4bde155138cc6ddd9e501f98b6a882cca14aa27a114b19470bc14e7406d59 +hmac: 37d46a35770a3cca3dd643b4cd4afbc1edea3eb6c5afc0501c9376cfc0ef2ecf ... diff --git a/.github/workflows/pr-e2e-tests.yml b/.github/workflows/pr-e2e-tests.yml index a8f2e1cd54a..a4a5a71b906 100644 --- a/.github/workflows/pr-e2e-tests.yml +++ b/.github/workflows/pr-e2e-tests.yml @@ -18,20 +18,15 @@ jobs: outputs: artifact: ${{ steps.artifact.outputs.artifact }} steps: - - uses: actions/checkout@v4 - with: - repository: 'grafana/grafana-build' - ref: 'main' - persist-credentials: false - uses: actions/checkout@v4 with: path: ./grafana - - run: echo "GRAFANA_GO_VERSION=$(grep "go 1." grafana/go.work | cut -d\ -f2)" >> "$GITHUB_ENV" + persist-credentials: false - uses: dagger/dagger-for-github@e47aba410ef9bb9ed81a4d2a97df31061e5e842e with: verb: run - args: go run ./cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir=grafana --go-version=${GRAFANA_GO_VERSION} > out.txt - - run: mv $(cat out.txt) grafana.tar.gz + args: go -C grafana run ./pkg/build/cmd artifacts -a targz:grafana:linux/amd64 --grafana-dir="${PWD}/grafana" > out.txt + - run: mv "$(cat out.txt)" grafana.tar.gz - run: echo "artifact=grafana-e2e-${{github.run_number}}" >> "$GITHUB_OUTPUT" id: artifact - uses: actions/upload-artifact@v4 diff --git a/apps/alerting/notifications/go.mod b/apps/alerting/notifications/go.mod index c7a9e142d25..d03c5f0fdeb 100644 --- a/apps/alerting/notifications/go.mod +++ b/apps/alerting/notifications/go.mod @@ -80,8 +80,11 @@ require ( golang.org/x/term v0.32.0 // indirect golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + golang.org/x/tools v0.33.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/apps/alerting/notifications/go.sum b/apps/alerting/notifications/go.sum index 2a50a2716eb..f1e3af44006 100644 --- a/apps/alerting/notifications/go.sum +++ b/apps/alerting/notifications/go.sum @@ -256,10 +256,10 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= diff --git a/apps/dashboard/go.mod b/apps/dashboard/go.mod index 3a063b451a9..987fb54a8f3 100644 --- a/apps/dashboard/go.mod +++ b/apps/dashboard/go.mod @@ -113,8 +113,8 @@ require ( golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.33.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect diff --git a/apps/dashboard/go.sum b/apps/dashboard/go.sum index 789fb0d66fa..04ff5573ed0 100644 --- a/apps/dashboard/go.sum +++ b/apps/dashboard/go.sum @@ -354,10 +354,10 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhS golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/apps/playlist/go.mod b/apps/playlist/go.mod index 4adee35ae7d..2a2f6bf3959 100644 --- a/apps/playlist/go.mod +++ b/apps/playlist/go.mod @@ -74,8 +74,8 @@ require ( golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.33.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/apps/playlist/go.sum b/apps/playlist/go.sum index 83f5547ec09..a9f4f33fcb5 100644 --- a/apps/playlist/go.sum +++ b/apps/playlist/go.sum @@ -189,10 +189,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/go.mod b/go.mod index 4a88fea5916..9ef80ec3e1b 100644 --- a/go.mod +++ b/go.mod @@ -558,8 +558,8 @@ require ( golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect diff --git a/go.sum b/go.sum index 109c7ef9589..9619d94ebfc 100644 --- a/go.sum +++ b/go.sum @@ -3348,15 +3348,15 @@ google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go. google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= diff --git a/go.work.sum b/go.work.sum index 1cc45c57834..206a6d93c1a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -597,6 +597,8 @@ github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAc github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/PuerkitoBio/goquery v1.10.2 h1:7fh2BdHcG6VFZsK7toXBT/Bh1z5Wmy8Q9MV9HqT2AM8= github.com/PuerkitoBio/goquery v1.10.2/go.mod h1:0guWGjcLu9AYC7C1GHnpysHy056u9aEkUHwhdnePMCU= +github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= +github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/RaveNoX/go-jsoncommentstrip v1.0.0 h1:t527LHHE3HmiHrq74QMpNPZpGCIJzTx+apLkMKt4HC0= @@ -627,9 +629,13 @@ github.com/alecthomas/participle/v2 v2.1.1 h1:hrjKESvSqGHzRb4yW1ciisFJ4p3MGYih6i github.com/alecthomas/participle/v2 v2.1.1/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= github.com/alexflint/go-arg v1.4.2 h1:lDWZAXxpAnZUq4qwb86p/3rIJJ2Li81EoMbTMujhVa0= github.com/alexflint/go-arg v1.4.2/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= +github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y= +github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae h1:AMzIhMUqU3jMrZiTuW0zkYeKlKDAFD+DG20IoO421/Y= github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= +github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= +github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= github.com/aliyun/aliyun-oss-go-sdk v2.2.10+incompatible h1:ROMcuN61gI8SfQ+AEMh4d7GZ3gwTZLIhPjtd05TQCG4= @@ -1591,6 +1597,7 @@ github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46r github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU= github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= @@ -1672,6 +1679,8 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k= github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= +github.com/vektah/gqlparser/v2 v2.5.26 h1:REqqFkO8+SOEgZHR/eHScjjVjGS8Nk3RMO/juiTobN4= +github.com/vektah/gqlparser/v2 v2.5.26/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= github.com/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw= github.com/vertica/vertica-sql-go v1.3.3/go.mod h1:jnn2GFuv+O2Jcjktb7zyc4Utlbu9YVqpHH/lx63+1M4= github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA= @@ -1910,6 +1919,7 @@ golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= @@ -1936,7 +1946,7 @@ golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -1956,6 +1966,7 @@ golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= @@ -1999,12 +2010,16 @@ golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= @@ -2117,6 +2132,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= diff --git a/pkg/aggregator/go.mod b/pkg/aggregator/go.mod index fd2f0934eb1..de4b203d0c4 100644 --- a/pkg/aggregator/go.mod +++ b/pkg/aggregator/go.mod @@ -150,8 +150,8 @@ require ( golang.org/x/tools v0.33.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/pkg/aggregator/go.sum b/pkg/aggregator/go.sum index 5f122e501a7..e07e85d586f 100644 --- a/pkg/aggregator/go.sum +++ b/pkg/aggregator/go.sum @@ -483,10 +483,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= diff --git a/pkg/apimachinery/go.mod b/pkg/apimachinery/go.mod index cff7dac7faa..1881a47e32b 100644 --- a/pkg/apimachinery/go.mod +++ b/pkg/apimachinery/go.mod @@ -41,7 +41,7 @@ require ( golang.org/x/sync v0.14.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.25.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/pkg/apimachinery/go.sum b/pkg/apimachinery/go.sum index eff3550b5bf..56dee2aab5e 100644 --- a/pkg/apimachinery/go.sum +++ b/pkg/apimachinery/go.sum @@ -147,8 +147,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/pkg/apis/secret/go.mod b/pkg/apis/secret/go.mod index cf353171870..10ea58a2473 100644 --- a/pkg/apis/secret/go.mod +++ b/pkg/apis/secret/go.mod @@ -87,8 +87,8 @@ require ( golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.33.0 // indirect google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect k8s.io/api v0.32.3 // indirect diff --git a/pkg/apis/secret/go.sum b/pkg/apis/secret/go.sum index 7f4111acb29..5285b362a83 100644 --- a/pkg/apis/secret/go.sum +++ b/pkg/apis/secret/go.sum @@ -292,10 +292,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= diff --git a/pkg/apiserver/go.mod b/pkg/apiserver/go.mod index b9b4f5f7a9b..001c298bda8 100644 --- a/pkg/apiserver/go.mod +++ b/pkg/apiserver/go.mod @@ -91,8 +91,8 @@ require ( golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.33.0 // indirect google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/pkg/apiserver/go.sum b/pkg/apiserver/go.sum index 53726e549ab..a92869dd9d0 100644 --- a/pkg/apiserver/go.sum +++ b/pkg/apiserver/go.sum @@ -300,10 +300,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= diff --git a/pkg/build/cmd/main.go b/pkg/build/cmd/main.go index 37957b15c0e..8b2152c42a5 100644 --- a/pkg/build/cmd/main.go +++ b/pkg/build/cmd/main.go @@ -4,8 +4,8 @@ import ( "log" "os" - "github.com/grafana/grafana/pkg/build" "github.com/grafana/grafana/pkg/build/cmd/util" + "github.com/grafana/grafana/pkg/build/daggerbuild/cmd" "github.com/urfave/cli/v2" ) @@ -17,15 +17,131 @@ func registerAppCommand(c *cli.Command) { } func main() { - app := cli.NewApp() - app.Commands = cli.Commands{ + // TODO change the registerer if the user is running using a JSON file etc + for k, v := range cmd.Artifacts { + if err := cmd.GlobalCLI.Register(k, v); err != nil { + panic(err) + } + } + + app := cmd.GlobalCLI.App() + artifactsCommand := cmd.GlobalCLI.ArtifactsCommand() + artifactsCommand.Subcommands = cli.Commands{ { - Name: "build", - Action: build.RunCmdCLI, + Name: "storybook", + Usage: "[ARCHIVED] Publish Grafana storybook", + Action: PublishStorybookAction, + Flags: []cli.Flag{ + &editionFlag, + &tagFlag, + &srcFlag, + &cli.StringFlag{ + Name: "storybook-bucket", + Value: "grafana-storybook", + Usage: "Google Cloud Storage bucket for storybooks", + }, + }, }, + { + Name: "static-assets", + Usage: "[ARCHIVED] Publish Grafana static assets", + Action: PublishStaticAssetsAction, + Flags: []cli.Flag{ + &editionFlag, + &securityFlag, + &securityDestBucketFlag, + &tagFlag, + &srcFlag, + &destFlag, + &cli.StringFlag{ + Name: "static-assets-bucket", + Value: "grafana-static-assets", + Usage: "Google Cloud Storage bucket for static assets", + }, + &cli.StringSliceFlag{ + Name: "static-asset-editions", + Usage: "All the editions of the static assets (or $STATIC_ASSET_EDITIONS)", + }, + }, + }, + { + Name: "packages", + Usage: "[ARCHIVED] Publish Grafana packages", + Action: PublishArtifactsAction, + Flags: []cli.Flag{ + &editionFlag, + &securityFlag, + &securityDestBucketFlag, + &tagFlag, + &srcFlag, + &destFlag, + &cli.StringSliceFlag{ + Name: "artifacts-editions", + Value: cli.NewStringSlice("oss", "enterprise", "enterprise2"), + Usage: "Editions for which the artifacts should be delivered (oss,enterprise,enterprise2), (or $ARTIFACTS_EDITIONS)", + }, + &cli.StringFlag{ + Name: "enterprise2-dest-bucket", + Value: "grafana-downloads-enterprise2", + Usage: "Google Cloud Storage bucket for published packages", + }, + &cli.StringFlag{ + Name: "enterprise2-security-prefix", + Usage: "Bucket path prefix for enterprise2 security releases (or $ENTERPRISE2_SECURITY_PREFIX)", + }, + }, + }, + { + Name: "docker", + Usage: "[ARCHIVED] Handle Grafana Docker images", + Subcommands: cli.Commands{ + { + Name: "fetch", + Usage: "Fetch Grafana Docker images", + ArgsUsage: "[version]", + Action: util.MaxArgCountWrapper(1, FetchImages), + Flags: []cli.Flag{ + &editionFlag, + }, + }, + }, + }, + { + Name: "npm", + Usage: "[ARCHIVED] Handle Grafana npm packages", + Subcommands: cli.Commands{ + { + Name: "release", + Usage: "Release npm packages", + ArgsUsage: "[version]", + Action: NpmReleaseAction, + Flags: []cli.Flag{ + &tagFlag, + }, + }, + { + Name: "store", + Usage: "Store npm packages tarball", + Action: NpmStoreAction, + Flags: []cli.Flag{ + &tagFlag, + }, + }, + { + Name: "retrieve", + Usage: "Retrieve npm packages tarball", + Action: NpmRetrieveAction, + Flags: []cli.Flag{ + &tagFlag, + }, + }, + }, + }, + } + app.Commands = append(app.Commands, []*cli.Command{ { Name: "e2e-tests", - Usage: "Run Grafana e2e tests", + Usage: "[ARCHIVED] Run Grafana e2e tests", Action: EndToEndTests, Flags: []cli.Flag{ &triesFlag, @@ -50,14 +166,9 @@ func main() { }, }, }, - { - Name: "whatsnew-checker", - Usage: "Checks whatsNewUrl in package.json for differences between the tag and the docs version", - Action: WhatsNewChecker, - }, { Name: "upload-cdn", - Usage: "Upload public/* to a cdn bucket", + Usage: "[ARCHIVED] Upload public/* to a cdn bucket", Action: UploadCDN, Flags: []cli.Flag{ &editionFlag, @@ -65,18 +176,18 @@ func main() { }, { Name: "publish-metrics", - Usage: "Publish a set of metrics from stdin", + Usage: "[ARCHIVED] Publish a set of metrics from stdin", ArgsUsage: "", Action: util.MaxArgCountWrapper(1, PublishMetrics), }, { Name: "verify-drone", - Usage: "Verify Drone configuration", + Usage: "[ARCHIVED] Verify Drone configuration", Action: VerifyDrone, }, { Name: "store-storybook", - Usage: "Stores storybook to GCS buckets", + Usage: "[ARCHIVED] Stores storybook to GCS buckets", Action: StoreStorybook, Flags: []cli.Flag{ &cli.StringFlag{ @@ -87,12 +198,12 @@ func main() { }, { Name: "verify-storybook", - Usage: "Integrity check for storybook build", + Usage: "[ARCHIVED] Integrity check for storybook build", Action: VerifyStorybook, }, { Name: "upload-packages", - Usage: "Upload Grafana packages", + Usage: "[ARCHIVED] Upload Grafana packages", Action: UploadPackages, Flags: []cli.Flag{ &jobsFlag, @@ -103,125 +214,10 @@ func main() { }, }, }, - { - Name: "artifacts", - Usage: "Handle Grafana artifacts", - Subcommands: cli.Commands{ - { - Name: "storybook", - Usage: "Publish Grafana storybook", - Action: PublishStorybookAction, - Flags: []cli.Flag{ - &editionFlag, - &tagFlag, - &srcFlag, - &cli.StringFlag{ - Name: "storybook-bucket", - Value: "grafana-storybook", - Usage: "Google Cloud Storage bucket for storybooks", - }, - }, - }, - { - Name: "static-assets", - Usage: "Publish Grafana static assets", - Action: PublishStaticAssetsAction, - Flags: []cli.Flag{ - &editionFlag, - &securityFlag, - &securityDestBucketFlag, - &tagFlag, - &srcFlag, - &destFlag, - &cli.StringFlag{ - Name: "static-assets-bucket", - Value: "grafana-static-assets", - Usage: "Google Cloud Storage bucket for static assets", - }, - &cli.StringSliceFlag{ - Name: "static-asset-editions", - Usage: "All the editions of the static assets (or $STATIC_ASSET_EDITIONS)", - }, - }, - }, - { - Name: "packages", - Usage: "Publish Grafana packages", - Action: PublishArtifactsAction, - Flags: []cli.Flag{ - &editionFlag, - &securityFlag, - &securityDestBucketFlag, - &tagFlag, - &srcFlag, - &destFlag, - &cli.StringSliceFlag{ - Name: "artifacts-editions", - Value: cli.NewStringSlice("oss", "enterprise", "enterprise2"), - Usage: "Editions for which the artifacts should be delivered (oss,enterprise,enterprise2), (or $ARTIFACTS_EDITIONS)", - }, - &cli.StringFlag{ - Name: "enterprise2-dest-bucket", - Value: "grafana-downloads-enterprise2", - Usage: "Google Cloud Storage bucket for published packages", - }, - &cli.StringFlag{ - Name: "enterprise2-security-prefix", - Usage: "Bucket path prefix for enterprise2 security releases (or $ENTERPRISE2_SECURITY_PREFIX)", - }, - }, - }, - { - Name: "docker", - Usage: "Handle Grafana Docker images", - Subcommands: cli.Commands{ - { - Name: "fetch", - Usage: "Fetch Grafana Docker images", - ArgsUsage: "[version]", - Action: util.MaxArgCountWrapper(1, FetchImages), - Flags: []cli.Flag{ - &editionFlag, - }, - }, - }, - }, - { - Name: "npm", - Usage: "Handle Grafana npm packages", - Subcommands: cli.Commands{ - { - Name: "release", - Usage: "Release npm packages", - ArgsUsage: "[version]", - Action: NpmReleaseAction, - Flags: []cli.Flag{ - &tagFlag, - }, - }, - { - Name: "store", - Usage: "Store npm packages tarball", - Action: NpmStoreAction, - Flags: []cli.Flag{ - &tagFlag, - }, - }, - { - Name: "retrieve", - Usage: "Retrieve npm packages tarball", - Action: NpmRetrieveAction, - Flags: []cli.Flag{ - &tagFlag, - }, - }, - }, - }, - }, - }, + artifactsCommand, { Name: "publish", - Usage: "Publish packages to Grafana com and repositories", + Usage: "[ARCHIVED] Publish packages to Grafana com and repositories", Subcommands: cli.Commands{ { Name: "grafana-com", @@ -292,7 +288,7 @@ func main() { }, }, }, - } + }...) app.Commands = append(app.Commands, additionalCommands...) diff --git a/pkg/build/cmd/whatsnewchecker.go b/pkg/build/cmd/whatsnewchecker.go deleted file mode 100644 index 8e74513c2eb..00000000000 --- a/pkg/build/cmd/whatsnewchecker.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/grafana/grafana/pkg/build/config" - "github.com/urfave/cli/v2" - "golang.org/x/mod/semver" -) - -const GrafanaDir = "." - -var whatsNewRegex = regexp.MustCompile(`^.*whats-new-in-(v\d*-[\d+]*)`) - -type PackageJSON struct { - Grafana Grafana `json:"grafana"` - Version string `json:"version"` -} - -type Grafana struct { - WhatsNewUrl string `json:"whatsNewUrl"` -} - -func WhatsNewChecker(c *cli.Context) error { - metadata, err := config.GenerateMetadata(c) - if err != nil { - return err - } - - if metadata.ReleaseMode.IsTest { - fmt.Println("test mode, skipping check") - return nil - } - if metadata.ReleaseMode.Mode != config.TagMode { - return fmt.Errorf("non-tag pipeline, exiting") - } - - tag := fmt.Sprintf("v%s", metadata.GrafanaVersion) - - if !semver.IsValid(tag) { - return fmt.Errorf("non-semver compatible version %s, exiting", tag) - } - - majorMinorDigits := strings.Replace(semver.MajorMinor(tag), ".", "-", 1) - - pkgJSONPath := filepath.Join(GrafanaDir, "package.json") - //nolint:gosec - pkgJSONB, err := os.ReadFile(pkgJSONPath) - if err != nil { - return fmt.Errorf("failed to read %q: %w", pkgJSONPath, err) - } - - var pkgObj PackageJSON - if err := json.Unmarshal(pkgJSONB, &pkgObj); err != nil { - return fmt.Errorf("failed decoding %q: %w", pkgJSONPath, err) - } - - whatsNewSplit := whatsNewRegex.FindStringSubmatch(pkgObj.Grafana.WhatsNewUrl) - whatsNewVersion := whatsNewSplit[1] - - if whatsNewVersion != majorMinorDigits { - return fmt.Errorf("whatsNewUrl in package.json needs to be updated to %s/", strings.Replace(whatsNewSplit[0], whatsNewVersion, majorMinorDigits, 1)) - } - - return nil -} diff --git a/pkg/build/cmd/whatsnewchecker_test.go b/pkg/build/cmd/whatsnewchecker_test.go deleted file mode 100644 index 91d75e7c0e7..00000000000 --- a/pkg/build/cmd/whatsnewchecker_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "encoding/json" - "flag" - "fmt" - "os" - "testing" - - "github.com/grafana/grafana/pkg/build/config" - "github.com/stretchr/testify/require" - "github.com/urfave/cli/v2" -) - -const ( - DroneBuildEvent = "DRONE_BUILD_EVENT" - DroneTag = "DRONE_TAG" - DroneSemverPrerelease = "DRONE_SEMVER_PRERELEASE" -) - -const whatsNewUrl = "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-" - -func TestWhatsNewChecker(t *testing.T) { - tests := []struct { - envMap map[string]string - packageJsonVersion string - name string - wantErr bool - errMsg string - }{ - {envMap: map[string]string{DroneBuildEvent: config.PullRequest}, packageJsonVersion: "", name: "non-tag event", wantErr: true, errMsg: "non-tag pipeline, exiting"}, - {envMap: map[string]string{DroneBuildEvent: config.Tag, DroneTag: "abcd123"}, packageJsonVersion: "", name: "non-semver compatible", wantErr: true, errMsg: "non-semver compatible version vabcd123, exiting"}, - {envMap: map[string]string{DroneBuildEvent: config.Tag, DroneTag: "v0.0.0", DroneSemverPrerelease: "test"}, packageJsonVersion: "v10-0", name: "skip check for test tags", wantErr: false}, - {envMap: map[string]string{DroneBuildEvent: config.Tag, DroneTag: "v10.0.0"}, packageJsonVersion: "v10-0", name: "package.json version matches tag", wantErr: false}, - {envMap: map[string]string{DroneBuildEvent: config.Tag, DroneTag: "v10.0.0"}, packageJsonVersion: "v9-5", name: "package.json doesn't match tag", wantErr: true, errMsg: "whatsNewUrl in package.json needs to be updated to https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v10-0/"}, - } - for _, tt := range tests { - app := cli.NewApp() - app.Version = "1.0.0" - context := cli.NewContext(app, &flag.FlagSet{}, nil) - t.Run(tt.name, func(t *testing.T) { - setUpEnv(t, tt.envMap) - err := createTempPackageJson(t, tt.packageJsonVersion) - require.NoError(t, err) - - err = WhatsNewChecker(context) - if tt.wantErr { - require.Error(t, err) - require.Equal(t, tt.errMsg, err.Error()) - } else { - require.NoError(t, err) - } - }) - } -} - -func setUpEnv(t *testing.T, envMap map[string]string) { - t.Helper() - - os.Clearenv() - t.Setenv("DRONE_BUILD_NUMBER", "12345") - t.Setenv("DRONE_COMMIT", "abcd12345") - for k, v := range envMap { - t.Setenv(k, v) - } -} - -func createTempPackageJson(t *testing.T, version string) error { - t.Helper() - - grafanaData := Grafana{WhatsNewUrl: fmt.Sprintf("%s%s/", whatsNewUrl, version)} - data := PackageJSON{Grafana: grafanaData, Version: "1.2.3"} - file, _ := json.MarshalIndent(data, "", " ") - - err := os.WriteFile("package.json", file, 0644) - require.NoError(t, err) - - t.Cleanup(func() { - err := os.RemoveAll("package.json") - require.NoError(t, err) - }) - return nil -} diff --git a/pkg/build/daggerbuild/.gitignore b/pkg/build/daggerbuild/.gitignore new file mode 100644 index 00000000000..3b7158a22f6 --- /dev/null +++ b/pkg/build/daggerbuild/.gitignore @@ -0,0 +1,8 @@ +.grafana/ +bin/ +*.tar.gz +*.txt +.idea/ +dist/ +grafana/ +.DS_Store diff --git a/pkg/build/daggerbuild/README.md b/pkg/build/daggerbuild/README.md new file mode 100644 index 00000000000..4d4b9cd4930 --- /dev/null +++ b/pkg/build/daggerbuild/README.md @@ -0,0 +1,4 @@ +# daggerbuild + +This folder was copied from the repository [grafana-build](https://github.com/grafana/grafana-build). If anything looks +out-of-place, then that's probably why. diff --git a/pkg/build/daggerbuild/arguments/docker.go b/pkg/build/daggerbuild/arguments/docker.go new file mode 100644 index 00000000000..0992f5986c0 --- /dev/null +++ b/pkg/build/daggerbuild/arguments/docker.go @@ -0,0 +1,102 @@ +package arguments + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/docker" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +var ( + DockerRegistryFlag = &cli.StringFlag{ + Name: "registry", + Usage: "Prefix the image name with the registry provided", + Value: "docker.io", + } + DockerOrgFlag = &cli.StringFlag{ + Name: "org", + Usage: "Overrides the organization of the images", + Value: "grafana", + } + AlpineImageFlag = &cli.StringFlag{ + Name: "alpine-base", + Usage: "The alpine image to use as the base image when building the Alpine version of the Grafana docker image", + Value: "alpine:latest", + } + UbuntuImageFlag = &cli.StringFlag{ + Name: "ubuntu-base", + Usage: "The Ubuntu image to use as the base image when building the Ubuntu version of the Grafana docker image", + Value: "ubuntu:latest", + } + TagFormatFlag = &cli.StringFlag{ + Name: "tag-format", + Usage: "Provide a go template for formatting the docker tag(s) for images with an Alpine base", + Value: docker.DefaultTagFormat, + } + UbuntuTagFormatFlag = &cli.StringFlag{ + Name: "ubuntu-tag-format", + Usage: "Provide a go template for formatting the docker tag(s) for images with a ubuntu base", + Value: docker.DefaultUbuntuTagFormat, + } + BoringTagFormatFlag = &cli.StringFlag{ + Name: "boring-tag-format", + Usage: "Provide a go template for formatting the docker tag(s) for the boringcrypto build of Grafana Enterprise", + Value: docker.DefaultBoringTagFormat, + } + + ProDockerRegistryFlag = &cli.StringFlag{ + Name: "pro-registry", + Usage: "Prefix the image name with the registry provided", + Value: "docker.io", + } + ProDockerOrgFlag = &cli.StringFlag{ + Name: "pro-org", + Usage: "Overrides the organization of the images", + Value: "grafana", + } + ProDockerRepoFlag = &cli.StringFlag{ + Name: "pro-repo", + Usage: "Overrides the docker repository of the built images", + Value: "grafana-pro", + } + + EntDockerRegistryFlag = &cli.StringFlag{ + Name: "docker-enterprise-registry", + Usage: "Prefix the image name with the registry provided", + Value: "docker.io", + } + EntDockerOrgFlag = &cli.StringFlag{ + Name: "docker-enterprise-org", + Usage: "Overrides the organization of the images", + Value: "grafana", + } + EntDockerRepoFlag = &cli.StringFlag{ + Name: "docker-enterprise-repo", + Usage: "Overrides the docker repository of the built images", + Value: "grafana-enterprise", + } + + HGTagFormatFlag = &cli.StringFlag{ + Name: "hg-tag-format", + Usage: "Provide a go template for formatting the docker tag(s) for Hosted Grafana images", + Value: docker.DefaultHGTagFormat, + } + + DockerRegistry = pipeline.NewStringFlagArgument(DockerRegistryFlag) + DockerOrg = pipeline.NewStringFlagArgument(DockerOrgFlag) + AlpineImage = pipeline.NewStringFlagArgument(AlpineImageFlag) + UbuntuImage = pipeline.NewStringFlagArgument(UbuntuImageFlag) + TagFormat = pipeline.NewStringFlagArgument(TagFormatFlag) + UbuntuTagFormat = pipeline.NewStringFlagArgument(UbuntuTagFormatFlag) + BoringTagFormat = pipeline.NewStringFlagArgument(BoringTagFormatFlag) + + // The docker registry for Grafana Pro is often different than the one for Grafana & Enterprise + ProDockerRegistry = pipeline.NewStringFlagArgument(ProDockerRegistryFlag) + ProDockerOrg = pipeline.NewStringFlagArgument(ProDockerOrgFlag) + ProDockerRepo = pipeline.NewStringFlagArgument(ProDockerRepoFlag) + + EntDockerRegistry = pipeline.NewStringFlagArgument(EntDockerRegistryFlag) + EntDockerOrg = pipeline.NewStringFlagArgument(EntDockerOrgFlag) + EntDockerRepo = pipeline.NewStringFlagArgument(EntDockerRepoFlag) + + HGTagFormat = pipeline.NewStringFlagArgument(HGTagFormatFlag) +) diff --git a/pkg/build/daggerbuild/arguments/docs.go b/pkg/build/daggerbuild/arguments/docs.go new file mode 100644 index 00000000000..0a79f807480 --- /dev/null +++ b/pkg/build/daggerbuild/arguments/docs.go @@ -0,0 +1,4 @@ +// Package arguments holds globally-defined arguments that are used throughout the program for shared data. +// A good candidate for an argument is a directory whose contents that may be used in the creation of multiple artifacts, like the Grafana source directory. +// Arguments are different than flags; a flag is a boolean argument in an artifact string which can set one or multiple preset values. +package arguments diff --git a/pkg/build/daggerbuild/arguments/flag_value_func.go b/pkg/build/daggerbuild/arguments/flag_value_func.go new file mode 100644 index 00000000000..057766709dc --- /dev/null +++ b/pkg/build/daggerbuild/arguments/flag_value_func.go @@ -0,0 +1 @@ +package arguments diff --git a/pkg/build/daggerbuild/arguments/go_build_cache.go b/pkg/build/daggerbuild/arguments/go_build_cache.go new file mode 100644 index 00000000000..f174d261789 --- /dev/null +++ b/pkg/build/daggerbuild/arguments/go_build_cache.go @@ -0,0 +1,53 @@ +package arguments + +import ( + "context" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/golang" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +var GoBuildCache = pipeline.Argument{ + Name: "go-cache-volume", + Description: "Mounted at GOCACHE when building Go backends", + ArgumentType: pipeline.ArgumentTypeCacheVolume, + Flags: []cli.Flag{}, + ValueFunc: func(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + return opts.Client.CacheVolume("go-build-cache"), nil + }, +} + +var GoModCache = pipeline.Argument{ + Name: "go-mod-volume", + Description: "Stores downloaded Go modules when building Go backends", + ArgumentType: pipeline.ArgumentTypeCacheVolume, + Flags: []cli.Flag{}, + ValueFunc: func(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + vol := opts.Client.CacheVolume("go-mod-cache") + goVersion, err := opts.State.String(ctx, GoVersion) + if err != nil { + return nil, err + } + src, err := opts.State.Directory(ctx, GrafanaDirectory) + if err != nil { + return nil, err + } + + c := golang.Container(opts.Client, opts.Platform, goVersion). + WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). + WithMountedCache("/go/pkg/mod", vol). + WithDirectory("/src", src, dagger.ContainerWithDirectoryOpts{ + Include: []string{"**/*.mod", "**/*.sum", "**/*.work"}, + }). + WithWorkdir("/src"). + WithExec([]string{"go", "mod", "download"}) + + if _, err := c.Sync(ctx); err != nil { + return nil, err + } + + return vol, nil + }, +} diff --git a/pkg/build/daggerbuild/arguments/golang.go b/pkg/build/daggerbuild/arguments/golang.go new file mode 100644 index 00000000000..b54b137f574 --- /dev/null +++ b/pkg/build/daggerbuild/arguments/golang.go @@ -0,0 +1,41 @@ +package arguments + +import ( + "context" + "strings" + + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +const ( + DefaultViceroyVersion = "v0.4.0" +) + +var GoVersion = pipeline.Argument{ + Name: "go-version", + Description: "The Go version to use when compiling Grafana", + ArgumentType: pipeline.ArgumentTypeString, + ValueFunc: func(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + src, err := opts.State.Directory(ctx, GrafanaDirectory) + if err != nil { + return nil, err + } + + stdout, err := opts.Client.Container().From("alpine"). + WithMountedFile("/src/go.mod", src.File("go.mod")). + WithWorkdir("/src"). + WithExec([]string{"/bin/sh", "-c", `grep '^go ' go.mod | awk '{print $2}'`}). + Stdout(ctx) + + return strings.TrimSpace(stdout), err + }, +} + +var ViceroyVersionFlag = &cli.StringFlag{ + Name: "viceroy-version", + Usage: "This flag sets the base image of the container used to build the Grafana backend binaries for non-Linux distributions", + Value: DefaultViceroyVersion, +} + +var ViceroyVersion = pipeline.NewStringFlagArgument(ViceroyVersionFlag) diff --git a/pkg/build/daggerbuild/arguments/gpg.go b/pkg/build/daggerbuild/arguments/gpg.go new file mode 100644 index 00000000000..1daf8292fce --- /dev/null +++ b/pkg/build/daggerbuild/arguments/gpg.go @@ -0,0 +1,28 @@ +package arguments + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +var ( + GPGPublicKeyFlag = &cli.StringFlag{ + Name: "gpg-public-key-base64", + Usage: "Provides a public key encoded in base64 for GPG signing", + EnvVars: []string{"GPG_PUBLIC_KEY"}, + } + GPGPrivateKeyFlag = &cli.StringFlag{ + Name: "gpg-private-key-base64", + Usage: "Provides a private key encoded in base64 for GPG signing", + EnvVars: []string{"GPG_PRIVATE_KEY"}, + } + GPGPassphraseFlag = &cli.StringFlag{ + Name: "gpg-passphrase", + Usage: "Provides a private key passphrase encoded in base64 for GPG signing", + EnvVars: []string{"GPG_PASSPHRASE"}, + } + + GPGPublicKey = pipeline.NewStringFlagArgument(GPGPublicKeyFlag) + GPGPrivateKey = pipeline.NewStringFlagArgument(GPGPrivateKeyFlag) + GPGPassphrase = pipeline.NewStringFlagArgument(GPGPassphraseFlag) +) diff --git a/pkg/build/daggerbuild/arguments/grafana.go b/pkg/build/daggerbuild/arguments/grafana.go new file mode 100644 index 00000000000..d7a4ebe599c --- /dev/null +++ b/pkg/build/daggerbuild/arguments/grafana.go @@ -0,0 +1,296 @@ +package arguments + +import ( + "context" + "fmt" + "log" + "log/slog" + "path" + "path/filepath" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/daggerutil" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/git" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +const BusyboxImage = "busybox:1.36" + +func InitializeEnterprise(d *dagger.Client, grafana *dagger.Directory, enterprise *dagger.Directory) *dagger.Directory { + hash := d.Container().From("alpine/git"). + WithDirectory("/src/grafana-enterprise", enterprise). + WithWorkdir("/src/grafana-enterprise"). + WithEntrypoint([]string{}). + WithExec([]string{"/bin/sh", "-c", "git rev-parse HEAD > .buildinfo.enterprise-commit"}). + File("/src/grafana-enterprise/.buildinfo.enterprise-commit") + + return d.Container().From(BusyboxImage). + WithDirectory("/src/grafana", grafana). + WithDirectory("/src/grafana-enterprise", enterprise). + WithWorkdir("/src/grafana-enterprise"). + WithFile("/src/grafana/.buildinfo.enterprise-commit", hash). + WithExec([]string{"/bin/sh", "build.sh"}). + WithExec([]string{"cp", "LICENSE", "../grafana"}). + Directory("/src/grafana") +} + +// GrafnaaOpts are populated by the 'GrafanaFlags' flags. +// These options define how to mount or clone the grafana/enterprise source code. +type GrafanaDirectoryOpts struct { + // GrafanaDir is the path to the Grafana source tree. + // If GrafanaDir is empty, then we're most likely cloning Grafana and using that as a directory. + GrafanaDir string + EnterpriseDir string + // GrafanaRepo will clone Grafana from a different repository when cloning Grafana. + GrafanaRepo string + EnterpriseRepo string + // GrafanaRef will checkout a specific tag, branch, or commit when cloning Grafana. + GrafanaRef string + EnterpriseRef string + // GitHubToken is used when cloning Grafana/Grafana Enterprise. + GitHubToken string + + PatchesRepo string + PatchesPath string + PatchesRef string +} + +func githubToken(ctx context.Context, token string) (string, error) { + // Since GrafanaDir was not provided, we must clone it. + ght := token + + // If GitHubToken was not set from flag + if ght != "" { + return ght, nil + } + + token, err := git.LookupGitHubToken(ctx) + if err != nil { + return "", err + } + if token == "" { + return "", fmt.Errorf("unable to acquire github token") + } + + return token, nil +} + +func GrafanaDirectoryOptsFromFlags(c cliutil.CLIContext) *GrafanaDirectoryOpts { + return &GrafanaDirectoryOpts{ + GrafanaRepo: c.String("grafana-repo"), + EnterpriseRepo: c.String("enterprise-repo"), + GrafanaDir: c.String("grafana-dir"), + EnterpriseDir: c.String("enterprise-dir"), + GrafanaRef: c.String("grafana-ref"), + EnterpriseRef: c.String("enterprise-ref"), + GitHubToken: c.String("github-token"), + PatchesRepo: c.String("patches-repo"), + PatchesPath: c.String("patches-path"), + PatchesRef: c.String("patches-ref"), + } +} + +func cloneOrMount(ctx context.Context, client *dagger.Client, localPath, repo, ref string, ght string) (*dagger.Directory, error) { + // If GrafanaDir was provided, then we can just use that one. + if path := localPath; path != "" { + slog.Info("Using local Grafana found", "path", path) + return daggerutil.HostDir(client, path) + } + + return git.CloneWithGitHubToken(client, ght, repo, ref) +} + +func applyPatches(ctx context.Context, client *dagger.Client, src *dagger.Directory, repo, patchesPath, ref, ght string) (*dagger.Directory, error) { + // Clone the patches repository on 'main' + dir, err := git.CloneWithGitHubToken(client, ght, repo, ref) + if err != nil { + return nil, fmt.Errorf("error cloning patches repository: %w", err) + } + + entries, err := dir.Entries(ctx, dagger.DirectoryEntriesOpts{ + Path: patchesPath, + }) + if err != nil { + return nil, fmt.Errorf("error listing entries in repository: %w", err) + } + + if len(entries) == 0 { + return nil, fmt.Errorf("no patches in the given path") + } + + container := client.Container().From(git.GitImage). + WithEntrypoint([]string{}). + WithMountedDirectory("/src", src). + WithMountedDirectory("/patches", dir). + WithWorkdir("/src"). + WithExec([]string{"git", "config", "--local", "user.name", "grafana"}). + WithExec([]string{"git", "config", "--local", "user.email", "engineering@grafana.com"}) + + for _, v := range entries { + if filepath.Ext(v) != ".patch" { + continue + } + + container = container.WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`git am --3way --ignore-whitespace --ignore-space-change --committer-date-is-author-date %s > /dev/null 2>&1`, path.Join("/patches", patchesPath, v))}) + } + + return container.Directory("/src"), nil +} + +func grafanaDirectory(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + o := GrafanaDirectoryOptsFromFlags(opts.CLIContext) + + ght, err := githubToken(ctx, o.GitHubToken) + if err != nil { + log.Println("No github token found:", err) + } + + src, err := cloneOrMount(ctx, opts.Client, o.GrafanaDir, o.GrafanaRepo, o.GrafanaRef, ght) + if err != nil { + return nil, err + } + + gitContainer := opts.Client.Container().From("alpine/git"). + WithWorkdir("/src"). + WithMountedDirectory("/src/.git", src.Directory(".git")). + WithEntrypoint([]string{}) + + commitFile := gitContainer. + WithExec([]string{"/bin/sh", "-c", "git rev-parse HEAD > .buildinfo.grafana-commit"}). + File("/src/.buildinfo.grafana-commit") + + branchFile := gitContainer. + WithExec([]string{"/bin/sh", "-c", "git rev-parse --abbrev-ref HEAD > .buildinfo.grafana-branch"}). + File("/src/.buildinfo.grafana-branch") + + src = src. + WithFile(".buildinfo.commit", commitFile). + WithFile(".buildinfo.branch", branchFile) + + if o.PatchesRepo != "" { + withPatches, err := applyPatches(ctx, opts.Client, src, o.PatchesRepo, o.PatchesPath, o.PatchesRef, ght) + if err != nil { + opts.Log.Debug("patch application skipped", "error", err) + } else { + // Only replace src when there was no error. + src = withPatches + } + } + + nodeVersion, err := frontend.NodeVersion(opts.Client, src).Stdout(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get node version from source code: %w", err) + } + + yarnCache, err := opts.State.CacheVolume(ctx, YarnCacheDirectory) + if err != nil { + return nil, err + } + + container := frontend.YarnInstall(opts.Client, src, nodeVersion, yarnCache, opts.Platform) + + if _, err := containers.ExitError(ctx, container); err != nil { + return nil, err + } + + return container.Directory("/src"), nil +} + +func enterpriseDirectory(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + // Get the Grafana directory... + o := GrafanaDirectoryOptsFromFlags(opts.CLIContext) + + grafanaDir, err := grafanaDirectory(ctx, opts) + if err != nil { + return nil, fmt.Errorf("error initializing grafana directory: %w", err) + } + + ght, err := githubToken(ctx, o.GitHubToken) + if err != nil { + return nil, nil + } + + src, err := cloneOrMount(ctx, opts.Client, o.EnterpriseDir, o.EnterpriseRepo, o.EnterpriseRef, ght) + if err != nil { + return nil, err + } + + return InitializeEnterprise(opts.Client, grafanaDir.(*dagger.Directory), src), nil +} + +var GrafanaDirectoryFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "grafana-dir", + Usage: "Local Grafana dir to use, instead of git clone", + Required: false, + }, + &cli.StringFlag{ + Name: "enterprise-dir", + Usage: "Local Grafana Enterprise dir to use, instead of git clone", + Required: false, + }, + &cli.StringFlag{ + Name: "grafana-repo", + Usage: "Grafana repo to clone, not valid if --grafana-dir is set", + Required: false, + Value: "https://github.com/grafana/grafana.git", + }, + &cli.StringFlag{ + Name: "enterprise-repo", + Usage: "Grafana Enterprise repo to clone, not valid if --grafana-dir is set", + Required: false, + Value: "https://github.com/grafana/grafana-enterprise.git", + }, + &cli.StringFlag{ + Name: "grafana-ref", + Usage: "Grafana ref to clone, not valid if --grafana-dir is set", + Required: false, + Value: "main", + }, + &cli.StringFlag{ + Name: "enterprise-ref", + Usage: "Grafana Enterprise ref to clone, not valid if --grafana-dir is set", + Required: false, + Value: "main", + }, + &cli.StringFlag{ + Name: "github-token", + Usage: "GitHub token to use for git cloning, by default will be pulled from GitHub", + Required: false, + }, + &cli.StringFlag{ + Name: "patches-repo", + Usage: "GitHub repository that contains git patches to apply to the Grafana source code. Must be an https git URL", + }, + &cli.StringFlag{ + Name: "patches-path", + Usage: "Path to folder containing '.patch' files to apply", + }, + &cli.StringFlag{ + Name: "patches-ref", + Usage: "Ref to checkout in the patches repository", + Value: "main", + }, +} + +// GrafanaDirectory will provide the valueFunc that initializes and returns a *dagger.Directory that has Grafana in it. +// Where possible, when cloning and no authentication options are provided, the valuefunc will try to use the configured github CLI for cloning. +var GrafanaDirectory = pipeline.Argument{ + Name: "grafana-dir", + Description: "The source tree of the Grafana repository", + Flags: GrafanaDirectoryFlags, + ValueFunc: grafanaDirectory, +} + +// EnterpriseDirectory will provide the valueFunc that initializes and returns a *dagger.Directory that has Grafana Enterprise initialized it. +// Where possible, when cloning and no authentication options are provided, the valuefunc will try to use the configured github CLI for cloning. +var EnterpriseDirectory = pipeline.Argument{ + Name: "enterprise-dir", + Description: "The source tree of Grafana Enterprise", + Flags: GrafanaDirectoryFlags, + ValueFunc: enterpriseDirectory, +} diff --git a/pkg/build/daggerbuild/arguments/hg_docker.go b/pkg/build/daggerbuild/arguments/hg_docker.go new file mode 100644 index 00000000000..b40c7a8285a --- /dev/null +++ b/pkg/build/daggerbuild/arguments/hg_docker.go @@ -0,0 +1,70 @@ +package arguments + +import ( + "context" + "fmt" + + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +var HGDirectoryFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "hosted-grafana-dir", + Usage: "Local clone of HG to use, instead of git cloning", + Required: false, + }, + &cli.StringFlag{ + Name: "hosted-grafana-repo", + Usage: "https `.git` repository to use for hosted-grafana", + Required: false, + Value: "https://github.com/grafana/hosted-grafana.git", + }, + &cli.StringFlag{ + Name: "hosted-grafana-ref", + Usage: "git ref to checkout", + Required: false, + Value: "main", + }, +} + +// HGDirectory will provide the valueFunc that initializes and returns a *dagger.Directory that has a repository that has the Grafana Pro/Enterprise docker image. +// Where possible, when cloning and no authentication options are provided, the valuefunc will try to use the configured github CLI for cloning. +var HGDirectory = pipeline.Argument{ + Name: "hg-dir", + Description: "The source tree of that has the Dockerfile for Grafana Pro/Enterprise", + Flags: HGDirectoryFlags, + ValueFunc: hgDirectory, +} + +type HGDirectoryOpts struct { + GitHubToken string + HGDir string + HGRepo string + HGRef string +} + +func HGDirectoryOptsFromFlags(c cliutil.CLIContext) *HGDirectoryOpts { + return &HGDirectoryOpts{ + GitHubToken: c.String("github-token"), + HGDir: c.String("hosted-grafana-dir"), + HGRepo: c.String("hosted-grafana-repo"), + HGRef: c.String("hosted-grafana-ref"), + } +} + +func hgDirectory(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + o := HGDirectoryOptsFromFlags(opts.CLIContext) + ght, err := githubToken(ctx, o.GitHubToken) + if err != nil { + return nil, fmt.Errorf("could not get GitHub token: %w", err) + } + + src, err := cloneOrMount(ctx, opts.Client, o.HGDir, o.HGRepo, o.HGRef, ght) + if err != nil { + return nil, err + } + + return src, nil +} diff --git a/pkg/build/daggerbuild/arguments/join.go b/pkg/build/daggerbuild/arguments/join.go new file mode 100644 index 00000000000..c62761015d6 --- /dev/null +++ b/pkg/build/daggerbuild/arguments/join.go @@ -0,0 +1,12 @@ +package arguments + +import "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + +func Join(f ...[]pipeline.Argument) []pipeline.Argument { + r := []pipeline.Argument{} + for _, v := range f { + r = append(r, v...) + } + + return r +} diff --git a/pkg/build/daggerbuild/arguments/packages.go b/pkg/build/daggerbuild/arguments/packages.go new file mode 100644 index 00000000000..2de625f226e --- /dev/null +++ b/pkg/build/daggerbuild/arguments/packages.go @@ -0,0 +1,69 @@ +package arguments + +import ( + "context" + "strings" + + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/grafana/grafana/pkg/build/daggerbuild/stringutil" + "github.com/urfave/cli/v2" +) + +var flagBuildID = &cli.StringFlag{ + Name: "build-id", + Usage: "Build ID to use in package names", + Value: "local", +} + +var BuildID = pipeline.Argument{ + Name: "build-id", + Description: "The grafana backend binaries ('grafana', 'grafana-cli', 'grafana-server') in a directory", + Flags: []cli.Flag{ + flagBuildID, + }, + ValueFunc: func(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + v := opts.CLIContext.String("build-id") + if v == "" { + v = stringutil.RandomString(8) + } + + return v, nil + }, +} + +var flagVersion = &cli.StringFlag{ + Name: "version", + Usage: "Explicit version number. If this is not set then one with will auto-detected based on the source repository", +} + +var Version = pipeline.Argument{ + Name: "version", + Description: "The version string that is shown in the UI, in the CLI, and in package metadata", + Flags: []cli.Flag{ + flagVersion, + }, + Requires: []pipeline.Argument{ + GrafanaDirectory, + }, + ValueFunc: func(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + v := opts.CLIContext.String("version") + if v != "" { + return v, nil + } + src, err := opts.State.Directory(ctx, GrafanaDirectory) + if err != nil { + return "", err + } + buildID, err := opts.State.String(ctx, BuildID) + if err != nil { + return "", err + } + version, err := containers.GetJSONValue(ctx, opts.Client, src, "package.json", "version") + if err != nil { + return "", err + } + + return strings.ReplaceAll(version, "pre", buildID), nil + }, +} diff --git a/pkg/build/daggerbuild/arguments/yarn.go b/pkg/build/daggerbuild/arguments/yarn.go new file mode 100644 index 00000000000..060697e2872 --- /dev/null +++ b/pkg/build/daggerbuild/arguments/yarn.go @@ -0,0 +1,54 @@ +package arguments + +import ( + "context" + "os" + + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" +) + +var YarnCacheDirFlag = &cli.StringFlag{ + Name: "yarn-cache-dir", + Aliases: []string{"yarn-cache"}, + Usage: "Path to the yarn cache directory to mount during 'yarn install' commands (if there is one)", + EnvVars: []string{"YARN_CACHE_FOLDER", "YARN_CACHE_DIR"}, + Value: "", +} + +var YarnCacheDirectory = pipeline.Argument{ + Name: "yarn-cache-dir", + Description: YarnCacheDirFlag.Usage, + ArgumentType: pipeline.ArgumentTypeCacheVolume, + Flags: []cli.Flag{ + YarnCacheDirFlag, + }, + ValueFunc: func(ctx context.Context, opts *pipeline.ArgumentOpts) (any, error) { + vol := opts.CLIContext.String(YarnCacheDirFlag.Name) + + // Prepopulate the cache with what's defined in YARN_CACHE_FOLDER + // or in the CLI + if val, ok := os.LookupEnv("YARN_CACHE_FOLDER"); ok { + vol = val + } + + cache := opts.Client.CacheVolume("yarn-cache-dir") + if vol == "" { + return cache, nil + } + + dir := opts.Client.Host().Directory(vol) + _, err := opts.Client.Container(). + From("alpine"). + WithMountedCache("/cache", cache). + WithMountedDirectory("/data", dir). + WithExec([]string{"/bin/sh", "-c", "cp -r /data/* /cache || return 0"}). + Sync(ctx) + + if err != nil { + return nil, err + } + + return cache, nil + }, +} diff --git a/pkg/build/daggerbuild/artifacts/action.go b/pkg/build/daggerbuild/artifacts/action.go new file mode 100644 index 00000000000..b60d84f0a3d --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/action.go @@ -0,0 +1,273 @@ +package artifacts + +import ( + "context" + "errors" + "fmt" + "log/slog" + "os" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/urfave/cli/v2" + "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" +) + +func Action(r Registerer, c *cli.Context) error { + // ArtifactStrings represent an artifact with a list of boolean options, like + // targz:linux/amd64:enterprise + artifactStrings := c.StringSlice("artifacts") + + logLevel := slog.LevelInfo + if c.Bool("verbose") { + logLevel = slog.LevelDebug + } + + var ( + ctx = c.Context + log = slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ + Level: logLevel, + })) + parallel = c.Int64("parallel") + destination = c.String("destination") + platform = dagger.Platform(c.String("platform")) + verify = c.Bool("verify") + checksum = c.Bool("checksum") + ) + + if len(artifactStrings) == 0 { + return errors.New("no artifacts specified. At least 1 artifact is required using the '--artifact' or '-a' flag") + } + + log.Debug("Connecting to dagger daemon...") + daggerOpts := []dagger.ClientOpt{} + if logLevel == slog.LevelDebug { + daggerOpts = append(daggerOpts, dagger.WithLogOutput(os.Stderr)) + } + client, err := dagger.Connect(ctx, daggerOpts...) + if err != nil { + return err + } + log.Debug("Connected to dagger daemon") + + var state pipeline.StateHandler = &pipeline.State{ + Log: log, + Client: client, + CLIContext: c, + Platform: platform, + } + + registered := r.Initializers() + + log.Debug("Generating artifacts from artifact strings...") + // Initialize the artifacts that were specified by the artifacts commands. + // These are specified by using artifact strings, or comma-delimited lists of flags. + artifacts, err := ArtifactsFromStrings(ctx, log, artifactStrings, registered, state) + if err != nil { + return err + } + log.Debug("Done generating artifact metadata") + + state = pipeline.StateWithLogger( + log.With("service", "state"), + state, + ) + + // The artifact store is responsible for storing built artifacts and issuing them to artifacts that use them as dependencies using the artifact's filename as the key. + store := pipeline.NewArtifactStore(log) + + opts := &pipeline.ArtifactContainerOpts{ + Client: client, + Log: log, + State: state, + Platform: platform, + Store: store, + } + + // Build each artifact and their dependencies, essentially constructing a dag using Dagger. + for i, v := range artifacts { + filename, err := v.Handler.Filename(ctx) + if err != nil { + return fmt.Errorf("error processing artifact string '%s': %w", artifactStrings[i], err) + } + log := log.With("filename", filename, "artifact", v.ArtifactString) + log.Info("Adding artifact to dag...") + if err := BuildArtifact(ctx, log, v, opts); err != nil { + return err + } + log.Info("Done adding artifact") + } + + wg := &errgroup.Group{} + sm := semaphore.NewWeighted(parallel) + log.Info("Exporting artifacts...") + // Export the files from the dag, causing the containers to trigger. + for _, v := range artifacts { + log := log.With("artifact", v.ArtifactString, "action", "export") + wg.Go(ExportArtifactFunc(ctx, client, sm, log, v, store, destination, checksum)) + } + if verify { + // Export the files from the dag, causing the containers to trigger. + for _, v := range artifacts { + log := log.With("artifact", v.ArtifactString, "action", "validate") + wg.Go(VerifyArtifactFunc(ctx, client, sm, log, v, store, destination)) + } + } + + return wg.Wait() +} + +func BuildArtifact(ctx context.Context, log *slog.Logger, a *pipeline.Artifact, opts *pipeline.ArtifactContainerOpts) error { + store := opts.Store + exists, err := store.Exists(ctx, a) + if err != nil { + return err + } + if exists { + return nil + } + + // populate the dependency list + dependencies, err := a.Handler.Dependencies(ctx) + if err != nil { + return err + } + + // Get the files / directories that the dependencies define, + // and store the result for re-use. + for _, v := range dependencies { + f, err := v.Handler.Filename(ctx) + if err != nil { + return err + } + log := log.With("artifact", v.ArtifactString, "filename", f) + if err := BuildArtifact(ctx, log, v, opts); err != nil { + return err + } + } + + switch a.Type { + case pipeline.ArtifactTypeDirectory: + dir, err := BuildArtifactDirectory(ctx, a, opts) + if err != nil { + return err + } + + return store.StoreDirectory(ctx, a, dir) + case pipeline.ArtifactTypeFile: + file, err := BuildArtifactFile(ctx, a, opts) + if err != nil { + return err + } + + return store.StoreFile(ctx, a, file) + } + + return nil +} + +func Command(r Registerer) func(c *cli.Context) error { + return func(c *cli.Context) error { + if err := Action(r, c); err != nil { + return cli.Exit(err, 1) + } + return nil + } +} + +func BuildArtifactFile(ctx context.Context, a *pipeline.Artifact, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + builder, err := a.Handler.Builder(ctx, opts) + if err != nil { + return nil, err + } + return a.Handler.BuildFile(ctx, builder, opts) +} + +func BuildArtifactDirectory(ctx context.Context, a *pipeline.Artifact, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + builder, err := a.Handler.Builder(ctx, opts) + if err != nil { + return nil, err + } + return a.Handler.BuildDir(ctx, builder, opts) +} + +func ExportArtifactFunc(ctx context.Context, d *dagger.Client, sm *semaphore.Weighted, log *slog.Logger, v *pipeline.Artifact, store pipeline.ArtifactStore, dst string, checksum bool) func() error { + return func() error { + log.Info("Started exporting artifact...") + + log.Info("Acquiring semaphore") + if err := sm.Acquire(ctx, 1); err != nil { + log.Info("Error acquiring semaphore", "error", err) + return err + } + log.Info("Acquired semaphore") + + defer sm.Release(1) + + filename, err := v.Handler.Filename(ctx) + if err != nil { + return fmt.Errorf("error processing artifact string '%s': %w", v.ArtifactString, err) + } + + log.Info("Exporting artifact") + paths, err := store.Export(ctx, d, v, dst, checksum) + if err != nil { + return fmt.Errorf("error exporting artifact '%s': %w", filename, err) + } + + for _, v := range paths { + if _, err := fmt.Fprintf(Stdout, "%s\n", v); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + } + + log.Info("Done exporting artifact") + + return nil + } +} + +func verifyArtifact(ctx context.Context, client *dagger.Client, v *pipeline.Artifact, store pipeline.ArtifactStore) error { + switch v.Type { + case pipeline.ArtifactTypeDirectory: + file, err := store.Directory(ctx, v) + if err != nil { + return err + } + + if err := v.Handler.VerifyDirectory(ctx, client, file); err != nil { + return err + } + case pipeline.ArtifactTypeFile: + file, err := store.File(ctx, v) + if err != nil { + return err + } + + if err := v.Handler.VerifyFile(ctx, client, file); err != nil { + return err + } + } + + return nil +} + +func VerifyArtifactFunc(ctx context.Context, d *dagger.Client, sm *semaphore.Weighted, log *slog.Logger, v *pipeline.Artifact, store pipeline.ArtifactStore, dst string) func() error { + return func() error { + log.Info("Started verifying artifact...") + + log.Info("Acquiring semaphore") + if err := sm.Acquire(ctx, 1); err != nil { + log.Info("Error acquiring semaphore", "error", err) + return err + } + log.Info("Acquired semaphore") + defer sm.Release(1) + + if err := verifyArtifact(ctx, d, v, store); err != nil { + return err + } + return nil + } +} diff --git a/pkg/build/daggerbuild/artifacts/backend.go b/pkg/build/daggerbuild/artifacts/backend.go new file mode 100644 index 00000000000..64d820bc86c --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/backend.go @@ -0,0 +1,246 @@ +package artifacts + +import ( + "context" + "log/slog" + "path/filepath" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + BackendArguments = []pipeline.Argument{ + arguments.GrafanaDirectory, + arguments.EnterpriseDirectory, + arguments.GoVersion, + arguments.ViceroyVersion, + } + + BackendFlags = flags.JoinFlags( + flags.PackageNameFlags, + flags.DistroFlags(), + ) +) + +var BackendInitializer = Initializer{ + InitializerFunc: NewBackendFromString, + Arguments: BackendArguments, +} + +type Backend struct { + // Name allows different backend compilations to be different even if all other factors are the same. + // For example, Grafana Enterprise, Grafana, and Grafana Pro may be built using the same options, + // but are fundamentally different because of the source code of the binary. + Name packages.Name + Src *dagger.Directory + Distribution backend.Distribution + BuildOpts *backend.BuildOpts + GoVersion string + ViceroyVersion string + + GoBuildCache *dagger.CacheVolume + GoModCache *dagger.CacheVolume + // Version is embedded in the binary at build-time + Version string +} + +func (b *Backend) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return backend.Builder( + opts.Client, + opts.Log, + b.Distribution, + b.BuildOpts, + opts.Platform, + b.Src, + b.GoVersion, + b.ViceroyVersion, + b.GoBuildCache, + b.GoModCache, + ) +} + +func (b *Backend) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return nil, nil +} + +func (b *Backend) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + panic("not implemented") // TODO: Implement +} + +func (b *Backend) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + f, err := b.Filename(ctx) + if err != nil { + return nil, err + } + + return backend.Build( + opts.Client, + builder, + b.Src, + b.Distribution, + f, + b.BuildOpts, + ), nil +} + +func (b *Backend) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (b *Backend) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (b *Backend) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (b *Backend) Filename(ctx context.Context) (string, error) { + return filepath.Join("bin", string(b.Name), string(b.Distribution)), nil +} + +func (b *Backend) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + // Not a file + return nil +} + +func (b *Backend) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + // Nothing to do (yet) + return nil +} + +type NewBackendOpts struct { + Name packages.Name + Enterprise bool + Src *dagger.Directory + Distribution backend.Distribution + GoVersion string + ViceroyVersion string + Version string + Experiments []string + Tags []string + Static bool + WireTag string + GoBuildCache *dagger.CacheVolume + GoModCache *dagger.CacheVolume +} + +func NewBackendFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + goVersion, err := state.String(ctx, arguments.GoVersion) + if err != nil { + return nil, err + } + viceroyVersion, err := state.String(ctx, arguments.ViceroyVersion) + if err != nil { + return nil, err + } + + goModCache, err := state.CacheVolume(ctx, arguments.GoModCache) + if err != nil { + return nil, err + } + + goBuildCache, err := state.CacheVolume(ctx, arguments.GoBuildCache) + if err != nil { + return nil, err + } + + // 1. Figure out the options that were provided as part of the artifact string. + // For example, `linux/amd64:grafana`. + options, err := pipeline.ParseFlags(artifact, TargzFlags) + if err != nil { + return nil, err + } + static, err := options.Bool(flags.Static) + if err != nil { + return nil, err + } + + wireTag, err := options.String(flags.WireTag) + if err != nil { + return nil, err + } + + experiments, err := options.StringSlice(flags.GoExperiments) + if err != nil { + return nil, err + } + + tags, err := options.StringSlice(flags.GoTags) + if err != nil { + return nil, err + } + + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + + src, err := GrafanaDir(ctx, state, p.Enterprise) + if err != nil { + return nil, err + } + + bopts := &backend.BuildOpts{ + Version: p.Version, + Enterprise: p.Enterprise, + ExperimentalFlags: experiments, + Static: static, + WireTag: wireTag, + Tags: tags, + } + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeDirectory, + Flags: BackendFlags, + Handler: &Backend{ + Name: p.Name, + Distribution: p.Distribution, + BuildOpts: bopts, + GoVersion: goVersion, + ViceroyVersion: viceroyVersion, + Src: src, + GoModCache: goModCache, + GoBuildCache: goBuildCache, + }, + }) +} + +func NewBackend(ctx context.Context, log *slog.Logger, artifact string, opts *NewBackendOpts) (*pipeline.Artifact, error) { + bopts := &backend.BuildOpts{ + Version: opts.Version, + Enterprise: opts.Enterprise, + ExperimentalFlags: opts.Experiments, + Tags: opts.Tags, + Static: opts.Static, + WireTag: opts.WireTag, + } + + log.Info("Initializing backend artifact with options", "static", opts.Static, "version", opts.Version, "name", opts.Name, "distro", opts.Distribution) + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeDirectory, + Flags: BackendFlags, + Handler: &Backend{ + Name: opts.Name, + Distribution: opts.Distribution, + BuildOpts: bopts, + GoVersion: opts.GoVersion, + ViceroyVersion: opts.ViceroyVersion, + Src: opts.Src, + GoModCache: opts.GoModCache, + GoBuildCache: opts.GoBuildCache, + }, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/flags.go b/pkg/build/daggerbuild/artifacts/flags.go new file mode 100644 index 00000000000..564da1c798e --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/flags.go @@ -0,0 +1,75 @@ +package artifacts + +import ( + "sort" + "strings" + + "log/slog" + + "github.com/grafana/grafana/pkg/build/daggerbuild/cmd/flags" + "github.com/urfave/cli/v2" +) + +func ArtifactFlags(r Registerer) []cli.Flag { + artifactsFlag := &cli.StringSliceFlag{ + Name: "artifacts", + Aliases: []string{"a"}, + } + + buildFlag := &cli.BoolFlag{ + Name: "build", + Value: true, + } + publishFlag := &cli.BoolFlag{ + Name: "publish", + Usage: "If true, then the artifacts that are built will be published. If `--build=false` and the artifacts are found in the --destination, then those artifacts are not built and are published instead.", + Value: true, + } + + verifyFlag := &cli.BoolFlag{ + Name: "verify", + Usage: "If true, then the artifacts that are built will be verified with e2e tests or similar after being exported, depending on the artifact", + Value: false, + } + + flags := flags.Join( + []cli.Flag{ + artifactsFlag, + buildFlag, + publishFlag, + verifyFlag, + flags.Platform, + }, + flags.PublishFlags, + flags.ConcurrencyFlags, + []cli.Flag{ + flags.Verbose, + }, + ) + + // All of these artifacts are the registered artifacts. These should mostly stay the same no matter what. + initializers := r.Initializers() + + // Add all of the CLI flags that are defined by each artifact's arguments. + m := map[string]cli.Flag{} + + // For artifact arguments that specify flags, we'll coalesce them here and add them to the list of flags. + for _, n := range initializers { + for _, arg := range n.Arguments { + for _, f := range arg.Flags { + fn := strings.Join(f.Names(), ",") + m[fn] = f + slog.Debug("global flag added by argument in artifact", "flag", fn, "arg", arg.Name) + } + } + } + for _, v := range m { + flags = append(flags, v) + } + + sort.Slice(flags, func(i, j int) bool { + return strings.Compare(flags[i].Names()[0], flags[j].Names()[0]) <= 0 + }) + + return flags +} diff --git a/pkg/build/daggerbuild/artifacts/frontend.go b/pkg/build/daggerbuild/artifacts/frontend.go new file mode 100644 index 00000000000..403c515b4e4 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/frontend.go @@ -0,0 +1,147 @@ +package artifacts + +import ( + "context" + "fmt" + "log/slog" + "path/filepath" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + FrontendFlags = flags.PackageNameFlags + FrontendArguments = []pipeline.Argument{ + arguments.YarnCacheDirectory, + } +) + +var FrontendInitializer = Initializer{ + InitializerFunc: NewFrontendFromString, + Arguments: FrontendArguments, +} + +type Frontend struct { + Enterprise bool + Version string + Src *dagger.Directory + YarnCache *dagger.CacheVolume +} + +// The frontend does not have any artifact dependencies. +func (f *Frontend) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return nil, nil +} + +// Builder will return a node.js alpine container that matches the .nvmrc in the Grafana source repository +func (f *Frontend) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return FrontendBuilder(ctx, f.Src, f.YarnCache, opts) +} + +func (f *Frontend) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + panic("not implemented") // Frontend doesn't return a file +} + +func (f *Frontend) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + return frontend.Build(builder), nil +} + +func (f *Frontend) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (f *Frontend) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (f *Frontend) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (f *Frontend) Filename(ctx context.Context) (string, error) { + n := "grafana" + if f.Enterprise { + n = "grafana-enterprise" + } + + // Important note: this path is only used in two ways: + // 1. When requesting an artifact be built and exported, this is the path where it will be exported to + // 2. In a map to distinguish when the same artifact is being built more than once + return filepath.Join(f.Version, n, "public"), nil +} + +func (f *Frontend) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + // Should never be called since this isn't a File. + return nil +} + +func (f *Frontend) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + // Nothing to do to verify these (for now?) + return nil +} + +func NewFrontendFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + options, err := pipeline.ParseFlags(artifact, FrontendFlags) + if err != nil { + return nil, err + } + + enterprise, err := options.Bool(flags.Enterprise) + if err != nil { + return nil, err + } + + src, err := GrafanaDir(ctx, state, enterprise) + if err != nil { + return nil, err + } + + cache, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + + version, err := state.String(ctx, arguments.Version) + if err != nil { + return nil, err + } + + return NewFrontend(ctx, log, artifact, version, enterprise, src, cache) +} + +func NewFrontend(ctx context.Context, log *slog.Logger, artifact, version string, enterprise bool, src *dagger.Directory, cache *dagger.CacheVolume) (*pipeline.Artifact, error) { + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeDirectory, + Flags: FrontendFlags, + Handler: &Frontend{ + Enterprise: enterprise, + Version: version, + Src: src, + YarnCache: cache, + }, + }) +} + +func FrontendBuilder( + ctx context.Context, + src *dagger.Directory, + cache *dagger.CacheVolume, + opts *pipeline.ArtifactContainerOpts, +) (*dagger.Container, error) { + nodeVersion, err := frontend.NodeVersion(opts.Client, src).Stdout(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get node version from source code: %w", err) + } + + return frontend.Builder(opts.Client, opts.Platform, src, nodeVersion, cache), nil +} diff --git a/pkg/build/daggerbuild/artifacts/grafana_dir.go b/pkg/build/daggerbuild/artifacts/grafana_dir.go new file mode 100644 index 00000000000..754eb8461b3 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/grafana_dir.go @@ -0,0 +1,16 @@ +package artifacts + +import ( + "context" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +func GrafanaDir(ctx context.Context, state pipeline.StateHandler, enterprise bool) (*dagger.Directory, error) { + if enterprise { + return state.Directory(ctx, arguments.EnterpriseDirectory) + } + return state.Directory(ctx, arguments.GrafanaDirectory) +} diff --git a/pkg/build/daggerbuild/artifacts/npm.go b/pkg/build/daggerbuild/artifacts/npm.go new file mode 100644 index 00000000000..89130cdf254 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/npm.go @@ -0,0 +1,114 @@ +package artifacts + +import ( + "context" + "log/slog" + "path/filepath" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + NPMPackagesFlags = flags.PackageNameFlags + NPMPackagesArguments = []pipeline.Argument{ + arguments.YarnCacheDirectory, + } +) + +var NPMPackagesInitializer = Initializer{ + InitializerFunc: NewNPMPackagesFromString, + Arguments: NPMPackagesArguments, +} + +type NPMPackages struct { + Src *dagger.Directory + YarnCache *dagger.CacheVolume + Version string +} + +// The frontend does not have any artifact dependencies. +func (f *NPMPackages) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return nil, nil +} + +// Builder will return a node.js alpine container that matches the .nvmrc in the Grafana source repository +func (f *NPMPackages) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return FrontendBuilder(ctx, f.Src, f.YarnCache, opts) +} + +func (f *NPMPackages) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + panic("not implemented") // NPMPackages doesn't return a file +} + +func (f *NPMPackages) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + return frontend.NPMPackages(builder, opts.Client, opts.Log, f.Src, strings.TrimPrefix(f.Version, "v")) +} + +func (f *NPMPackages) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (f *NPMPackages) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (f *NPMPackages) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +func (f *NPMPackages) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + // Not a file + return nil +} + +func (f *NPMPackages) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + // Nothing to verify (yet?) + return nil +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (f *NPMPackages) Filename(ctx context.Context) (string, error) { + // Important note: this path is only used in two ways: + // 1. When requesting an artifact be built and exported, this is the path where it will be exported to + // 2. In a map to distinguish when the same artifact is being built more than once + return filepath.Join(f.Version, "npm-packages"), nil +} + +func NewNPMPackagesFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + grafanaDir, err := GrafanaDir(ctx, state, false) + if err != nil { + return nil, err + } + cache, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + version, err := state.String(ctx, arguments.Version) + if err != nil { + return nil, err + } + + return NewNPMPackages(ctx, log, artifact, grafanaDir, version, cache) +} + +func NewNPMPackages(ctx context.Context, log *slog.Logger, artifact string, src *dagger.Directory, version string, cache *dagger.CacheVolume) (*pipeline.Artifact, error) { + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeDirectory, + Flags: NPMPackagesFlags, + Handler: &NPMPackages{ + Src: src, + YarnCache: cache, + Version: version, + }, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_deb.go b/pkg/build/daggerbuild/artifacts/package_deb.go new file mode 100644 index 00000000000..6d36b0a6ed1 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_deb.go @@ -0,0 +1,179 @@ +package artifacts + +import ( + "context" + "log/slog" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/fpm" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + DebArguments = TargzArguments + DebFlags = flags.JoinFlags( + TargzFlags, + []pipeline.Flag{ + flags.NightlyFlag, + }, + ) +) + +var DebInitializer = Initializer{ + InitializerFunc: NewDebFromString, + Arguments: TargzArguments, +} + +// PacakgeDeb uses a built tar.gz package to create a .deb installer for debian based Linux distributions. +type Deb struct { + Name packages.Name + Version string + BuildID string + Distribution backend.Distribution + Enterprise bool + NameOverride string + + Tarball *pipeline.Artifact + + // Src is the source tree of Grafana. This should only be used in the verify function. + Src *dagger.Directory + YarnCache *dagger.CacheVolume +} + +func (d *Deb) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Tarball, + }, nil +} + +func (d *Deb) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return fpm.Builder(opts.Client), nil +} + +func debVersion(version string) string { + // If there is a `+security-` modifier to the version, simply use `-` + return strings.ReplaceAll(version, "+security-", "-") +} + +func (d *Deb) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + targz, err := opts.Store.File(ctx, d.Tarball) + if err != nil { + return nil, err + } + + return fpm.Build(builder, fpm.BuildOpts{ + Name: d.Name, + Enterprise: d.Enterprise, + Version: debVersion(d.Version), + BuildID: d.BuildID, + Distribution: d.Distribution, + PackageType: fpm.PackageTypeDeb, + NameOverride: d.NameOverride, + ConfigFiles: [][]string{ + {"/src/packaging/deb/default/grafana-server", "/pkg/etc/default/grafana-server"}, + {"/src/packaging/deb/init.d/grafana-server", "/pkg/etc/init.d/grafana-server"}, + {"/src/packaging/deb/systemd/grafana-server.service", "/pkg/usr/lib/systemd/system/grafana-server.service"}, + }, + AfterInstall: "/src/packaging/deb/control/postinst", + BeforeRemove: "/src/packaging/deb/control/prerm", + Depends: []string{ + "adduser", + "musl", + }, + EnvFolder: "/pkg/etc/default", + ExtraArgs: []string{ + "--deb-no-default-config-files", + }, + }, targz), nil +} + +func (d *Deb) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("not implemented") // TODO: Implement +} + +func (d *Deb) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (d *Deb) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (d *Deb) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *Deb) Filename(ctx context.Context) (string, error) { + name := d.Name + if d.NameOverride != "" { + name = packages.Name(d.NameOverride) + } + + return packages.FileName(name, d.Version, d.BuildID, d.Distribution, "deb") +} + +func (d *Deb) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return fpm.VerifyDeb(ctx, client, file, d.Src, d.YarnCache, d.Distribution, d.Enterprise) +} + +func (d *Deb) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func NewDebFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + tarball, err := NewTarballFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + options, err := pipeline.ParseFlags(artifact, DebFlags) + if err != nil { + return nil, err + } + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + src, err := state.Directory(ctx, arguments.GrafanaDirectory) + if err != nil { + return nil, err + } + yarnCache, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + + debname := string(p.Name) + if nightly, _ := options.Bool(flags.Nightly); nightly { + debname += "-nightly" + } + if rpi, _ := options.Bool(flags.RPI); rpi { + debname += "-rpi" + } + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &Deb{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distribution: p.Distribution, + Enterprise: p.Enterprise, + Tarball: tarball, + Src: src, + YarnCache: yarnCache, + NameOverride: debname, + }, + Type: pipeline.ArtifactTypeFile, + Flags: TargzFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_docker.go b/pkg/build/daggerbuild/artifacts/package_docker.go new file mode 100644 index 00000000000..cdc679ebc96 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_docker.go @@ -0,0 +1,265 @@ +package artifacts + +import ( + "context" + "fmt" + "log/slog" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/docker" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + DockerArguments = arguments.Join( + TargzArguments, + []pipeline.Argument{ + arguments.DockerRegistry, + arguments.DockerOrg, + arguments.AlpineImage, + arguments.UbuntuImage, + arguments.TagFormat, + arguments.UbuntuTagFormat, + arguments.BoringTagFormat, + }, + ) + DockerFlags = flags.JoinFlags( + TargzFlags, + flags.DockerFlags, + ) +) + +var DockerInitializer = Initializer{ + InitializerFunc: NewDockerFromString, + Arguments: DockerArguments, +} + +// PacakgeDocker uses a built tar.gz package to create a docker image from the Dockerfile in the tar.gz +type Docker struct { + Name packages.Name + Version string + BuildID string + Distro backend.Distribution + Enterprise bool + + Ubuntu bool + Registry string + Repositories []string + Org string + BaseImage string + TagFormat string + + Tarball *pipeline.Artifact + + // Src is the Grafana source code for running e2e tests when validating. + // The grafana source should not be used for anything else when building a docker image. All files in the Docker image, including the Dockerfile, should be + // from the tar.gz file. + Src *dagger.Directory + YarnCache *dagger.CacheVolume +} + +func (d *Docker) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Tarball, + }, nil +} + +func (d *Docker) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + targz, err := opts.Store.File(ctx, d.Tarball) + if err != nil { + return nil, err + } + + return docker.Builder(opts.Client, opts.Client.Host().UnixSocket("/var/run/docker.sock"), targz), nil +} + +func (d *Docker) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + // Unlike most other things we push to, docker image tags do not support all characters. + // Specifically, the `+` character used in the `buildmetadata` section of semver. + version := strings.ReplaceAll(d.Version, "+", "-") + + tags, err := docker.Tags(d.Org, d.Registry, d.Repositories, d.TagFormat, packages.NameOpts{ + Name: d.Name, + Version: version, + BuildID: d.BuildID, + Distro: d.Distro, + }) + if err != nil { + return nil, err + } + buildOpts := &docker.BuildOpts{ + // Tags are provided as the '-t' argument, and can include the registry domain as well as the repository. + // Docker build supports building the same image with multiple tags. + // You might want to also include a 'latest' version of the tag. + Tags: tags, + Platform: backend.Platform(d.Distro), + BuildArgs: []string{ + "GRAFANA_TGZ=grafana.tar.gz", + "GO_SRC=tgz-builder", + "JS_SRC=tgz-builder", + fmt.Sprintf("BASE_IMAGE=%s", d.BaseImage), + }, + } + + b := docker.Build(opts.Client, builder, buildOpts) + + return docker.Save(b, buildOpts), nil +} + +func (d *Docker) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("This artifact does not produce directories") +} + +func (d *Docker) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + socket := opts.Client.Host().UnixSocket("/var/run/docker.sock") + return opts.Client.Container().From("docker").WithUnixSocket("/var/run/docker.sock", socket), nil +} + +func (d *Docker) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") +} + +func (d *Docker) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("This artifact does not produce directories") +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *Docker) Filename(ctx context.Context) (string, error) { + ext := "docker.tar.gz" + if d.Ubuntu { + ext = "ubuntu.docker.tar.gz" + } + + return packages.FileName(d.Name, d.Version, d.BuildID, d.Distro, ext) +} + +func (d *Docker) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + // Currently verifying riscv64 is unsupported (because alpine and ubuntu don't have riscv64 images yet) + if _, arch := backend.OSAndArch(d.Distro); arch == "riscv64" { + return nil + } + + return docker.Verify(ctx, client, file, d.Src, d.YarnCache, d.Distro) +} + +func (d *Docker) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func NewDockerFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + options, err := pipeline.ParseFlags(artifact, DockerFlags) + if err != nil { + return nil, err + } + + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + + tarball, err := NewTarballFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + + ubuntu, err := options.Bool(flags.Ubuntu) + if err != nil { + return nil, err + } + + // Ubuntu Version to use as the base for the Grafana docker image (if this is a ubuntu artifact) + // This shouldn't fail if it's not set by the user, instead it'll default to 22.04 or something. + ubuntuImage, err := state.String(ctx, arguments.UbuntuImage) + if err != nil { + return nil, err + } + + // Same for Alpine + alpineImage, err := state.String(ctx, arguments.AlpineImage) + if err != nil { + return nil, err + } + + registry, err := state.String(ctx, arguments.DockerRegistry) + if err != nil { + return nil, err + } + + org, err := state.String(ctx, arguments.DockerOrg) + if err != nil { + return nil, err + } + + repos, err := options.StringSlice(flags.DockerRepositories) + if err != nil { + return nil, err + } + + format, err := state.String(ctx, arguments.TagFormat) + if err != nil { + return nil, err + } + ubuntuFormat, err := state.String(ctx, arguments.UbuntuTagFormat) + if err != nil { + return nil, err + } + boringFormat, err := state.String(ctx, arguments.BoringTagFormat) + if err != nil { + return nil, err + } + + base := alpineImage + if ubuntu { + format = ubuntuFormat + base = ubuntuImage + } + + if p.Name == packages.PackageEnterpriseBoring { + format = boringFormat + } + + src, err := state.Directory(ctx, arguments.GrafanaDirectory) + if err != nil { + return nil, err + } + + yarnCache, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + + log.Info("initializing Docker artifact", "Org", org, "registry", registry, "repos", repos, "tag", format) + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &Docker{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distro: p.Distribution, + Enterprise: p.Enterprise, + Tarball: tarball, + + Ubuntu: ubuntu, + BaseImage: base, + Registry: registry, + Org: org, + Repositories: repos, + TagFormat: format, + + Src: src, + YarnCache: yarnCache, + }, + Type: pipeline.ArtifactTypeFile, + Flags: DockerFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_docker_enterprise.go b/pkg/build/daggerbuild/artifacts/package_docker_enterprise.go new file mode 100644 index 00000000000..570ed645cf2 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_docker_enterprise.go @@ -0,0 +1,202 @@ +package artifacts + +import ( + "context" + "fmt" + "log/slog" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/docker" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + EntDockerArguments = arguments.Join( + DebArguments, + []pipeline.Argument{ + arguments.HGDirectory, + arguments.EntDockerRegistry, + arguments.EntDockerOrg, + arguments.EntDockerRepo, + arguments.HGTagFormat, + }, + ) + EntDockerFlags = flags.JoinFlags( + DebFlags, + flags.DockerFlags, + ) +) + +var EntDockerInitializer = Initializer{ + InitializerFunc: NewEntDockerFromString, + Arguments: EntDockerArguments, +} + +// EntDocker uses a built deb installer to create a docker image +type EntDocker struct { + Name packages.Name + Version string + BuildID string + Distro backend.Distribution + EntDir *dagger.Directory + + // EntRegistry is the docker registry when using the `enterprise` name. (e.g. hub.docker.io) + EntRegistry string + // EntOrg is the docker org when using the `enterprise` name. (e.g. grafana) + EntOrg string + // EntOrg is the docker repo when using the `enterprise` name. (e.g. grafana-enterprise) + EntRepo string + // TagFormat is the docker tag format when using the `enterprise` name. (e.g. {{ .version }}-{{ .os }}-{{ .arch }}) + TagFormat string + + Deb *pipeline.Artifact +} + +func (d *EntDocker) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Deb, + }, nil +} + +func (d *EntDocker) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + deb, err := opts.Store.File(ctx, d.Deb) + if err != nil { + return nil, fmt.Errorf("error getting deb from state: %w", err) + } + + socket := opts.Client.Host().UnixSocket("/var/run/docker.sock") + + return opts.Client.Container().From("docker"). + WithUnixSocket("/var/run/docker.sock", socket). + WithMountedDirectory("/src", d.EntDir). + WithMountedFile("/src/grafana.deb", deb). + WithWorkdir("/src"), nil +} + +func (d *EntDocker) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + tags, err := docker.Tags(d.EntOrg, d.EntRegistry, []string{d.EntRepo}, d.TagFormat, packages.NameOpts{ + Name: d.Name, + Version: d.Version, + BuildID: d.BuildID, + Distro: d.Distro, + }) + + if err != nil { + return nil, err + } + + builder = docker.Build(opts.Client, builder, &docker.BuildOpts{ + Dockerfile: "./docker/hosted-grafana-all/Dockerfile", + Tags: tags, + Target: "hosted-grafana-localenterprise", + Platform: dagger.Platform("linux/amd64"), + BuildArgs: []string{ + "RELEASE_TYPE=main", + // I think because deb files use a ~ as a version delimiter of some kind, so the hg docker image uses that instead of a - + fmt.Sprintf("GRAFANA_VERSION=%s", strings.Replace(d.Version, "-", "~", 1)), + }, + }) + + // Save the resulting docker image to the local filesystem + return builder.WithExec([]string{"docker", "save", tags[0], "-o", "enterprise.tar"}).File("enterprise.tar"), nil +} + +func (d *EntDocker) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("This artifact does not produce directories") +} + +func (d *EntDocker) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") +} + +func (d *EntDocker) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") +} + +func (d *EntDocker) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("This artifact does not produce directories") +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *EntDocker) Filename(ctx context.Context) (string, error) { + ext := "docker-enterprise.tar.gz" + + return packages.FileName(d.Name, d.Version, d.BuildID, d.Distro, ext) +} + +func (d *EntDocker) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil +} + +func (d *EntDocker) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func NewEntDockerFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + options, err := pipeline.ParseFlags(artifact, DockerFlags) + if err != nil { + return nil, err + } + + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + + deb, err := NewDebFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + + entRegistry, err := state.String(ctx, arguments.EntDockerRegistry) + if err != nil { + return nil, err + } + entOrg, err := state.String(ctx, arguments.EntDockerOrg) + if err != nil { + return nil, err + } + entRepo, err := state.String(ctx, arguments.EntDockerRepo) + if err != nil { + return nil, err + } + tagFormat, err := state.String(ctx, arguments.HGTagFormat) + if err != nil { + return nil, err + } + + dir, err := state.Directory(ctx, arguments.HGDirectory) + if err != nil { + return nil, err + } + + log.Info("initializing Enterprise Docker artifact", "Org", entOrg, "registry", entRegistry, "repo", entRepo, "tag", tagFormat) + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &EntDocker{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distro: p.Distribution, + EntDir: dir, + Deb: deb, + + EntRegistry: entRegistry, + EntOrg: entOrg, + EntRepo: entRepo, + TagFormat: tagFormat, + }, + Type: pipeline.ArtifactTypeFile, + Flags: DockerFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_docker_pro.go b/pkg/build/daggerbuild/artifacts/package_docker_pro.go new file mode 100644 index 00000000000..b71ce73e4d3 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_docker_pro.go @@ -0,0 +1,203 @@ +package artifacts + +import ( + "context" + "fmt" + "log/slog" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/docker" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + ProDockerArguments = arguments.Join( + DebArguments, + []pipeline.Argument{ + arguments.HGDirectory, + arguments.ProDockerRegistry, + arguments.ProDockerOrg, + arguments.ProDockerRepo, + arguments.HGTagFormat, + }, + ) + ProDockerFlags = flags.JoinFlags( + DebFlags, + flags.DockerFlags, + ) +) + +var ProDockerInitializer = Initializer{ + InitializerFunc: NewProDockerFromString, + Arguments: ProDockerArguments, +} + +// ProDocker uses a built deb installer to create a docker image +type ProDocker struct { + Name packages.Name + Version string + BuildID string + Distro backend.Distribution + ProDir *dagger.Directory + + // ProRegistry is the docker registry when using the `pro` name. (e.g. hub.docker.io) + ProRegistry string + // ProOrg is the docker org when using the `pro` name. (e.g. grafana) + ProOrg string + // ProOrg is the docker repo when using the `pro` name. (e.g. grafana-pro) + ProRepo string + // TagFormat is the docker tag format when using the `pro` name. (e.g. {{ .version }}-{{ .os }}-{{ .arch }}) + TagFormat string + + // Building the Pro image requires a Debian package instead of a tar.gz + Deb *pipeline.Artifact +} + +func (d *ProDocker) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Deb, + }, nil +} + +func (d *ProDocker) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + deb, err := opts.Store.File(ctx, d.Deb) + if err != nil { + return nil, fmt.Errorf("error getting deb from state: %w", err) + } + + socket := opts.Client.Host().UnixSocket("/var/run/docker.sock") + + return opts.Client.Container().From("docker"). + WithUnixSocket("/var/run/docker.sock", socket). + WithMountedDirectory("/src", d.ProDir). + WithMountedFile("/src/grafana.deb", deb). + WithWorkdir("/src"), nil +} + +func (d *ProDocker) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + tags, err := docker.Tags(d.ProOrg, d.ProRegistry, []string{d.ProRepo}, d.TagFormat, packages.NameOpts{ + Name: d.Name, + Version: d.Version, + BuildID: d.BuildID, + Distro: d.Distro, + }) + + if err != nil { + return nil, err + } + + builder = docker.Build(opts.Client, builder, &docker.BuildOpts{ + Dockerfile: "./docker/hosted-grafana-all/Dockerfile", + Tags: tags, + Target: "hosted-grafana-localpro", + Platform: dagger.Platform("linux/amd64"), + BuildArgs: []string{ + "RELEASE_TYPE=main", + // I think because deb files use a ~ as a version delimiter of some kind, so the hg docker image uses that instead of a - + fmt.Sprintf("GRAFANA_VERSION=%s", strings.Replace(d.Version, "-", "~", 1)), + }, + }) + + // Save the resulting docker image to the local filesystem + return builder.WithExec([]string{"docker", "save", tags[0], "-o", "pro.tar"}).File("pro.tar"), nil +} + +func (d *ProDocker) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("This artifact does not produce directories") +} + +func (d *ProDocker) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") +} + +func (d *ProDocker) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") +} + +func (d *ProDocker) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("This artifact does not produce directories") +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *ProDocker) Filename(ctx context.Context) (string, error) { + ext := "docker-pro.tar.gz" + + return packages.FileName(d.Name, d.Version, d.BuildID, d.Distro, ext) +} + +func (d *ProDocker) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil +} + +func (d *ProDocker) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func NewProDockerFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + options, err := pipeline.ParseFlags(artifact, DockerFlags) + if err != nil { + return nil, err + } + + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + + deb, err := NewDebFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + + proRegistry, err := state.String(ctx, arguments.ProDockerRegistry) + if err != nil { + return nil, err + } + proOrg, err := state.String(ctx, arguments.ProDockerOrg) + if err != nil { + return nil, err + } + proRepo, err := state.String(ctx, arguments.ProDockerRepo) + if err != nil { + return nil, err + } + tagFormat, err := state.String(ctx, arguments.HGTagFormat) + if err != nil { + return nil, err + } + + dir, err := state.Directory(ctx, arguments.HGDirectory) + if err != nil { + return nil, err + } + + log.Info("initializing Pro Docker artifact", "Org", proOrg, "registry", proRegistry, "repo", proRepo, "tag", tagFormat) + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &ProDocker{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distro: p.Distribution, + ProDir: dir, + Deb: deb, + + ProRegistry: proRegistry, + ProOrg: proOrg, + ProRepo: proRepo, + TagFormat: tagFormat, + }, + Type: pipeline.ArtifactTypeFile, + Flags: DockerFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_msi.go b/pkg/build/daggerbuild/artifacts/package_msi.go new file mode 100644 index 00000000000..443d76d219d --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_msi.go @@ -0,0 +1,121 @@ +package artifacts + +import ( + "context" + "fmt" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/msi" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + MSIArguments = TargzArguments + MSIFlags = TargzFlags +) + +var MSIInitializer = Initializer{ + InitializerFunc: NewMSIFromString, + Arguments: TargzArguments, +} + +// PacakgeMSI uses a built tar.gz package to create a .exe installer for exeian based Linux distributions. +type MSI struct { + Name packages.Name + Version string + BuildID string + Distribution backend.Distribution + Enterprise bool + + Tarball *pipeline.Artifact +} + +func (d *MSI) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Tarball, + }, nil +} + +func (d *MSI) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return msi.Builder(opts.Client) +} + +func (d *MSI) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + targz, err := opts.Store.File(ctx, d.Tarball) + if err != nil { + return nil, err + } + + return msi.Build(opts.Client, builder, targz, d.Version, d.Enterprise) +} + +func (d *MSI) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + // Not a directory so this shouldn't be called + return nil, nil +} + +func (d *MSI) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return nil, nil +} + +func (d *MSI) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (d *MSI) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + // Not a directory so this shouldn't be called + return nil +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *MSI) Filename(ctx context.Context) (string, error) { + return packages.FileName(d.Name, d.Version, d.BuildID, d.Distribution, "msi") +} + +func (d *MSI) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil +} + +func (d *MSI) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func NewMSIFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + targz, err := NewTarballFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + options, err := pipeline.ParseFlags(artifact, MSIFlags) + if err != nil { + return nil, err + } + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + + if !backend.IsWindows(p.Distribution) { + return nil, fmt.Errorf("distribution ('%s') for exe '%s' is not a Windows distribution", string(p.Distribution), artifact) + } + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &MSI{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distribution: p.Distribution, + Enterprise: p.Enterprise, + Tarball: targz, + }, + Type: pipeline.ArtifactTypeFile, + Flags: ZipFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_rpm.go b/pkg/build/daggerbuild/artifacts/package_rpm.go new file mode 100644 index 00000000000..d6fde3dfc78 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_rpm.go @@ -0,0 +1,242 @@ +package artifacts + +import ( + "context" + "encoding/base64" + "fmt" + "log/slog" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/fpm" + "github.com/grafana/grafana/pkg/build/daggerbuild/gpg" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + RPMArguments = TargzArguments + RPMFlags = flags.JoinFlags( + TargzFlags, + []pipeline.Flag{ + flags.SignFlag, + flags.NightlyFlag, + }, + ) +) + +var RPMInitializer = Initializer{ + InitializerFunc: NewRPMFromString, + Arguments: arguments.Join( + TargzArguments, + []pipeline.Argument{ + arguments.GPGPublicKey, + arguments.GPGPrivateKey, + arguments.GPGPassphrase, + }, + ), +} + +// PacakgeRPM uses a built tar.gz package to create a .rpm installer for RHEL-ish Linux distributions. +type RPM struct { + Name packages.Name + Version string + BuildID string + Distribution backend.Distribution + Enterprise bool + Sign bool + NameOverride string + + GPGPublicKey string + GPGPrivateKey string + GPGPassphrase string + + Src *dagger.Directory + YarnCache *dagger.CacheVolume + + Tarball *pipeline.Artifact +} + +func (d *RPM) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Tarball, + }, nil +} + +func (d *RPM) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return fpm.Builder(opts.Client), nil +} + +func rpmVersion(version string) string { + // https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/#_snapshots + // If there's a buildmeta revision, then use that as a snapshot version + return strings.ReplaceAll(version, "+", "^") +} + +func (d *RPM) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + targz, err := opts.Store.File(ctx, d.Tarball) + if err != nil { + return nil, err + } + + rpm := fpm.Build(builder, fpm.BuildOpts{ + Name: d.Name, + Enterprise: d.Enterprise, + Version: rpmVersion(d.Version), + BuildID: d.BuildID, + Distribution: d.Distribution, + PackageType: fpm.PackageTypeRPM, + NameOverride: d.NameOverride, + ConfigFiles: [][]string{ + {"/src/packaging/rpm/sysconfig/grafana-server", "/pkg/etc/sysconfig/grafana-server"}, + {"/src/packaging/rpm/systemd/grafana-server.service", "/pkg/usr/lib/systemd/system/grafana-server.service"}, + }, + AfterInstall: "/src/packaging/rpm/control/postinst", + Depends: []string{ + "/sbin/service", + }, + ExtraArgs: []string{ + "--rpm-posttrans=/src/packaging/rpm/control/posttrans", + "--rpm-digest=sha256", + }, + EnvFolder: "/pkg/etc/sysconfig", + }, targz) + + if !d.Sign { + return rpm, nil + } + return gpg.Sign(opts.Client, rpm, gpg.GPGOpts{ + GPGPublicKey: d.GPGPublicKey, + GPGPrivateKey: d.GPGPrivateKey, + GPGPassphrase: d.GPGPassphrase, + }), nil +} + +func (d *RPM) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("not implemented") // TODO: Implement +} + +func (d *RPM) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (d *RPM) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (d *RPM) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *RPM) Filename(ctx context.Context) (string, error) { + name := d.Name + if d.NameOverride != "" { + name = packages.Name(d.NameOverride) + } + + return packages.FileName(name, d.Version, d.BuildID, d.Distribution, "rpm") +} + +func (d *RPM) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil + // return fpm.VerifyRpm(ctx, client, file, d.Src, d.YarnCache, d.Distribution, d.Enterprise, d.Sign, d.GPGPublicKey, d.GPGPrivateKey, d.GPGPassphrase) +} + +func (d *RPM) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func NewRPMFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + tarball, err := NewTarballFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + options, err := pipeline.ParseFlags(artifact, RPMFlags) + if err != nil { + return nil, err + } + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + sign, err := options.Bool(flags.Sign) + if err != nil { + return nil, err + } + src, err := state.Directory(ctx, arguments.GrafanaDirectory) + if err != nil { + return nil, err + } + yarnCache, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + + var gpgPublicKey, gpgPrivateKey, gpgPassphrase string + + if sign { + pubb64, err := state.String(ctx, arguments.GPGPublicKey) + if err != nil { + return nil, err + } + pub, err := base64.StdEncoding.DecodeString(pubb64) + if err != nil { + return nil, fmt.Errorf("gpg-private-key-base64 cannot be decoded %w", err) + } + + privb64, err := state.String(ctx, arguments.GPGPrivateKey) + if err != nil { + return nil, err + } + priv, err := base64.StdEncoding.DecodeString(privb64) + if err != nil { + return nil, fmt.Errorf("gpg-private-key-base64 cannot be decoded %w", err) + } + + pass, err := state.String(ctx, arguments.GPGPassphrase) + if err != nil { + return nil, err + } + + gpgPublicKey = string(pub) + gpgPrivateKey = string(priv) + gpgPassphrase = pass + } + + rpmname := string(p.Name) + if nightly, _ := options.Bool(flags.Nightly); nightly { + rpmname += "-nightly" + } + if rpi, _ := options.Bool(flags.RPI); rpi { + rpmname += "-rpi" + } + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &RPM{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distribution: p.Distribution, + Enterprise: p.Enterprise, + Tarball: tarball, + Sign: sign, + Src: src, + YarnCache: yarnCache, + GPGPublicKey: gpgPublicKey, + GPGPrivateKey: gpgPrivateKey, + GPGPassphrase: gpgPassphrase, + NameOverride: rpmname, + }, + Type: pipeline.ArtifactTypeFile, + Flags: TargzFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/package_targz.go b/pkg/build/daggerbuild/artifacts/package_targz.go new file mode 100644 index 00000000000..9046ae7f5ad --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_targz.go @@ -0,0 +1,382 @@ +package artifacts + +import ( + "context" + "fmt" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/e2e" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/grafana/grafana/pkg/build/daggerbuild/targz" +) + +var ( + TargzArguments = []pipeline.Argument{ + // Tarballs need the Build ID and version for naming the package properly. + arguments.BuildID, + arguments.Version, + + // The grafanadirectory has contents like the LICENSE.txt and such that need to be included in the package + arguments.GrafanaDirectory, + + // The go version used to build the backend + arguments.GoVersion, + arguments.ViceroyVersion, + arguments.YarnCacheDirectory, + } + TargzFlags = flags.JoinFlags( + flags.StdPackageFlags(), + ) +) + +var TargzInitializer = Initializer{ + InitializerFunc: NewTarballFromString, + Arguments: TargzArguments, +} + +type Tarball struct { + Distribution backend.Distribution + Name packages.Name + BuildID string + Version string + GoVersion string + Enterprise bool + + Grafana *dagger.Directory + YarnCache *dagger.CacheVolume + + // Dependent artifacts + Backend *pipeline.Artifact + Frontend *pipeline.Artifact + NPMPackages *pipeline.Artifact + BundledPlugins *pipeline.Artifact + Storybook *pipeline.Artifact +} + +func NewTarballFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + goVersion, err := state.String(ctx, arguments.GoVersion) + if err != nil { + return nil, err + } + viceroyVersion, err := state.String(ctx, arguments.ViceroyVersion) + if err != nil { + return nil, err + } + + // 1. Figure out the options that were provided as part of the artifact string. + // For example, `linux/amd64:grafana`. + options, err := pipeline.ParseFlags(artifact, TargzFlags) + if err != nil { + return nil, err + } + static, err := options.Bool(flags.Static) + if err != nil { + return nil, err + } + + wireTag, err := options.String(flags.WireTag) + if err != nil { + return nil, err + } + + tags, err := options.StringSlice(flags.GoTags) + if err != nil { + return nil, err + } + + experiments, err := options.StringSlice(flags.GoExperiments) + if err != nil { + return nil, err + } + + yarnCache, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + + goModCache, err := state.CacheVolume(ctx, arguments.GoModCache) + if err != nil { + return nil, err + } + + goBuildCache, err := state.CacheVolume(ctx, arguments.GoBuildCache) + if err != nil { + return nil, err + } + + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + log.Info("Initializing tar.gz artifact with options", "name", p.Name, "build ID", p.BuildID, "version", p.Version, "distro", p.Distribution, "static", static, "enterprise", p.Enterprise) + + src, err := GrafanaDir(ctx, state, p.Enterprise) + if err != nil { + return nil, err + } + return NewTarball(ctx, log, artifact, p.Distribution, p.Enterprise, p.Name, p.Version, p.BuildID, src, yarnCache, goModCache, goBuildCache, static, wireTag, tags, goVersion, viceroyVersion, experiments) +} + +// NewTarball returns a properly initialized Tarball artifact. +// There are a lot of options that can affect how a tarball is built; most of which define different ways for the backend to be built. +func NewTarball( + ctx context.Context, + log *slog.Logger, + artifact string, + distro backend.Distribution, + enterprise bool, + name packages.Name, + version string, + buildID string, + src *dagger.Directory, + cache *dagger.CacheVolume, + goModCache *dagger.CacheVolume, + goBuildCache *dagger.CacheVolume, + static bool, + wireTag string, + tags []string, + goVersion string, + viceroyVersion string, + experiments []string, +) (*pipeline.Artifact, error) { + backendArtifact, err := NewBackend(ctx, log, artifact, &NewBackendOpts{ + Name: name, + Version: version, + Distribution: distro, + Src: src, + Static: static, + WireTag: wireTag, + Tags: tags, + GoVersion: goVersion, + ViceroyVersion: viceroyVersion, + Experiments: experiments, + Enterprise: enterprise, + GoBuildCache: goBuildCache, + GoModCache: goModCache, + }) + if err != nil { + return nil, err + } + frontendArtifact, err := NewFrontend(ctx, log, version, artifact, enterprise, src, cache) + if err != nil { + return nil, err + } + + bundledPluginsArtifact, err := NewBundledPlugins(ctx, log, artifact, src, version, cache) + if err != nil { + return nil, err + } + + npmArtifact, err := NewNPMPackages(ctx, log, artifact, src, version, cache) + if err != nil { + return nil, err + } + + storybookArtifact, err := NewStorybook(ctx, log, artifact, src, version, cache) + if err != nil { + return nil, err + } + tarball := &Tarball{ + Name: name, + Distribution: distro, + Version: version, + GoVersion: goVersion, + BuildID: buildID, + Grafana: src, + Enterprise: enterprise, + YarnCache: cache, + + Backend: backendArtifact, + Frontend: frontendArtifact, + NPMPackages: npmArtifact, + BundledPlugins: bundledPluginsArtifact, + Storybook: storybookArtifact, + } + + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: tarball, + Type: pipeline.ArtifactTypeFile, + Flags: TargzFlags, + }) +} + +func (t *Tarball) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + version := t.Version + + container := opts.Client.Container(). + From("alpine:3.18.4"). + WithExec([]string{"apk", "add", "--update", "tar"}). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("echo %s > VERSION", version)}) + + return container, nil +} + +func (t *Tarball) BuildFile(ctx context.Context, b *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + var ( + state = opts.State + log = opts.Log + ) + + log.Debug("Getting grafana dir from state...") + // The Grafana directory is used for other packaged data like Dockerfile, license.txt, etc. + grafanaDir := t.Grafana + + backendDir, err := opts.Store.Directory(ctx, t.Backend) + if err != nil { + return nil, err + } + + frontendDir, err := opts.Store.Directory(ctx, t.Frontend) + if err != nil { + return nil, err + } + + npmDir, err := opts.Store.Directory(ctx, t.NPMPackages) + if err != nil { + return nil, err + } + + storybookDir, err := opts.Store.Directory(ctx, t.Storybook) + if err != nil { + return nil, err + } + + pluginsDir, err := opts.Store.Directory(ctx, t.BundledPlugins) + if err != nil { + return nil, err + } + + version, err := state.String(ctx, arguments.Version) + if err != nil { + return nil, err + } + + files := []targz.MappedFile{ + targz.NewMappedFile("VERSION", b.File("VERSION")), + targz.NewMappedFile("LICENSE", grafanaDir.File("LICENSE")), + targz.NewMappedFile("NOTICE.md", grafanaDir.File("NOTICE.md")), + targz.NewMappedFile("README.md", grafanaDir.File("README.md")), + targz.NewMappedFile("Dockerfile", grafanaDir.File("Dockerfile")), + targz.NewMappedFile("tools/zoneinfo.zip", opts.Client.Container().From(fmt.Sprintf("golang:%s", t.GoVersion)).File("/usr/local/go/lib/time/zoneinfo.zip")), + } + + directories := []targz.MappedDirectory{ + targz.NewMappedDir("conf", grafanaDir.Directory("conf")), + targz.NewMappedDir("docs/sources", grafanaDir.Directory("docs/sources")), + targz.NewMappedDir("packaging/deb", grafanaDir.Directory("packaging/deb")), + targz.NewMappedDir("packaging/rpm", grafanaDir.Directory("packaging/rpm")), + targz.NewMappedDir("packaging/docker", grafanaDir.Directory("packaging/docker")), + targz.NewMappedDir("packaging/wrappers", grafanaDir.Directory("packaging/wrappers")), + targz.NewMappedDir("bin", backendDir), + targz.NewMappedDir("public", frontendDir), + targz.NewMappedDir("npm-artifacts", npmDir), + targz.NewMappedDir("storybook", storybookDir), + targz.NewMappedDir("plugins-bundled", pluginsDir), + } + + root := fmt.Sprintf("grafana-%s", version) + + return targz.Build( + b, + &targz.Opts{ + Root: root, + Files: files, + Directories: directories, + }, + ), nil +} + +func (t *Tarball) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("not implemented") // TODO: Implement +} + +func (t *Tarball) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (t *Tarball) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + return nil +} + +func (t *Tarball) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +func (t *Tarball) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + // Currently verifying riscv64 is unsupported (because alpine and ubuntu don't have riscv64 images yet) + // windows/darwin verification may never be supported. + os, arch := backend.OSAndArch(t.Distribution) + if os != "linux" || arch == "riscv64" { + return nil + } + + return verifyTarball(ctx, client, file, t.Grafana, t.YarnCache, t.Distribution, t.Enterprise) +} + +func (t *Tarball) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +func (t *Tarball) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + t.Backend, + t.Frontend, + t.NPMPackages, + t.BundledPlugins, + t.Storybook, + }, nil +} + +func (t *Tarball) Filename(ctx context.Context) (string, error) { + return packages.FileName(t.Name, t.Version, t.BuildID, t.Distribution, "tar.gz") +} + +func verifyTarball( + ctx context.Context, + d *dagger.Client, + pkg *dagger.File, + src *dagger.Directory, + yarnCache *dagger.CacheVolume, + distro backend.Distribution, + enterprise bool, +) error { + nodeVersion, err := frontend.NodeVersion(d, src).Stdout(ctx) + if err != nil { + return fmt.Errorf("failed to get node version from source code: %w", err) + } + + var ( + platform = backend.Platform(distro) + archive = containers.ExtractedArchive(d, pkg) + ) + + // This grafana service runs in the background for the e2e tests + service := d.Container(dagger.ContainerOpts{ + Platform: platform, + }).From("ubuntu:22.04"). + WithExec([]string{"apt-get", "update", "-yq"}). + WithExec([]string{"apt-get", "install", "-yq", "ca-certificates", "libfontconfig1"}). + WithDirectory("/src", archive). + WithWorkdir("/src") + + if err := e2e.ValidateLicense(ctx, service, "/src/LICENSE", enterprise); err != nil { + return err + } + + service = service. + WithExec([]string{"./bin/grafana", "server"}). + WithExposedPort(3000) + + if _, err := containers.ExitError(ctx, e2e.ValidatePackage(d, service.AsService(), src, yarnCache, nodeVersion)); err != nil { + return err + } + return nil +} diff --git a/pkg/build/daggerbuild/artifacts/package_zip.go b/pkg/build/daggerbuild/artifacts/package_zip.go new file mode 100644 index 00000000000..7114fc516a9 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/package_zip.go @@ -0,0 +1,113 @@ +package artifacts + +import ( + "context" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + "github.com/grafana/grafana/pkg/build/daggerbuild/zip" +) + +var ( + ZipArguments = TargzArguments + ZipFlags = TargzFlags +) + +var ZipInitializer = Initializer{ + InitializerFunc: NewZipFromString, + Arguments: TargzArguments, +} + +// PacakgeZip uses a built tar.gz package to create a .zip package for zipian based Linux distributions. +type Zip struct { + Name packages.Name + Version string + BuildID string + Distribution backend.Distribution + Enterprise bool + + Tarball *pipeline.Artifact +} + +func (d *Zip) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{ + d.Tarball, + }, nil +} + +func (d *Zip) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return zip.Builder(opts.Client), nil +} + +func (d *Zip) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + targz, err := opts.Store.File(ctx, d.Tarball) + if err != nil { + return nil, err + } + + return zip.Build(builder, targz), nil +} + +func (d *Zip) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + panic("not implemented") // TODO: Implement +} + +func (d *Zip) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return nil, nil +} + +func (d *Zip) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + return nil +} + +func (d *Zip) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +func (d *Zip) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil +} + +func (d *Zip) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (d *Zip) Filename(ctx context.Context) (string, error) { + return packages.FileName(d.Name, d.Version, d.BuildID, d.Distribution, "zip") +} + +func NewZipFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + tarball, err := NewTarballFromString(ctx, log, artifact, state) + if err != nil { + return nil, err + } + options, err := pipeline.ParseFlags(artifact, ZipFlags) + if err != nil { + return nil, err + } + p, err := GetPackageDetails(ctx, options, state) + if err != nil { + return nil, err + } + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Handler: &Zip{ + Name: p.Name, + Version: p.Version, + BuildID: p.BuildID, + Distribution: p.Distribution, + Enterprise: p.Enterprise, + Tarball: tarball, + }, + Type: pipeline.ArtifactTypeFile, + Flags: TargzFlags, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/packages.go b/pkg/build/daggerbuild/artifacts/packages.go new file mode 100644 index 00000000000..c13cf403f68 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/packages.go @@ -0,0 +1,52 @@ +package artifacts + +import ( + "context" + + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +type PackageDetails struct { + Name packages.Name + Enterprise bool + Version string + BuildID string + Distribution backend.Distribution +} + +func GetPackageDetails(ctx context.Context, options *pipeline.OptionsHandler, state pipeline.StateHandler) (PackageDetails, error) { + distro, err := options.String(flags.Distribution) + if err != nil { + return PackageDetails{}, err + } + version, err := state.String(ctx, arguments.Version) + if err != nil { + return PackageDetails{}, err + } + buildID, err := state.String(ctx, arguments.BuildID) + if err != nil { + return PackageDetails{}, err + } + + name, err := options.String(flags.PackageName) + if err != nil { + return PackageDetails{}, err + } + + enterprise, err := options.Bool(flags.Enterprise) + if err != nil { + return PackageDetails{}, err + } + + return PackageDetails{ + Name: packages.Name(name), + Version: version, + BuildID: buildID, + Distribution: backend.Distribution(distro), + Enterprise: enterprise, + }, nil +} diff --git a/pkg/build/daggerbuild/artifacts/parse_args.go b/pkg/build/daggerbuild/artifacts/parse_args.go new file mode 100644 index 00000000000..b3c62780eff --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/parse_args.go @@ -0,0 +1,76 @@ +package artifacts + +import ( + "context" + "errors" + "fmt" + "log/slog" + "strings" + + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + ErrorArtifactCollision = errors.New("artifact argument specifies two different artifacts") + ErrorDuplicateArgument = errors.New("artifact argument specifies duplicate or incompatible arguments") + ErrorNoArtifact = errors.New("could not find compatible artifact for argument string") + + ErrorFlagNotFound = errors.New("no option available for the given flag") +) + +func findInitializer(val string, initializers map[string]Initializer) (Initializer, error) { + c := strings.Split(val, ":") + var initializer *Initializer + + // Find the artifact that is requested by `val`. + // The artifact can be defined anywhere in the artifact string. Example: `linux/amd64:grafana:targz` or `linux/amd64:grafana:targz` are the same, where targz is the artifact. + for _, v := range c { + n, ok := initializers[v] + if !ok { + continue + } + if initializer != nil { + return Initializer{}, fmt.Errorf("%s: %w", val, ErrorArtifactCollision) + } + + initializer = &n + } + + if initializer == nil { + return Initializer{}, fmt.Errorf("%s: %w", val, ErrorNoArtifact) + } + + return *initializer, nil +} + +// The ArtifactsFromStrings function should provide all of the necessary arguments to produce each artifact +// dleimited by colons. It's a repeated flag, so all permutations are stored in 1 instance of the ArtifactsFlag struct. +// Examples: +// * targz:linux/amd64 -- Will produce a "Grafana" tar.gz for "linux/amd64". +// * targz:enterprise:linux/amd64 -- Will produce a "Grafana" tar.gz for "linux/amd64". +func ArtifactsFromStrings(ctx context.Context, log *slog.Logger, a []string, registered map[string]Initializer, state pipeline.StateHandler) ([]*pipeline.Artifact, error) { + artifacts := make([]*pipeline.Artifact, len(a)) + for i, v := range a { + n, err := Parse(ctx, log, v, registered, state) + if err != nil { + return nil, err + } + + artifacts[i] = n + } + + return artifacts, nil +} + +// Parse parses the artifact string `artifact` and finds the matching initializer. +func Parse(ctx context.Context, log *slog.Logger, artifact string, initializers map[string]Initializer, state pipeline.StateHandler) (*pipeline.Artifact, error) { + artifact = strings.TrimSpace(artifact) + initializer, err := findInitializer(artifact, initializers) + if err != nil { + return nil, err + } + + initializerFunc := initializer.InitializerFunc + // TODO soon, the initializer might need more info about flags + return initializerFunc(ctx, log, artifact, state) +} diff --git a/pkg/build/daggerbuild/artifacts/parse_args_test.go b/pkg/build/daggerbuild/artifacts/parse_args_test.go new file mode 100644 index 00000000000..a5747b2234b --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/parse_args_test.go @@ -0,0 +1,38 @@ +package artifacts_test + +// var TestArtifact struct { +// } +// +// func TestParse(t *testing.T) { +// v := "artifact:flag1:flag2" +// +// exampleArtifact := &pipeline.Artifact{ +// Name: "example", +// } +// +// argument1 := &pipeline.Argument{ +// Name: "argument1", +// } +// +// argument2 := &pipeline.Argument{ +// Name: "argument2", +// } +// +// res, err := artifacts.Parse(v, map[string]artifacts.ArgumentOption{ +// "artifact": {Artifact: exampleArtifact}, +// "argument1": {Arguments: []*pipeline.Argument{argument1}}, +// "argument2": {Arguments: []*pipeline.Argument{argument2}}, +// }) +// +// if err != nil { +// t.Fatal(err) +// } +// +// if res.Artifact.Name != exampleArtifact.Name { +// t.Fatal("Parse should return the example artifact") +// } +// +// if len(res.Arguments) != 2 { +// t.Fatal("Parse should return 2 Arguments") +// } +// } diff --git a/pkg/build/daggerbuild/artifacts/plugins_bundled.go b/pkg/build/daggerbuild/artifacts/plugins_bundled.go new file mode 100644 index 00000000000..a2ef5e311ba --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/plugins_bundled.go @@ -0,0 +1,91 @@ +package artifacts + +import ( + "context" + "log/slog" + "path" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + BundledPluginsFlags = flags.PackageNameFlags + BundledPluginsArguments = []pipeline.Argument{ + arguments.YarnCacheDirectory, + } +) + +type BundledPlugins struct { + Name packages.Name + Src *dagger.Directory + YarnCache *dagger.CacheVolume + Version string +} + +// The frontend does not have any artifact dependencies. +func (f *BundledPlugins) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return nil, nil +} + +// Builder will return a node.js alpine container that matches the .nvmrc in the Grafana source repository +func (f *BundledPlugins) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return FrontendBuilder(ctx, f.Src, f.YarnCache, opts) +} + +func (f *BundledPlugins) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + panic("not implemented") // BundledPlugins doesn't return a file +} + +func (f *BundledPlugins) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + return frontend.BuildPlugins(builder), nil +} + +func (f *BundledPlugins) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return nil, nil +} + +func (f *BundledPlugins) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (f *BundledPlugins) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + return nil +} + +func (f *BundledPlugins) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil +} + +func (f *BundledPlugins) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (f *BundledPlugins) Filename(ctx context.Context) (string, error) { + // Important note: this path is only used in two ways: + // 1. When requesting an artifact be built and exported, this is the path where it will be exported to + // 2. In a map to distinguish when the same artifact is being built more than once + return path.Join("bin", "bundled-plugins"), nil +} + +func NewBundledPlugins(ctx context.Context, log *slog.Logger, artifact string, src *dagger.Directory, version string, cacheVolume *dagger.CacheVolume) (*pipeline.Artifact, error) { + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeDirectory, + Flags: BundledPluginsFlags, + Handler: &BundledPlugins{ + Src: src, + YarnCache: cacheVolume, + Version: version, + }, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/registerer.go b/pkg/build/daggerbuild/artifacts/registerer.go new file mode 100644 index 00000000000..96c1615dd58 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/registerer.go @@ -0,0 +1,13 @@ +package artifacts + +import "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + +type Initializer struct { + InitializerFunc pipeline.ArtifactInitializer + Arguments []pipeline.Argument +} + +type Registerer interface { + Register(string, Initializer) error + Initializers() map[string]Initializer +} diff --git a/pkg/build/daggerbuild/artifacts/storage.go b/pkg/build/daggerbuild/artifacts/storage.go new file mode 100644 index 00000000000..33378d0db5c --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/storage.go @@ -0,0 +1 @@ +package artifacts diff --git a/pkg/build/daggerbuild/artifacts/storybook.go b/pkg/build/daggerbuild/artifacts/storybook.go new file mode 100644 index 00000000000..f2964d573f1 --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/storybook.go @@ -0,0 +1,113 @@ +package artifacts + +import ( + "context" + "log/slog" + "path/filepath" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/flags" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + StorybookFlags = flags.PackageNameFlags + StorybookArguments = []pipeline.Argument{ + arguments.YarnCacheDirectory, + } +) + +var StorybookInitializer = Initializer{ + InitializerFunc: NewStorybookFromString, + Arguments: StorybookArguments, +} + +type Storybook struct { + Src *dagger.Directory + YarnCache *dagger.CacheVolume + Version string +} + +// The frontend does not have any artifact dependencies. +func (f *Storybook) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return nil, nil +} + +// Builder will return a node.js alpine container that matches the .nvmrc in the Grafana source repository +func (f *Storybook) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return FrontendBuilder(ctx, f.Src, f.YarnCache, opts) +} + +func (f *Storybook) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + // Not a file + return nil, nil +} + +func (f *Storybook) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + return frontend.Storybook(builder, f.Src, f.Version), nil +} + +func (f *Storybook) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") // TODO: Implement +} + +func (f *Storybook) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + panic("not implemented") // TODO: Implement +} + +func (f *Storybook) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +func (f *Storybook) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + // Not a file + return nil +} + +func (f *Storybook) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + return nil +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (f *Storybook) Filename(ctx context.Context) (string, error) { + // Important note: this path is only used in two ways: + // 1. When requesting an artifact be built and exported, this is the path where it will be exported to + // 2. In a map to distinguish when the same artifact is being built more than once + return filepath.Join(f.Version, "storybook"), nil +} + +func NewStorybookFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + grafanaDir, err := GrafanaDir(ctx, state, false) + if err != nil { + return nil, err + } + cacheDir, err := state.CacheVolume(ctx, arguments.YarnCacheDirectory) + if err != nil { + return nil, err + } + version, err := state.String(ctx, arguments.Version) + if err != nil { + return nil, err + } + + return NewStorybook(ctx, log, artifact, grafanaDir, version, cacheDir) +} + +func NewStorybook(ctx context.Context, log *slog.Logger, artifact string, src *dagger.Directory, version string, cache *dagger.CacheVolume) (*pipeline.Artifact, error) { + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeDirectory, + Flags: StorybookFlags, + Handler: &Storybook{ + Src: src, + YarnCache: cache, + Version: version, + }, + }) +} diff --git a/pkg/build/daggerbuild/artifacts/sync_writer.go b/pkg/build/daggerbuild/artifacts/sync_writer.go new file mode 100644 index 00000000000..ff3aa0baa6f --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/sync_writer.go @@ -0,0 +1,31 @@ +package artifacts + +import ( + "io" + "os" + "sync" +) + +// SyncWriter wraps a writer and makes its writes synchronous, preventing multiple threads writing to the same writer +// from creating wacky looking output. +type SyncWriter struct { + Writer io.Writer + + mutex *sync.Mutex +} + +func NewSyncWriter(w io.Writer) *SyncWriter { + return &SyncWriter{ + Writer: w, + mutex: &sync.Mutex{}, + } +} + +func (w *SyncWriter) Write(b []byte) (int, error) { + w.mutex.Lock() + defer w.mutex.Unlock() + + return w.Writer.Write(b) +} + +var Stdout = NewSyncWriter(os.Stdout) diff --git a/pkg/build/daggerbuild/artifacts/version.go b/pkg/build/daggerbuild/artifacts/version.go new file mode 100644 index 00000000000..afc51bc2f6a --- /dev/null +++ b/pkg/build/daggerbuild/artifacts/version.go @@ -0,0 +1,94 @@ +package artifacts + +import ( + "context" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var ( + VersionArguments = []pipeline.Argument{ + arguments.GrafanaDirectory, + arguments.Version, + } + + VersionFlags = TargzFlags +) + +var VersionInitializer = Initializer{ + InitializerFunc: NewVersionFromString, + Arguments: VersionArguments, +} + +type Version struct { + // Version is embedded in the binary at build-time + Version string +} + +func (b *Version) Builder(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return opts.Client.Container().WithNewFile("/VERSION", b.Version), nil +} + +func (b *Version) Dependencies(ctx context.Context) ([]*pipeline.Artifact, error) { + return []*pipeline.Artifact{}, nil +} + +func (b *Version) BuildFile(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.File, error) { + return builder.File("/VERSION"), nil +} + +func (b *Version) BuildDir(ctx context.Context, builder *dagger.Container, opts *pipeline.ArtifactContainerOpts) (*dagger.Directory, error) { + return nil, nil +} + +func (b *Version) Publisher(ctx context.Context, opts *pipeline.ArtifactContainerOpts) (*dagger.Container, error) { + return nil, nil +} + +func (b *Version) PublishFile(ctx context.Context, opts *pipeline.ArtifactPublishFileOpts) error { + return nil +} + +func (b *Version) PublishDir(ctx context.Context, opts *pipeline.ArtifactPublishDirOpts) error { + panic("not implemented") // TODO: Implement +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (b *Version) Filename(ctx context.Context) (string, error) { + return "VERSION", nil +} + +func (b *Version) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + return nil +} + +func (b *Version) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + return nil +} + +func NewVersionFromString(ctx context.Context, log *slog.Logger, artifact string, state pipeline.StateHandler) (*pipeline.Artifact, error) { + version, err := state.String(ctx, arguments.Version) + if err != nil { + return nil, err + } + + return NewVersion(ctx, log, artifact, version) +} + +func NewVersion(ctx context.Context, log *slog.Logger, artifact, version string) (*pipeline.Artifact, error) { + return pipeline.ArtifactWithLogging(ctx, log, &pipeline.Artifact{ + ArtifactString: artifact, + Type: pipeline.ArtifactTypeFile, + Flags: VersionFlags, + Handler: &Version{ + Version: version, + }, + }) +} diff --git a/pkg/build/daggerbuild/backend/build.go b/pkg/build/daggerbuild/backend/build.go new file mode 100644 index 00000000000..2b55f829838 --- /dev/null +++ b/pkg/build/daggerbuild/backend/build.go @@ -0,0 +1,94 @@ +package backend + +import ( + "fmt" + "log" + "path" + "strings" + + "dagger.io/dagger" +) + +type LDFlag struct { + Name string + Values []string +} + +func GoLDFlags(flags []LDFlag) string { + ldflags := strings.Builder{} + for _, v := range flags { + if v.Values == nil { + ldflags.WriteString(v.Name + " ") + continue + } + + for _, value := range v.Values { + // For example, "-X 'main.version=v1.0.0'" + ldflags.WriteString(fmt.Sprintf(`%s \"%s\" `, v.Name, value)) + } + } + + return ldflags.String() +} + +// GoBuildCommand returns the arguments for go build to be used in 'WithExec'. +func GoBuildCommand(output string, ldflags []LDFlag, tags []string, main string) []string { + args := []string{"go", "build", "-v", "-x", + fmt.Sprintf("-ldflags=\"%s\"", GoLDFlags(ldflags)), + fmt.Sprintf("-o=%s", output), + "-trimpath", + fmt.Sprintf("-tags=%s", strings.Join(tags, ",")), + // Go is weird and paths referring to packages within a module to be prefixed with "./". + // Otherwise, the path is assumed to be relative to $GOROOT + "./" + main, + } + + return args +} + +func Build( + d *dagger.Client, + builder *dagger.Container, + src *dagger.Directory, + distro Distribution, + out string, + opts *BuildOpts, +) *dagger.Directory { + vcsinfo := GetVCSInfo(src, opts.Version, opts.Enterprise) + builder = WithVCSInfo(builder, vcsinfo, opts.Enterprise) + + ldflags := LDFlagsDynamic(vcsinfo) + + if opts.Static { + ldflags = LDFlagsStatic(vcsinfo) + } + + cmd := []string{ + "grafana", + "grafana-server", + "grafana-cli", + "grafana-example-apiserver", + } + + os, _ := OSAndArch(distro) + + for _, v := range cmd { + // Some CLI packages such as grafana-example-apiserver don't exist in earlier Grafana Versions <10.3 + // Below check skips building them as needed + pkgPath := path.Join("pkg", "cmd", v) + out := path.Join(out, v) + if os == "windows" { + out += ".exe" + } + + cmd := GoBuildCommand(out, ldflags, opts.Tags, pkgPath) + + script := fmt.Sprintf(`if [ -d %s ]; then %s; fi`, pkgPath, strings.Join(cmd, " ")) + log.Printf("Building with command '%s'", script) + + builder = builder. + WithExec([]string{"/bin/sh", "-c", script}) + } + + return builder.Directory(out) +} diff --git a/pkg/build/daggerbuild/backend/builder.go b/pkg/build/daggerbuild/backend/builder.go new file mode 100644 index 00000000000..b981beb61ee --- /dev/null +++ b/pkg/build/daggerbuild/backend/builder.go @@ -0,0 +1,196 @@ +package backend + +import ( + "errors" + "fmt" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/golang" +) + +// BuildOpts are general options that can change the way Grafana is compiled regardless of distribution. +type BuildOpts struct { + Version string + ExperimentalFlags []string + Tags []string + WireTag string + Static bool + Enterprise bool +} + +func distroOptsFunc(log *slog.Logger, distro Distribution) (DistroBuildOptsFunc, error) { + if val, ok := DistributionGoOpts[distro]; ok { + return DistroOptsLogger(log, val), nil + } + return nil, errors.New("unrecognized distribution") +} + +func WithGoEnv(log *slog.Logger, container *dagger.Container, distro Distribution, opts *BuildOpts) (*dagger.Container, error) { + fn, err := distroOptsFunc(log, distro) + if err != nil { + return nil, err + } + bopts := fn(distro, opts.ExperimentalFlags, opts.Tags) + + return containers.WithEnv(container, GoBuildEnv(bopts)), nil +} + +func WithViceroyEnv(log *slog.Logger, container *dagger.Container, distro Distribution, opts *BuildOpts) (*dagger.Container, error) { + fn, err := distroOptsFunc(log, distro) + if err != nil { + return nil, err + } + bopts := fn(distro, opts.ExperimentalFlags, opts.Tags) + + return containers.WithEnv(container, ViceroyEnv(bopts)), nil +} + +func ViceroyContainer( + d *dagger.Client, + log *slog.Logger, + distro Distribution, + goVersion string, + viceroyVersion string, + opts *BuildOpts, +) (*dagger.Container, error) { + containerOpts := dagger.ContainerOpts{ + Platform: "linux/amd64", + } + + // Instead of directly using the `arch` variable here to substitute in the GoURL, we have to be careful with the Go releases. + // Supported releases (in the names): + // * amd64 + // * armv6l + // * arm64 + goURL := golang.DownloadURL(goVersion, "amd64") + container := d.Container(containerOpts).From(fmt.Sprintf("rfratto/viceroy:%s", viceroyVersion)) + + // Install Go manually, and install make, git, and curl from the package manager. + container = container.WithExec([]string{"apt-get", "update"}). + WithExec([]string{"apt-get", "install", "-yq", "curl", "make", "git"}). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("curl -L %s | tar -C /usr/local -xzf -", goURL)}). + WithEnvVariable("PATH", "/bin:/usr/bin:/usr/local/bin:/usr/local/go/bin:/usr/osxcross/bin") + + return WithViceroyEnv(log, container, distro, opts) +} + +func GolangContainer( + d *dagger.Client, + log *slog.Logger, + goVersion string, + viceroyVersion string, + platform dagger.Platform, + distro Distribution, + opts *BuildOpts, +) (*dagger.Container, error) { + os, _ := OSAndArch(distro) + // Only use viceroy for all darwin and only windows/amd64 + if os == "darwin" || distro == DistWindowsAMD64 { + return ViceroyContainer(d, log, distro, goVersion, viceroyVersion, opts) + } + + container := golang.Container(d, platform, goVersion). + WithExec([]string{"apk", "add", "--update", "wget", "build-base", "alpine-sdk", "musl", "musl-dev", "xz"}). + WithExec([]string{"wget", "https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz"}). + WithExec([]string{"tar", "--strip-components=1", "-C", "/", "-xf", "zig-linux-x86_64-0.11.0.tar.xz"}). + WithExec([]string{"mv", "/zig", "/bin/zig"}). + // Install the toolchain specifically for armv7 until we figure out why it's crashing w/ zig container = container. + WithExec([]string{"mkdir", "/toolchain"}). + WithExec([]string{"wget", "http://musl.cc/arm-linux-musleabihf-cross.tgz", "-P", "/toolchain"}). + WithExec([]string{"tar", "-xvf", "/toolchain/arm-linux-musleabihf-cross.tgz", "-C", "/toolchain"}). + WithExec([]string{"wget", "https://musl.cc/s390x-linux-musl-cross.tgz", "-P", "/toolchain"}). + WithExec([]string{"tar", "-xvf", "/toolchain/s390x-linux-musl-cross.tgz", "-C", "/toolchain"}) + + return WithGoEnv(log, container, distro, opts) +} + +func withCue(c *dagger.Container, src *dagger.Directory) *dagger.Container { + return c. + WithDirectory("/src/cue.mod", src.Directory("cue.mod")). + WithDirectory("/src/kinds", src.Directory("kinds")). + WithDirectory("/src/packages/grafana-schema", src.Directory("packages/grafana-schema"), dagger.ContainerWithDirectoryOpts{ + Include: []string{"**/*.cue"}, + }). + WithDirectory("/src/public/app/plugins", src.Directory("public/app/plugins"), dagger.ContainerWithDirectoryOpts{ + Include: []string{"**/*.cue", "**/plugin.json"}, + }). + WithFile("/src/embed.go", src.File("embed.go")) +} + +// Builder returns the container that is used to build the Grafana backend binaries. +// The build container: +// * Will be based on rfratto/viceroy for Darwin or Windows +// * Will be based on golang:x.y.z-alpine for all other ditsros +// * Will download & cache the downloaded Go modules +// * Will run `make gen-go` on the provided Grafana source +// - With the linux/amd64 arch/os combination, regardless of what the requested distro is. +// +// * And will have all of the environment variables necessary to run `go build`. +func Builder( + d *dagger.Client, + log *slog.Logger, + distro Distribution, + opts *BuildOpts, + platform dagger.Platform, + src *dagger.Directory, + goVersion string, + viceroyVersion string, + goBuildCache *dagger.CacheVolume, + goModCache *dagger.CacheVolume, +) (*dagger.Container, error) { + var ( + version = opts.Version + ) + + // for some distros we use the golang official iamge. For others, we use viceroy. + builder, err := GolangContainer(d, log, goVersion, viceroyVersion, platform, distro, opts) + if err != nil { + return nil, err + } + + builder = builder. + WithMountedCache("/root/.cache/go", goBuildCache). + WithEnvVariable("GOCACHE", "/root/.cache/go") + + commitInfo := GetVCSInfo(src, version, opts.Enterprise) + + builder = withCue(builder, src). + WithDirectory("/src/", src, dagger.ContainerWithDirectoryOpts{ + Include: []string{"**/*.mod", "**/*.sum", "**/*.work"}, + }). + WithDirectory("/src/pkg", src.Directory("pkg")). + WithDirectory("/src/apps", src.Directory("apps")). + WithDirectory("/src/emails", src.Directory("emails")). + WithFile("/src/pkg/server/wire_gen.go", Wire(d, src, platform, goVersion, opts.WireTag)). + WithFile("/src/.buildinfo.commit", commitInfo.Commit). + WithWorkdir("/src") + + if opts.Enterprise { + builder = builder.WithFile("/src/.buildinfo.enterprise-commit", commitInfo.EnterpriseCommit) + } + + builder = golang.WithCachedGoDependencies( + builder, + goModCache, + ) + + return builder, nil +} + +func Wire(d *dagger.Client, src *dagger.Directory, platform dagger.Platform, goVersion string, wireTag string) *dagger.File { + // withCue is only required during `make gen-go` in 9.5.x or older. + return withCue(golang.Container(d, platform, goVersion), src). + WithExec([]string{"apk", "add", "make"}). + WithDirectory("/src/", src, dagger.ContainerWithDirectoryOpts{ + Include: []string{"**/*.mod", "**/*.sum", "**/*.work"}, + }). + WithDirectory("/src/pkg", src.Directory("pkg")). + WithDirectory("/src/apps", src.Directory("apps")). + WithDirectory("/src/.bingo", src.Directory(".bingo")). + WithFile("/src/Makefile", src.File("Makefile")). + WithWorkdir("/src"). + WithExec([]string{"make", "gen-go", fmt.Sprintf("WIRE_TAGS=%s", wireTag)}). + File("/src/pkg/server/wire_gen.go") +} diff --git a/pkg/build/daggerbuild/backend/distributions.go b/pkg/build/daggerbuild/backend/distributions.go new file mode 100644 index 00000000000..05322192a63 --- /dev/null +++ b/pkg/build/daggerbuild/backend/distributions.go @@ -0,0 +1,352 @@ +package backend + +import ( + "fmt" + "log/slog" + "strings" + + "dagger.io/dagger" +) + +// Distribution is a string that represents the GOOS and GOARCH environment variables joined by a "/". +// Optionally, if there is an extra argument specific to that architecture, it will be the last segment of the string. +// Examples: +// - "linux/arm/v6" = GOOS=linux, GOARCH=arm, GOARM=6 +// - "linux/arm/v7" = GOOS=linux, GOARCH=arm, GOARM=7 +// - "linux/amd64/v7" = GOOS=linux, GOARCH=arm, GOARM=7 +// - "linux/amd64/v2" = GOOS=linux, GOARCH=amd64, GOAMD64=v2 +// The list of distributions is built from the command "go tool dist list". +// While not all are used, it at least represents the possible combinations. +type Distribution string + +const ( + DistDarwinAMD64 Distribution = "darwin/amd64" + DistDarwinAMD64v1 Distribution = "darwin/amd64/v1" + DistDarwinAMD64v2 Distribution = "darwin/amd64/v2" + DistDarwinAMD64v3 Distribution = "darwin/amd64/v3" + DistDarwinAMD64v4 Distribution = "darwin/amd64/v4" + DistDarwinARM64 Distribution = "darwin/arm64" +) + +const ( + DistFreeBSD386 Distribution = "freebsd/386" + DistFreeBSD386SSE2 Distribution = "freebsd/386/sse2" + DistFreeBSD386SoftFloat Distribution = "freebsd/386/softfloat" + DistFreeBSDAMD64 Distribution = "freebsd/amd64" + DistFreeBSDAMD64v1 Distribution = "freebsd/amd64/v1" + DistFreeBSDAMD64v2 Distribution = "freebsd/amd64/v2" + DistFreeBSDAMD64v3 Distribution = "freebsd/amd64/v3" + DistFreeBSDAMD64v4 Distribution = "freebsd/amd64/v4" + DistFreeBSDARM Distribution = "freebsd/arm" + DistFreeBSDARM64 Distribution = "freebsd/arm64" + DistFreeBSDRISCV Distribution = "freebsd/riscv64" +) + +const ( + DistIllumosAMD64 Distribution = "illumos/amd64" + DistIllumosAMD64v1 Distribution = "illumos/amd64/v1" + DistIllumosAMD64v2 Distribution = "illumos/amd64/v2" + DistIllumosAMD64v3 Distribution = "illumos/amd64/v3" + DistIllumosAMD64v4 Distribution = "illumos/amd64/v4" +) +const ( + DistLinux386 Distribution = "linux/386" + DistLinux386SSE2 Distribution = "linux/386/sse2" + DistLinux386SoftFloat Distribution = "linux/386/softfloat" + DistLinuxAMD64 Distribution = "linux/amd64" + DistLinuxAMD64v1 Distribution = "linux/amd64/v1" + DistLinuxAMD64v2 Distribution = "linux/amd64/v2" + DistLinuxAMD64v3 Distribution = "linux/amd64/v3" + DistLinuxAMD64v4 Distribution = "linux/amd64/v4" + DistLinuxAMD64Dynamic Distribution = "linux/amd64/dynamic" + DistLinuxAMD64DynamicMusl Distribution = "linux/amd64/dynamic-musl" + DistLinuxARM Distribution = "linux/arm" + DistLinuxARMv6 Distribution = "linux/arm/v6" + DistLinuxARMv7 Distribution = "linux/arm/v7" + DistLinuxARM64 Distribution = "linux/arm64" + DistLinuxARM64Dynamic Distribution = "linux/arm64/dynamic" + DistLinuxLoong64 Distribution = "linux/loong64" + DistLinuxMips Distribution = "linux/mips" + DistLinuxMips64 Distribution = "linux/mips64" + DistLinuxMips64le Distribution = "linux/mips64le" + DistLinuxMipsle Distribution = "linux/mipsle" + DistLinuxPPC64 Distribution = "linux/ppc64" + DistLinuxPPC64le Distribution = "linux/ppc64le" + DistLinuxRISCV64 Distribution = "linux/riscv64" + DistLinuxS390X Distribution = "linux/s390x" +) + +const ( + DistOpenBSD386 Distribution = "openbsd/386" + DistOpenBSD386SSE2 Distribution = "openbsd/386/sse2" + DistOpenBSD386SoftFLoat Distribution = "openbsd/386/softfloat" + DistOpenBSDAMD64 Distribution = "openbsd/amd64" + DistOpenBSDAMD64v1 Distribution = "openbsd/amd64/v1" + DistOpenBSDAMD64v2 Distribution = "openbsd/amd64/v2" + DistOpenBSDAMD64v3 Distribution = "openbsd/amd64/v3" + DistOpenBSDAMD64v4 Distribution = "openbsd/amd64/v4" + DistOpenBSDARM Distribution = "openbsd/arm" + DistOpenBSDARMv6 Distribution = "openbsd/arm/v6" + DistOpenBSDARMv7 Distribution = "openbsd/arm/v7" + DistOpenBSDARM64 Distribution = "openbsd/arm64" + DistOpenBSDMips64 Distribution = "openbsd/mips64" +) + +const ( + DistPlan9386 Distribution = "plan9/386" + DistPlan9386SSE2 Distribution = "plan9/386/sse2" + DistPlan9386SoftFloat Distribution = "plan9/386/softfloat" + DistPlan9AMD64 Distribution = "plan9/amd64" + DistPlan9AMD64v1 Distribution = "plan9/amd64/v1" + DistPlan9AMD64v2 Distribution = "plan9/amd64/v2" + DistPlan9AMD64v3 Distribution = "plan9/amd64/v3" + DistPlan9AMD64v4 Distribution = "plan9/amd64/v4" + DistPlan9ARM Distribution = "plan9/arm/v6" + DistPlan9ARMv6 Distribution = "plan9/arm/v6" + DistPlan9ARMv7 Distribution = "plan9/arm/v7" +) + +const ( + DistSolarisAMD64 Distribution = "solaris/amd64" + DistSolarisAMD64v1 Distribution = "solaris/amd64/v1" + DistSolarisAMD64v2 Distribution = "solaris/amd64/v2" + DistSolarisAMD64v3 Distribution = "solaris/amd64/v3" + DistSolarisAMD64v4 Distribution = "solaris/amd64/v4" +) + +const ( + DistWindows386 Distribution = "windows/386" + DistWindows386SSE2 Distribution = "windows/386/sse2" + DistWindows386SoftFloat Distribution = "windows/386/softfloat" + DistWindowsAMD64 Distribution = "windows/amd64" + DistWindowsAMD64v1 Distribution = "windows/amd64/v1" + DistWindowsAMD64v2 Distribution = "windows/amd64/v2" + DistWindowsAMD64v3 Distribution = "windows/amd64/v3" + DistWindowsAMD64v4 Distribution = "windows/amd64/v4" + DistWindowsARM Distribution = "windows/arm" + DistWindowsARMv6 Distribution = "windows/arm/v6" + DistWindowsARMv7 Distribution = "windows/arm/v7" + DistWindowsARM64 Distribution = "windows/arm64" +) + +func IsWindows(d Distribution) bool { + return strings.Split(string(d), "/")[0] == "windows" +} + +func OSAndArch(d Distribution) (string, string) { + p := strings.Split(string(d), "/") + if len(p) < 2 { + return string(d), "" + } + return p[0], p[1] +} + +func FullArch(d Distribution) string { + p := strings.Split(string(d), "/") + return strings.Join(p[1:], "/") +} + +func ArchVersion(d Distribution) string { + p := strings.Split(string(d), "/") + if len(p) < 3 { + return "" + } + + // ARM specifically must be specified without a 'v' prefix. + // GOAMD64, however, expects a 'v' prefix. + // Specifying the ARM version with the 'v' prefix and without is supported in Docker's platform argument, however. + if arch := p[1]; arch == "arm" { + return strings.TrimPrefix(p[2], "v") + } + + return p[2] +} + +func PackageArch(d Distribution) string { + _, arch := OSAndArch(d) + + if arch == "arm" { + return "armhf" + } + + return arch +} + +// From the distribution, try to assume the docker platform (used in Docker's --platform argument or the (dagger.ContainerOpts).Platform field +func Platform(d Distribution) dagger.Platform { + p := strings.ReplaceAll(string(d), "/dynamic-musl", "") + p = strings.ReplaceAll(p, "/dynamic", "") + p = strings.ReplaceAll(p, "arm/v6", "arm/v7") + // for now let's just try to use the distro name as the platform and see if that works... + return dagger.Platform(p) +} + +type DistroBuildOptsFunc func(distro Distribution, experiments []string, tags []string) *GoBuildOpts + +func LDFlagsStatic(info *VCSInfo) []LDFlag { + return []LDFlag{ + {"-w", nil}, + {"-s", nil}, + {"-X", info.X()}, + {"-linkmode=external", nil}, + {"-extldflags=-static", nil}, + } +} + +func LDFlagsDynamic(info *VCSInfo) []LDFlag { + return []LDFlag{ + {"-X", info.X()}, + } +} + +func ZigCC(distro Distribution) string { + target, ok := ZigTargets[distro] + if !ok { + target = "x86_64-linux-musl" // best guess? should probably retun an error but i don't want to + } + + return fmt.Sprintf("zig cc -target %s", target) +} + +func ZigCXX(distro Distribution) string { + target, ok := ZigTargets[distro] + if !ok { + target = "x86_64-linux-musl" // best guess? should probably retun an error but i don't want to + } + + return fmt.Sprintf("zig c++ -target %s", target) +} + +var DefaultBuildOpts = func(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + os, arch := OSAndArch(distro) + + return &GoBuildOpts{ + CC: ZigCC(distro), + CXX: ZigCXX(distro), + ExperimentalFlags: experiments, + OS: os, + Arch: arch, + CGOEnabled: true, + } +} + +// BuildOptsStaticARM builds Grafana statically for the armv6/v7 architectures (not aarch64/arm64) +func BuildOptsStaticARM(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + var ( + os, _ = OSAndArch(distro) + arm = ArchVersion(distro) + ) + + return &GoBuildOpts{ + CC: "/toolchain/arm-linux-musleabihf-cross/bin/arm-linux-musleabihf-gcc", + CXX: "/toolchain/arm-linux-musleabihf-cross/bin/arm-linux-musleabihf-cpp", + ExperimentalFlags: experiments, + OS: os, + Arch: "arm", + GoARM: GoARM(arm), + CGOEnabled: true, + } +} + +// BuildOptsStaticS390X builds Grafana statically for the s390x arch +func BuildOptsStaticS390X(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + var ( + os, _ = OSAndArch(distro) + ) + + return &GoBuildOpts{ + CC: "/toolchain/s390x-linux-musl-cross/bin/s390x-linux-musl-gcc", + CXX: "/toolchain/s390x-linux-musl-cross/bin/s390x-linux-musl-cpp", + ExperimentalFlags: experiments, + OS: os, + Arch: "s390x", + CGOEnabled: true, + } +} + +func StdZigBuildOpts(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + var ( + os, arch = OSAndArch(distro) + ) + + return &GoBuildOpts{ + CC: ZigCC(distro), + CXX: ZigCXX(distro), + ExperimentalFlags: experiments, + OS: os, + Arch: arch, + CGOEnabled: true, + } +} + +func BuildOptsWithoutZig(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + var ( + os, arch = OSAndArch(distro) + ) + + return &GoBuildOpts{ + ExperimentalFlags: experiments, + OS: os, + Arch: arch, + CGOEnabled: true, + } +} + +func ViceroyBuildOpts(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + var ( + os, arch = OSAndArch(distro) + ) + + return &GoBuildOpts{ + CC: "viceroycc", + ExperimentalFlags: experiments, + OS: os, + Arch: arch, + CGOEnabled: true, + } +} + +var ZigTargets = map[Distribution]string{ + DistLinuxAMD64: "x86_64-linux-musl", + DistLinuxAMD64Dynamic: "x86_64-linux-gnu", + DistLinuxAMD64DynamicMusl: "x86_64-linux-musl", + DistLinuxARM64: "aarch64-linux-musl", + DistLinuxARM64Dynamic: "aarch64-linux-musl", + DistLinuxARM: "arm-linux-musleabihf", + DistLinuxARMv6: "arm-linux-musleabihf", + DistLinuxARMv7: "arm-linux-musleabihf", + DistLinuxRISCV64: "riscv64-linux-musl", + DistWindowsAMD64: "x86_64-windows-gnu", + DistWindowsARM64: "aarch64-windows-gnu", +} + +var DistributionGoOpts = map[Distribution]DistroBuildOptsFunc{ + // The Linux distros should all have an equivalent zig target in the ZigTargets map + DistLinuxARM: BuildOptsStaticARM, + DistLinuxARMv6: BuildOptsStaticARM, + DistLinuxARMv7: BuildOptsStaticARM, + DistLinuxS390X: BuildOptsStaticS390X, + DistLinuxARM64: StdZigBuildOpts, + DistLinuxARM64Dynamic: StdZigBuildOpts, + DistLinuxAMD64: StdZigBuildOpts, + DistLinuxAMD64Dynamic: StdZigBuildOpts, + DistPlan9AMD64: StdZigBuildOpts, + DistLinuxRISCV64: StdZigBuildOpts, + + // Non-Linux distros can have whatever they want in CC and CXX; it'll get overridden + // but it's probably not best to rely on that. + DistWindowsAMD64: ViceroyBuildOpts, + DistWindowsARM64: StdZigBuildOpts, + DistDarwinAMD64: ViceroyBuildOpts, + DistDarwinARM64: ViceroyBuildOpts, + + DistLinuxAMD64DynamicMusl: BuildOptsWithoutZig, +} + +func DistroOptsLogger(log *slog.Logger, fn DistroBuildOptsFunc) func(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + return func(distro Distribution, experiments []string, tags []string) *GoBuildOpts { + opts := fn(distro, experiments, tags) + log.Debug("Building with options", "distribution", distro, "experiments", experiments, "tags", tags, "os", opts.OS, "arch", opts.Arch, "arm", opts.GoARM, "CGO", opts.CGOEnabled, "386", opts.Go386, "CC", opts.CC, "CXX", opts.CXX) + return opts + } +} diff --git a/pkg/build/daggerbuild/backend/doc.go b/pkg/build/daggerbuild/backend/doc.go new file mode 100644 index 00000000000..064d0c7d169 --- /dev/null +++ b/pkg/build/daggerbuild/backend/doc.go @@ -0,0 +1,2 @@ +// Package backend holds the functions that create containers, files, and directories for building Grafana's backend binaries. +package backend diff --git a/pkg/build/daggerbuild/backend/env.go b/pkg/build/daggerbuild/backend/env.go new file mode 100644 index 00000000000..27d3cf59010 --- /dev/null +++ b/pkg/build/daggerbuild/backend/env.go @@ -0,0 +1,140 @@ +package backend + +import ( + "strings" + + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +type ( + BuildMode string + GoARM string + GoAMD64 string + Go386 string + LibC int +) + +const ( + BuildModeDefault BuildMode = "default" + BuildModeExe BuildMode = "exe" +) + +const ( + GOARM5 GoARM = "5" + GOARM6 GoARM = "6" + GOARM7 GoARM = "7" +) + +const ( + Go386SSE2 Go386 = "sse2" + Go386SoftFloat Go386 = "softfloat" +) + +const ( + Musl LibC = iota + GLibC +) + +type GoBuildOpts struct { + // OS is value supplied to the GOOS environment variable + OS string + + // Arch is value supplied to the GOARCH environment variable + Arch string + + // ExperimentalFlags are Go build-time feature flags in the "GOEXPERIMENT" environment variable that enable experimental features. + ExperimentalFlags []string + + // CGOEnabled defines whether or not the CGO_ENABLED flag is set. + CGOEnabled bool + + // GOARM: For GOARCH=arm, the ARM architecture for which to compile. + // Valid values are 5, 6, 7. + GoARM GoARM + + // GO386: For GOARCH=386, how to implement floating point instructions. + // Valid values are sse2 (default), softfloat. + Go386 Go386 + + // CC is the command to use to compile C code when CGO is enabled. (Sets the "CC" environment variable) + CC string + + // CXX is the command to use to compile C++ code when CGO is enabled. (Sets the "CXX" environment variable) + CXX string +} + +// GoBuildEnv returns the environment variables that must be set for a 'go build' command given the provided 'GoBuildOpts'. +func GoBuildEnv(opts *GoBuildOpts) []containers.Env { + var ( + os = opts.OS + arch = opts.Arch + ) + + env := []containers.Env{containers.EnvVar("GOOS", os), containers.EnvVar("GOARCH", arch)} + + if arch == "arm" { + env = append(env, containers.EnvVar("GOARM", string(opts.GoARM))) + } + + if opts.CGOEnabled { + env = append(env, containers.EnvVar("GOARM", string(opts.GoARM))) + env = append(env, containers.EnvVar("CGO_ENABLED", "1")) + + // https://github.com/mattn/go-sqlite3/issues/1164#issuecomment-1635253695 + env = append(env, containers.EnvVar("CGO_CFLAGS", "-D_LARGEFILE64_SOURCE")) + } else { + env = append(env, containers.EnvVar("CGO_ENABLED", "0")) + } + + if opts.ExperimentalFlags != nil { + env = append(env, containers.EnvVar("GOEXPERIMENT", strings.Join(opts.ExperimentalFlags, ","))) + } + + if opts.CC != "" { + env = append(env, containers.EnvVar("CC", opts.CC)) + } + + if opts.CXX != "" { + env = append(env, containers.EnvVar("CXX", opts.CXX)) + } + + return env +} + +// ViceroyEnv returns the environment variables that must be set for a 'go build' command given the provided 'GoBuildOpts'. +func ViceroyEnv(opts *GoBuildOpts) []containers.Env { + var ( + os = opts.OS + arch = opts.Arch + ) + + env := []containers.Env{ + containers.EnvVar("VICEROYOS", os), + containers.EnvVar("GOOS", os), + containers.EnvVar("VICEROYARCH", arch), + containers.EnvVar("GOARCH", arch), + } + + if arch == "arm" { + env = append(env, containers.EnvVar("VICEROYARM", string(opts.GoARM))) + } + + if opts.CGOEnabled { + env = append(env, containers.EnvVar("CGO_ENABLED", "1")) + + // https://github.com/mattn/go-sqlite3/issues/1164#issuecomment-1635253695 + env = append(env, containers.EnvVar("CGO_CFLAGS", "-D_LARGEFILE64_SOURCE")) + } else { + env = append(env, containers.EnvVar("CGO_ENABLED", "0")) + } + + if opts.ExperimentalFlags != nil { + env = append(env, containers.EnvVar("GOEXPERIMENT", strings.Join(opts.ExperimentalFlags, ","))) + } + + if opts.CC != "" { + env = append(env, containers.EnvVar("CC", "viceroycc")) + } + + return env +} diff --git a/pkg/build/daggerbuild/backend/vcsinfo.go b/pkg/build/daggerbuild/backend/vcsinfo.go new file mode 100644 index 00000000000..c53e9c529cf --- /dev/null +++ b/pkg/build/daggerbuild/backend/vcsinfo.go @@ -0,0 +1,56 @@ +package backend + +import ( + "fmt" + "strings" + + "dagger.io/dagger" +) + +type VCSInfo struct { + Version string + Commit *dagger.File + EnterpriseCommit *dagger.File + Branch *dagger.File +} + +func WithVCSInfo(c *dagger.Container, info *VCSInfo, enterprise bool) *dagger.Container { + c = c. + WithFile(".buildinfo.commit", info.Commit). + WithFile(".buildinfo.branch", info.Branch) + + if enterprise { + return c.WithFile(".buildinfo.enterprise-commit", info.EnterpriseCommit) + } + + return c +} + +// VCSInfo gets the VCS data from the directory 'src', writes them to a file on the given container, and returns the files which can be used in other containers. +func GetVCSInfo(src *dagger.Directory, version string, enterprise bool) *VCSInfo { + info := &VCSInfo{ + Version: version, + Commit: src.File(".buildinfo.commit"), + Branch: src.File(".buildinfo.branch"), + } + + if enterprise { + info.EnterpriseCommit = src.File(".buildinfo.enterprise-commit") + } + + return info +} + +func (v *VCSInfo) X() []string { + flags := []string{ + fmt.Sprintf("main.version=%s", strings.TrimPrefix(v.Version, "v")), + `main.commit=$(cat ./.buildinfo.commit)`, + `main.buildBranch=$(cat ./.buildinfo.branch)`, + } + + if v.EnterpriseCommit != nil { + flags = append(flags, `main.enterpriseCommit=$(cat ./.buildinfo.enterprise-commit)`) + } + + return flags +} diff --git a/pkg/build/daggerbuild/cliutil/context.go b/pkg/build/daggerbuild/cliutil/context.go new file mode 100644 index 00000000000..15edb3f2daa --- /dev/null +++ b/pkg/build/daggerbuild/cliutil/context.go @@ -0,0 +1,10 @@ +package cliutil + +type CLIContext interface { + Bool(string) bool + String(string) string + Set(string, string) error + StringSlice(string) []string + Path(string) string + Int64(string) int64 +} diff --git a/pkg/build/daggerbuild/cmd/app.go b/pkg/build/daggerbuild/cmd/app.go new file mode 100644 index 00000000000..f63dcea934c --- /dev/null +++ b/pkg/build/daggerbuild/cmd/app.go @@ -0,0 +1,65 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/artifacts" + "github.com/urfave/cli/v2" +) + +type CLI struct { + artifacts map[string]artifacts.Initializer +} + +func (c *CLI) ArtifactsCommand() *cli.Command { + f := artifacts.ArtifactFlags(c) + flags := make([]cli.Flag, len(f)) + copy(flags, f) + return &cli.Command{ + Name: "artifacts", + Usage: "Use this command to declare a list of artifacts to be built and/or published", + Flags: flags, + Action: artifacts.Command(c), + } +} + +func (c *CLI) App() *cli.App { + return &cli.App{ + Name: "grafana-build", + Usage: "A build tool for Grafana", + Commands: []*cli.Command{ + // Legacy commands, should eventually be completely replaced by what's in "artifacts" + { + Name: "package", + Subcommands: []*cli.Command{ + PackagePublishCommand, + }, + }, + { + Name: "docker", + Subcommands: []*cli.Command{ + DockerPublishCommand, + }, + }, + ProImageCommand, + { + Name: "npm", + Subcommands: []*cli.Command{ + PublishNPMCommand, + }, + }, + GCOMCommand, + }, + } +} + +func (c *CLI) Register(flag string, a artifacts.Initializer) error { + c.artifacts[flag] = a + return nil +} + +func (c *CLI) Initializers() map[string]artifacts.Initializer { + return c.artifacts +} + +var GlobalCLI = &CLI{ + artifacts: map[string]artifacts.Initializer{}, +} diff --git a/pkg/build/daggerbuild/cmd/artifacts.go b/pkg/build/daggerbuild/cmd/artifacts.go new file mode 100644 index 00000000000..57a04f5652a --- /dev/null +++ b/pkg/build/daggerbuild/cmd/artifacts.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/artifacts" +) + +var Artifacts = map[string]artifacts.Initializer{ + "backend": artifacts.BackendInitializer, + "frontend": artifacts.FrontendInitializer, + "npm": artifacts.NPMPackagesInitializer, + "targz": artifacts.TargzInitializer, + "zip": artifacts.ZipInitializer, + "deb": artifacts.DebInitializer, + "rpm": artifacts.RPMInitializer, + "docker": artifacts.DockerInitializer, + "docker-pro": artifacts.ProDockerInitializer, + "docker-enterprise": artifacts.EntDockerInitializer, + "storybook": artifacts.StorybookInitializer, + "msi": artifacts.MSIInitializer, + "version": artifacts.VersionInitializer, +} diff --git a/pkg/build/daggerbuild/cmd/docker_publish.go b/pkg/build/daggerbuild/cmd/docker_publish.go new file mode 100644 index 00000000000..a809e28eb80 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/docker_publish.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" + "github.com/urfave/cli/v2" +) + +var DockerPublishCommand = &cli.Command{ + Name: "publish", + Action: PipelineActionWithPackageInput(pipelines.PublishDocker), + Usage: "Using a grafana.docker.tar.gz as input (ideally one built using the 'package' command), publish a docker image and manifest", + Flags: JoinFlagsWithDefault( + PackageInputFlags, + DockerFlags, + DockerPublishFlags, + GCPFlags, + ConcurrencyFlags, + ), +} diff --git a/pkg/build/daggerbuild/cmd/flags.go b/pkg/build/daggerbuild/cmd/flags.go new file mode 100644 index 00000000000..5a2bcc63dec --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags.go @@ -0,0 +1,259 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/arguments" + "github.com/grafana/grafana/pkg/build/daggerbuild/cmd/flags" + "github.com/urfave/cli/v2" +) + +var FlagPackage = &cli.StringSliceFlag{ + Name: "package", + Usage: "Path to a grafana.tar.gz package used as input. This command will process each package provided separately and produce an equal number of applicable outputs", +} +var FlagNameOverride = &cli.StringFlag{ + Name: "name", + Usage: "Overrides any calculation for name in the package with the value provided here", +} + +// PackageInputFlags are used for commands that require a grafana package as input. +// These commands are exclusively used outside of the CI process and are typically used in the CD process where a grafana.tar.gz has already been created. +var PackageInputFlags = []cli.Flag{ + FlagPackage, + FlagNameOverride, +} + +// GCPFlags are used in commands that need to authenticate with Google Cloud platform using the Google Cloud SDK +var GCPFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "gcp-service-account-key-base64", + Usage: "Provides a service-account key encoded in base64 to use to authenticate with the Google Cloud SDK", + }, + &cli.StringFlag{ + Name: "gcp-service-account-key", + Usage: "Provides a service-account keyfile to use to authenticate with the Google Cloud SDK. If not provided or is empty, then $XDG_CONFIG_HOME/gcloud will be mounted in the container", + }, +} + +// NPMFlags are used in commands that need to authenticate with package registries to publish NPM packages +var NPMFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "registry", + Usage: "The package registry to publish packages", + Value: "registry.npmjs.org", + }, + &cli.StringFlag{ + Name: "token", + Usage: "Provides a token to use to authenticate with the package registry", + Required: true, + }, + &cli.StringSliceFlag{ + Name: "tag", + Usage: "Provides the tags to use when publishing packages", + Required: true, + }, +} + +// PublishFlags are flags that are used in commands that create artifacts. +// Anything that creates an artifact should have the option to specify a local folder destination or a remote destination. +var PublishFlags = flags.PublishFlags + +// GrafanaFlags are flags that are required when working with the grafana source code. +var GrafanaFlags = []cli.Flag{ + &cli.BoolFlag{ + Name: "grafana", + Usage: "If set, initialize Grafana", + Required: false, + Value: true, + }, + &cli.StringFlag{ + Name: "grafana-dir", + Usage: "Local Grafana dir to use, instead of git clone", + Required: false, + }, + &cli.StringFlag{ + Name: "grafana-repo", + Usage: "Grafana repo to clone, not valid if --grafana-dir is set", + Required: false, + Value: "https://github.com/grafana/grafana.git", + }, + &cli.StringFlag{ + Name: "grafana-ref", + Usage: "Grafana ref to clone, not valid if --grafana-dir is set", + Required: false, + Value: "main", + }, + &cli.BoolFlag{ + Name: "enterprise", + Usage: "If set, initialize Grafana Enterprise", + Value: false, + }, + &cli.StringFlag{ + Name: "enterprise-dir", + Usage: "Local Grafana Enterprise dir to use, instead of git clone", + Required: false, + }, + &cli.StringFlag{ + Name: "enterprise-repo", + Usage: "Grafana Enterprise repo to clone, not valid if --grafana-dir is set", + Required: false, + Value: "https://github.com/grafana/grafana-enterprise.git", + }, + &cli.StringFlag{ + Name: "enterprise-ref", + Usage: "Grafana Enterprise ref to clone, not valid if --enterprise-dir is set", + Required: false, + Value: "main", + }, + &cli.StringFlag{ + Name: "github-token", + Usage: "Github token to use for git cloning, by default will be pulled from GitHub", + Required: false, + }, + &cli.StringSliceFlag{ + Name: "env", + Aliases: []string{"e"}, + Usage: "Set a build-time environment variable using the same syntax as 'docker run'. Example: `--env=GOOS=linux --env=GOARCH=amd64`", + }, + &cli.StringSliceFlag{ + Name: "go-tags", + Usage: "Sets the go `-tags` flag when compiling the backend", + }, + &cli.StringFlag{ + Name: "go-version", + Usage: "The version of Go to be used for building the Grafana backend", + Required: false, + Value: "1.21.8", + }, + &cli.StringFlag{ + Name: "yarn-cache", + Usage: "If there is a yarn cache directory, then mount that when running 'yarn install' instead of creating a cache directory", + }, +} + +// DockerFlags are used when producing docker images. +var DockerFlags = []cli.Flag{ + arguments.DockerRegistryFlag, + arguments.AlpineImageFlag, + arguments.UbuntuImageFlag, + arguments.TagFormatFlag, + arguments.UbuntuTagFormatFlag, + arguments.DockerOrgFlag, +} + +var DockerPublishFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "username", + Usage: "The username to login to the docker registry when publishing images", + Required: true, + }, + &cli.StringFlag{ + Name: "password", + Usage: "The password to login to the docker registry when publishing images", + Required: true, + }, + &cli.StringFlag{ + Name: "repo", + Usage: "Overrides the repository of the images", + }, + &cli.BoolFlag{ + Name: "latest", + Usage: "Tags the published images as latest", + }, +} + +var FlagDistros = &cli.StringSliceFlag{ + Name: "distro", + Usage: "See the list of distributions with 'go tool dist list'. For variations of the same distribution, like 'armv6' or 'armv7', append an extra path part. Example: 'linux/arm/v6', or 'linux/amd64/v3'", + Value: cli.NewStringSlice(flags.DefaultDistros...), +} + +var ConcurrencyFlags = flags.ConcurrencyFlags + +// PackageFlags are flags that are used when building packages or similar artifacts (like binaries) for different distributions +// from the grafana source code. +var PackageFlags = []cli.Flag{ + FlagDistros, + &cli.StringFlag{ + Name: "edition", + Usage: "Simply alters the naming of the '.tar.gz' package. The string set will override the '-{flavor}' part of the package name", + }, +} + +var ProImageFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "github-token", + Usage: "Github token to use for git cloning, by default will be pulled from GitHub", + Required: false, + }, + &cli.StringFlag{ + Name: "grafana-repo", + Usage: "The Grafana repository", + Required: false, + Value: "https://github.com/grafana/grafana", + }, + &cli.StringFlag{ + Name: "grafana-version", + Usage: "The Grafana version", + Required: true, + }, + &cli.StringFlag{ + Name: "repo", + Usage: "The docker image repo", + Value: "hosted-grafana-pro", + Required: false, + }, + &cli.StringFlag{ + Name: "image-tag", + Usage: "The docker image tag", + Required: true, + }, + &cli.StringFlag{ + Name: "release-type", + Usage: "The Grafana release type", + Value: "prerelease", + }, + &cli.BoolFlag{ + Name: "push", + Usage: "Push the built image to the container registry", + Value: false, + }, + &cli.StringFlag{ + Name: "registry", + Usage: "The container registry that the image should be pushed to. Required if --push is set.", + Value: "docker.io", + }, +} + +var GCOMFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "api-url", + Usage: "API URL used in requests to grafana.com", + Value: "https://grafana.com/api/grafana", + }, + &cli.StringFlag{ + Name: "api-key", + Usage: "API Key used in requests to grafana.com", + Required: true, + }, + &cli.StringFlag{ + Name: "download-url", + Usage: "URL used to download packages from grafana.com", + Required: true, + }, + &cli.BoolFlag{ + Name: "beta", + Usage: "Use when publishing a beta version", + }, + &cli.BoolFlag{ + Name: "nightly", + Usage: "Use when publishing a nightly version", + }, +} + +// JoinFlags combines several slices of flags into one slice of flags. +var JoinFlags = flags.Join + +func JoinFlagsWithDefault(f ...[]cli.Flag) []cli.Flag { + // Kind of gross but ensures that DefaultFlags are registered before any others. + return JoinFlags(append([][]cli.Flag{flags.DefaultFlags}, f...)...) +} diff --git a/pkg/build/daggerbuild/cmd/flags/concurrency.go b/pkg/build/daggerbuild/cmd/flags/concurrency.go new file mode 100644 index 00000000000..1e018e91c3d --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/concurrency.go @@ -0,0 +1,16 @@ +package flags + +import ( + "runtime" + + "github.com/urfave/cli/v2" +) + +var ConcurrencyFlags = []cli.Flag{ + &cli.Int64Flag{ + Name: "parallel", + Usage: "The number of parallel pipelines to run. This can be particularly useful for building for multiple distributions at the same time", + DefaultText: "Just like with 'go test', this defaults to GOMAXPROCS", + Value: int64(runtime.GOMAXPROCS(0)), + }, +} diff --git a/pkg/build/daggerbuild/cmd/flags/default.go b/pkg/build/daggerbuild/cmd/flags/default.go new file mode 100644 index 00000000000..c88c27b00a9 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/default.go @@ -0,0 +1,15 @@ +package flags + +import "github.com/urfave/cli/v2" + +var Verbose = &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + Usage: "Increase log verbosity. WARNING: This setting could potentially log sensitive data", + Value: false, +} + +var DefaultFlags = []cli.Flag{ + Platform, + Verbose, +} diff --git a/pkg/build/daggerbuild/cmd/flags/defaults_darwin_amd64.go b/pkg/build/daggerbuild/cmd/flags/defaults_darwin_amd64.go new file mode 100644 index 00000000000..2817924592d --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/defaults_darwin_amd64.go @@ -0,0 +1,7 @@ +package flags + +// DefaultDistros are distributions that can quickly be built in an ideal scenario for the operating system on the above build tag. +var DefaultDistros = []string{"linux/amd64"} + +// DefaultPlatform is the docker platform that will natively / most efficiently run on the OS/arch filtered by the above tag. +var DefaultPlatform = "linux/amd64" diff --git a/pkg/build/daggerbuild/cmd/flags/defaults_darwin_arm64.go b/pkg/build/daggerbuild/cmd/flags/defaults_darwin_arm64.go new file mode 100644 index 00000000000..ff5b24531ce --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/defaults_darwin_arm64.go @@ -0,0 +1,7 @@ +package flags + +// DefaultDistros are distributions that can quickly be built in an ideal scenario for the operating system on the above build tag. +var DefaultDistros = []string{"linux/arm64"} + +// DefaultPlatform is the docker platform that will natively / most efficiently run on the OS/arch filtered by the above tag. +var DefaultPlatform = "linux/arm64" diff --git a/pkg/build/daggerbuild/cmd/flags/defaults_linux_amd64.go b/pkg/build/daggerbuild/cmd/flags/defaults_linux_amd64.go new file mode 100644 index 00000000000..2817924592d --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/defaults_linux_amd64.go @@ -0,0 +1,7 @@ +package flags + +// DefaultDistros are distributions that can quickly be built in an ideal scenario for the operating system on the above build tag. +var DefaultDistros = []string{"linux/amd64"} + +// DefaultPlatform is the docker platform that will natively / most efficiently run on the OS/arch filtered by the above tag. +var DefaultPlatform = "linux/amd64" diff --git a/pkg/build/daggerbuild/cmd/flags/defaults_linux_arm64.go b/pkg/build/daggerbuild/cmd/flags/defaults_linux_arm64.go new file mode 100644 index 00000000000..ff5b24531ce --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/defaults_linux_arm64.go @@ -0,0 +1,7 @@ +package flags + +// DefaultDistros are distributions that can quickly be built in an ideal scenario for the operating system on the above build tag. +var DefaultDistros = []string{"linux/arm64"} + +// DefaultPlatform is the docker platform that will natively / most efficiently run on the OS/arch filtered by the above tag. +var DefaultPlatform = "linux/arm64" diff --git a/pkg/build/daggerbuild/cmd/flags/defaults_windows_amd64.go b/pkg/build/daggerbuild/cmd/flags/defaults_windows_amd64.go new file mode 100644 index 00000000000..2817924592d --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/defaults_windows_amd64.go @@ -0,0 +1,7 @@ +package flags + +// DefaultDistros are distributions that can quickly be built in an ideal scenario for the operating system on the above build tag. +var DefaultDistros = []string{"linux/amd64"} + +// DefaultPlatform is the docker platform that will natively / most efficiently run on the OS/arch filtered by the above tag. +var DefaultPlatform = "linux/amd64" diff --git a/pkg/build/daggerbuild/cmd/flags/defaults_windows_arm64.go b/pkg/build/daggerbuild/cmd/flags/defaults_windows_arm64.go new file mode 100644 index 00000000000..ff5b24531ce --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/defaults_windows_arm64.go @@ -0,0 +1,7 @@ +package flags + +// DefaultDistros are distributions that can quickly be built in an ideal scenario for the operating system on the above build tag. +var DefaultDistros = []string{"linux/arm64"} + +// DefaultPlatform is the docker platform that will natively / most efficiently run on the OS/arch filtered by the above tag. +var DefaultPlatform = "linux/arm64" diff --git a/pkg/build/daggerbuild/cmd/flags/join.go b/pkg/build/daggerbuild/cmd/flags/join.go new file mode 100644 index 00000000000..79c4e3967fb --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/join.go @@ -0,0 +1,12 @@ +package flags + +import "github.com/urfave/cli/v2" + +func Join(f ...[]cli.Flag) []cli.Flag { + flags := []cli.Flag{} + for _, v := range f { + flags = append(flags, v...) + } + + return flags +} diff --git a/pkg/build/daggerbuild/cmd/flags/platform.go b/pkg/build/daggerbuild/cmd/flags/platform.go new file mode 100644 index 00000000000..893f104c75f --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/platform.go @@ -0,0 +1,9 @@ +package flags + +import "github.com/urfave/cli/v2" + +var Platform = &cli.StringFlag{ + Name: "platform", + Usage: "The buildkit / dagger platform to run containers when building the backend", + Value: DefaultPlatform, +} diff --git a/pkg/build/daggerbuild/cmd/flags/publish.go b/pkg/build/daggerbuild/cmd/flags/publish.go new file mode 100644 index 00000000000..49dac24b496 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/flags/publish.go @@ -0,0 +1,16 @@ +package flags + +import "github.com/urfave/cli/v2" + +var PublishFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "destination", + Usage: "full URL to upload the artifacts to (examples: '/tmp/package.tar.gz', 'file://package.tar.gz', 'file:///tmp/package.tar.gz', 'gs://bucket/grafana/')", + Aliases: []string{"d"}, + Value: "dist", + }, + &cli.BoolFlag{ + Name: "checksum", + Usage: "When enabled, also creates a `.sha256' checksum file in the destination that matches the checksum of the artifact(s) produced", + }, +} diff --git a/pkg/build/daggerbuild/cmd/gcom.go b/pkg/build/daggerbuild/cmd/gcom.go new file mode 100644 index 00000000000..6414cba99a6 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/gcom.go @@ -0,0 +1,11 @@ +package cmd + +import ( + "github.com/urfave/cli/v2" +) + +var GCOMCommand = &cli.Command{ + Name: "gcom", + Description: "Executes requests to grafana.com", + Subcommands: []*cli.Command{GCOMPublishCommand}, +} diff --git a/pkg/build/daggerbuild/cmd/gcom_publish.go b/pkg/build/daggerbuild/cmd/gcom_publish.go new file mode 100644 index 00000000000..0d41aa05096 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/gcom_publish.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" + "github.com/urfave/cli/v2" +) + +var GCOMPublishCommand = &cli.Command{ + Name: "publish", + Action: PipelineActionWithPackageInput(pipelines.PublishGCOM), + Description: "Publishes a grafana.tar.gz (ideally one built using the 'package' command) to grafana.com (--destination will be the download path)", + Flags: JoinFlagsWithDefault( + GCOMFlags, + PackageInputFlags, + PublishFlags, + ConcurrencyFlags, + ), +} diff --git a/pkg/build/daggerbuild/cmd/main.go b/pkg/build/daggerbuild/cmd/main.go new file mode 100644 index 00000000000..6b31194b684 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/main.go @@ -0,0 +1,47 @@ +package cmd + +import ( + "errors" + "fmt" + "os" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" + "github.com/urfave/cli/v2" +) + +// Deprecated: use the Artifact type instead +func PipelineActionWithPackageInput(pf pipelines.PipelineFuncWithPackageInput) cli.ActionFunc { + return func(c *cli.Context) error { + var ( + ctx = c.Context + opts = []dagger.ClientOpt{} + ) + if c.Bool("verbose") { + opts = append(opts, dagger.WithLogOutput(os.Stderr)) + } + client, err := dagger.Connect(ctx, opts...) + if err != nil { + return err + } + defer func(c *dagger.Client) { + if err := c.Close(); err != nil { + fmt.Println("error closing dagger client:", err) + } + }(client) + + args, err := pipelines.PipelineArgsFromContext(ctx, c) + if err != nil { + return err + } + + if len(args.PackageInputOpts.Packages) == 0 { + return errors.New("expected at least one package from a '--package' flag") + } + + if err := pf(ctx, client, args); err != nil { + return err + } + return nil + } +} diff --git a/pkg/build/daggerbuild/cmd/npm_publish.go b/pkg/build/daggerbuild/cmd/npm_publish.go new file mode 100644 index 00000000000..4a764034cca --- /dev/null +++ b/pkg/build/daggerbuild/cmd/npm_publish.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" + "github.com/urfave/cli/v2" +) + +var PublishNPMCommand = &cli.Command{ + Name: "publish", + Action: PipelineActionWithPackageInput(pipelines.PublishNPM), + Usage: "Using a grafana.tar.gz as input (ideally one built using the 'package' command), take the npm artifacts and publish them on NPM.", + Flags: JoinFlagsWithDefault( + PackageInputFlags, + NPMFlags, + GCPFlags, + ConcurrencyFlags, + ), +} diff --git a/pkg/build/daggerbuild/cmd/package_publish.go b/pkg/build/daggerbuild/cmd/package_publish.go new file mode 100644 index 00000000000..095a848ad12 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/package_publish.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" + "github.com/urfave/cli/v2" +) + +var PackagePublishCommand = &cli.Command{ + Name: "publish", + Action: PipelineActionWithPackageInput(pipelines.PublishPackage), + Description: "Publishes a grafana.tar.gz (ideally one built using the 'package' command) in the destination directory (--destination)", + Flags: JoinFlagsWithDefault( + PackageInputFlags, + PublishFlags, + GCPFlags, + ConcurrencyFlags, + ), +} diff --git a/pkg/build/daggerbuild/cmd/pro_image.go b/pkg/build/daggerbuild/cmd/pro_image.go new file mode 100644 index 00000000000..43001452244 --- /dev/null +++ b/pkg/build/daggerbuild/cmd/pro_image.go @@ -0,0 +1,13 @@ +package cmd + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" + "github.com/urfave/cli/v2" +) + +var ProImageCommand = &cli.Command{ + Name: "pro-image", + Action: PipelineActionWithPackageInput(pipelines.ProImage), + Description: "Creates a hosted grafana pro image", + Flags: JoinFlagsWithDefault(ProImageFlags, GCPFlags, PackageInputFlags), +} diff --git a/pkg/build/daggerbuild/containers/docs.go b/pkg/build/daggerbuild/containers/docs.go new file mode 100644 index 00000000000..a60c10a5ad8 --- /dev/null +++ b/pkg/build/daggerbuild/containers/docs.go @@ -0,0 +1,2 @@ +// package containers holds functions to make it easier to work with dagger containers. +package containers diff --git a/pkg/build/daggerbuild/containers/exit_error.go b/pkg/build/daggerbuild/containers/exit_error.go new file mode 100644 index 00000000000..23bf35e1aa7 --- /dev/null +++ b/pkg/build/daggerbuild/containers/exit_error.go @@ -0,0 +1,29 @@ +package containers + +import ( + "context" + "errors" + "fmt" + + "dagger.io/dagger" +) + +var ( + ErrorNonZero = errors.New("container exited with non-zero exit code") +) + +// ExitError functionally replaces '(*container).ExitCode' in a more usable way. +// It will return an error with the container's stderr and stdout if the exit code is not zero. +func ExitError(ctx context.Context, container *dagger.Container) (*dagger.Container, error) { + container, err := container.Sync(ctx) + if err == nil { + return container, nil + } + + var e *dagger.ExecError + if errors.As(err, &e) { + return container, fmt.Errorf("%w\nstdout: %s\nstderr: %s", ErrorNonZero, e.Stdout, e.Stderr) + } + + return container, err +} diff --git a/pkg/build/daggerbuild/containers/extracted_package.go b/pkg/build/daggerbuild/containers/extracted_package.go new file mode 100644 index 00000000000..ba2f98b109e --- /dev/null +++ b/pkg/build/daggerbuild/containers/extracted_package.go @@ -0,0 +1,13 @@ +package containers + +import "dagger.io/dagger" + +// ExtractedActive returns a directory that holds an extracted tar.gz +func ExtractedArchive(d *dagger.Client, f *dagger.File) *dagger.Directory { + return d.Container().From("busybox"). + // Workaround for now (maybe unnecessary?): set a FILE environment variable so that we don't accidentally cache + WithFile("/src/archive.tar.gz", f). + WithExec([]string{"mkdir", "-p", "/src/archive"}). + WithExec([]string{"tar", "--strip-components=1", "-xzf", "/src/archive.tar.gz", "-C", "/src/archive"}). + Directory("/src/archive") +} diff --git a/pkg/build/daggerbuild/containers/file_targz.go b/pkg/build/daggerbuild/containers/file_targz.go new file mode 100644 index 00000000000..0c09d3e403d --- /dev/null +++ b/pkg/build/daggerbuild/containers/file_targz.go @@ -0,0 +1 @@ +package containers diff --git a/pkg/build/daggerbuild/containers/google_cloud.go b/pkg/build/daggerbuild/containers/google_cloud.go new file mode 100644 index 00000000000..3463aaec270 --- /dev/null +++ b/pkg/build/daggerbuild/containers/google_cloud.go @@ -0,0 +1,132 @@ +package containers + +import ( + "fmt" + "math/rand" + "os" + "path/filepath" + "strconv" + + "dagger.io/dagger" +) + +const GoogleCloudImage = "google/cloud-sdk:alpine" + +// GCPAuthenticator injects authentication information into the provided container. +type GCPAuthenticator interface { + Authenticate(*dagger.Client, *dagger.Container) (*dagger.Container, error) +} + +// GCPServiceAccount satisfies GCPAuthenticator and injects the provided ServiceAccount into the filesystem and adds a 'gcloud auth activate-service-account' +type GCPServiceAccount struct { + DaggerFile *dagger.File + JSONFile string +} + +func (a *GCPServiceAccount) Authenticate(d *dagger.Client, c *dagger.Container) (*dagger.Container, error) { + if a.DaggerFile == nil && a.JSONFile == "" { + return nil, fmt.Errorf("GCPServiceAccount authentication missed JSONFile AND DaggerFile") + } + var container *dagger.Container + + if a.JSONFile != "" { + container = c.WithMountedFile( + "/opt/service_account.json", + d.Host().Directory(filepath.Dir(a.JSONFile)).File(filepath.Base(a.JSONFile)), + ) + } + + if a.DaggerFile != nil { + container = c.WithMountedFile("/opt/service_account.json", a.DaggerFile) + } + + return container.WithExec([]string{"gcloud", "auth", "activate-service-account", "--key-file", "/opt/service_account.json"}), nil +} + +func NewGCPServiceAccount(filepath string) *GCPServiceAccount { + return &GCPServiceAccount{ + JSONFile: filepath, + } +} + +func NewGCPServiceAccountWithFile(file *dagger.File) *GCPServiceAccount { + return &GCPServiceAccount{ + DaggerFile: file, + } +} + +// InheritedServiceAccount uses `gcloud` command in the current shell to get the GCS credentials. +// This type should really only be used when running locally. +type GCPInheritedAuth struct{} + +func (a *GCPInheritedAuth) Authenticate(d *dagger.Client, c *dagger.Container) (*dagger.Container, error) { + if val, ok := os.LookupEnv("GOOGLE_APPLICATION_CREDENTIALS"); ok { + return c.WithMountedDirectory("/auth/credentials.json", d.Host().Directory(val)).WithEnvVariable("GOOGLE_APPLICATION_CREDENTIALS", "/auth/credentials.json"), nil + } + + cfg, err := os.UserHomeDir() + if err != nil { + return nil, err + } + + return c.WithMountedDirectory("/root/.config/gcloud", d.Host().Directory(filepath.Join(cfg, ".config", "gcloud"))), nil +} + +func GCSUploadDirectory(d *dagger.Client, image string, auth GCPAuthenticator, dir *dagger.Directory, dst string) (*dagger.Container, error) { + container := d.Container().From(image). + WithMountedDirectory("/src", dir) + + var err error + container, err = auth.Authenticate(d, container) + if err != nil { + return nil, err + } + + secret := d.SetSecret("gcs-destination", dst) + container = container.WithSecretVariable("GCS_DESTINATION", secret) + + return container.WithExec([]string{"/bin/sh", "-c", "gcloud storage cp -r /src/* ${GCS_DESTINATION}"}), nil +} + +func GCSDownloadFile(d *dagger.Client, image string, auth GCPAuthenticator, url string) (*dagger.File, error) { + var ( + container = d.Container().From(image) + err error + r = rand.Int() + ) + + container, err = auth.Authenticate(d, container) + if err != nil { + return nil, err + } + secret := d.SetSecret("gcs-download-url", url) + file := container. + WithEnvVariable("RAND", strconv.Itoa(r)). + WithSecretVariable("GCS_DOWNLOAD_URL", secret). + WithExec([]string{"/bin/sh", "-c", "gcloud storage cp ${GCS_DOWNLOAD_URL} /src/file"}). + File("/src/file") + + return file, nil +} + +func GCSAuth(d *dagger.Client, opts *GCPOpts) GCPAuthenticator { + var auth GCPAuthenticator = &GCPInheritedAuth{} + // The order of operations: + // 1. Try to use base64 key. + // 2. Try to use gcp-service-account-key (path to a file). + // 3. Try mounting $XDG_CONFIG_HOME/gcloud + if key := opts.ServiceAccountKeyBase64; key != "" { + secret := d.SetSecret("gcp-sa-key-base64", key) + // Write key to a file in an alpine container... + file := d.Container().From("alpine"). + WithSecretVariable("GCP_SERVICE_ACCOUNT_KEY_BASE64", secret). + WithExec([]string{"/bin/sh", "-c", "echo $GCP_SERVICE_ACCOUNT_KEY_BASE64 | base64 -d > /key.json"}). + File("/key.json") + + auth = NewGCPServiceAccountWithFile(file) + } else if key := opts.ServiceAccountKey; key != "" { + auth = NewGCPServiceAccount(key) + } + + return auth +} diff --git a/pkg/build/daggerbuild/containers/ops_gcp.go b/pkg/build/daggerbuild/containers/ops_gcp.go new file mode 100644 index 00000000000..f7bbddac376 --- /dev/null +++ b/pkg/build/daggerbuild/containers/ops_gcp.go @@ -0,0 +1,16 @@ +package containers + +import "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" + +// GCPOpts are options used when using Google Cloud Platform / the Google Cloud SDK. +type GCPOpts struct { + ServiceAccountKey string + ServiceAccountKeyBase64 string +} + +func GCPOptsFromFlags(c cliutil.CLIContext) *GCPOpts { + return &GCPOpts{ + ServiceAccountKeyBase64: c.String("gcp-service-account-key-base64"), + ServiceAccountKey: c.String("gcp-service-account-key"), + } +} diff --git a/pkg/build/daggerbuild/containers/opts_pro_image.go b/pkg/build/daggerbuild/containers/opts_pro_image.go new file mode 100644 index 00000000000..8affbc6f753 --- /dev/null +++ b/pkg/build/daggerbuild/containers/opts_pro_image.go @@ -0,0 +1,42 @@ +package containers + +import "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" + +type ProImageOpts struct { + // Github token used to clone private repositories. + GitHubToken string + + // The path to a Grafana debian package. + Deb string + + // The Grafana version. + GrafanaVersion string + + // The docker image tag. + ImageTag string + + // The docker image repo. + Repo string + + // The release type. + ReleaseType string + + // True if the pro image should be pushed to the container registry. + Push bool + + // The container registry that the image should be pushed to. Required if Push is true. + ContainerRegistry string +} + +func ProImageOptsFromFlags(c cliutil.CLIContext) *ProImageOpts { + return &ProImageOpts{ + GitHubToken: c.String("github-token"), + Deb: c.String("deb"), + GrafanaVersion: c.String("grafana-version"), + ImageTag: c.String("image-tag"), + Repo: c.String("repo"), + ReleaseType: c.String("release-type"), + Push: c.Bool("push"), + ContainerRegistry: c.String("registry"), + } +} diff --git a/pkg/build/daggerbuild/containers/package_input.go b/pkg/build/daggerbuild/containers/package_input.go new file mode 100644 index 00000000000..13b4e53117f --- /dev/null +++ b/pkg/build/daggerbuild/containers/package_input.go @@ -0,0 +1,73 @@ +package containers + +import ( + "context" + "fmt" + "net/url" + "path/filepath" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" +) + +type PackageInputOpts struct { + // Name is used when overriding the artifact that is being produced. This is used in very specific scenarios where + // the source package's name does not match the package's metadata name. + Name string + Packages []string +} + +func PackageInputOptsFromFlags(c cliutil.CLIContext) *PackageInputOpts { + return &PackageInputOpts{ + Name: c.String("name"), + Packages: c.StringSlice("package"), + } +} + +// GetPackage uses the PackageInputOpts to get a Grafana package, either from the local filesystem (if the package is of type 'file://...') +// or Google Cloud Storage if the package is a 'gs://' URL. +func GetPackages(ctx context.Context, d *dagger.Client, packageOpts *PackageInputOpts, gcpOpts *GCPOpts) ([]*dagger.File, error) { + files := make([]*dagger.File, len(packageOpts.Packages)) + for i, pkg := range packageOpts.Packages { + u, err := url.Parse(pkg) + if err != nil { + return nil, err + } + + var file *dagger.File + switch u.Scheme { + case "file", "fs": + p := strings.TrimPrefix(u.String(), u.Scheme+"://") + f, err := getLocalPackage(ctx, d, p) + if err != nil { + return nil, err + } + + file = f + case "gs": + f, err := getGCSPackage(ctx, d, gcpOpts, u.String()) + if err != nil { + return nil, err + } + + file = f + default: + return nil, fmt.Errorf("%w: %s", ErrorUnrecognizedScheme, u.Scheme) + } + + files[i] = file + } + + return files, nil +} + +func getLocalPackage(ctx context.Context, d *dagger.Client, file string) (*dagger.File, error) { + // pending https://github.com/dagger/dagger/issues/4745 + return d.Host().Directory(filepath.Dir(file)).File(filepath.Base(file)), nil +} + +func getGCSPackage(ctx context.Context, d *dagger.Client, opts *GCPOpts, gcsURL string) (*dagger.File, error) { + auth := GCSAuth(d, opts) + return GCSDownloadFile(d, GoogleCloudImage, auth, gcsURL) +} diff --git a/pkg/build/daggerbuild/containers/package_validate.go b/pkg/build/daggerbuild/containers/package_validate.go new file mode 100644 index 00000000000..0c09d3e403d --- /dev/null +++ b/pkg/build/daggerbuild/containers/package_validate.go @@ -0,0 +1 @@ +package containers diff --git a/pkg/build/daggerbuild/containers/publish.go b/pkg/build/daggerbuild/containers/publish.go new file mode 100644 index 00000000000..b40f3249887 --- /dev/null +++ b/pkg/build/daggerbuild/containers/publish.go @@ -0,0 +1,38 @@ +package containers + +import ( + "errors" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" +) + +// PublishOpts fields are selectively used based on the protocol field of the destination. +// Be sure to fill out the applicable fields (or all of them) when calling a 'Publish' func. +type PublishOpts struct { + // Destination is any URL to publish an artifact(s) to. + // Examples: + // * '/tmp/package.tar.gz' + // * 'file:///tmp/package.tar.gz' + // * 'gcs://bucket/package.tar.gz' + Destination string + + // Checksum defines if the PublishFile function should also produce / publish a checksum of the given `*dagger.File' + Checksum bool +} + +func PublishOptsFromFlags(c cliutil.CLIContext) *PublishOpts { + return &PublishOpts{ + Destination: c.String("destination"), + Checksum: c.Bool("checksum"), + } +} + +var ErrorUnrecognizedScheme = errors.New("unrecognized scheme") + +type PublishFileOpts struct { + File *dagger.File + PublishOpts *PublishOpts + GCPOpts *GCPOpts + Destination string +} diff --git a/pkg/build/daggerbuild/containers/publish_dir.go b/pkg/build/daggerbuild/containers/publish_dir.go new file mode 100644 index 00000000000..abe1ad0bbdd --- /dev/null +++ b/pkg/build/daggerbuild/containers/publish_dir.go @@ -0,0 +1,62 @@ +package containers + +import ( + "context" + "fmt" + "log" + "net/url" + "strings" + + "dagger.io/dagger" +) + +func publishLocalDir(ctx context.Context, dir *dagger.Directory, dst string) error { + if _, err := dir.Export(ctx, dst); err != nil { + return err + } + + return nil +} + +func publishGCSDir(ctx context.Context, d *dagger.Client, dir *dagger.Directory, opts *GCPOpts, dst string) error { + auth := GCSAuth(d, opts) + uploader, err := GCSUploadDirectory(d, GoogleCloudImage, auth, dir, dst) + if err != nil { + return err + } + + if _, err := ExitError(ctx, uploader); err != nil { + return err + } + + return nil +} + +// PublishDirectory publishes a directory to the given destination. +func PublishDirectory(ctx context.Context, d *dagger.Client, dir *dagger.Directory, opts *GCPOpts, dst string) (string, error) { + log.Println("Publishing directory", dst) + u, err := url.Parse(dst) + if err != nil { + // If the destination URL is not a URL then we can assume that it's just a filepath. + if err := publishLocalDir(ctx, dir, dst); err != nil { + return "", err + } + return "", err + } + + switch u.Scheme { + case "file", "fs": + dst := strings.TrimPrefix(u.String(), u.Scheme+"://") + if err := publishLocalDir(ctx, dir, dst); err != nil { + return "", err + } + case "gs": + if err := publishGCSDir(ctx, d, dir, opts, dst); err != nil { + return "", err + } + default: + return "", fmt.Errorf("%w: '%s'", ErrorUnrecognizedScheme, u.Scheme) + } + + return dst, nil +} diff --git a/pkg/build/daggerbuild/containers/sha256.go b/pkg/build/daggerbuild/containers/sha256.go new file mode 100644 index 00000000000..4b2da63421f --- /dev/null +++ b/pkg/build/daggerbuild/containers/sha256.go @@ -0,0 +1,13 @@ +package containers + +import ( + "dagger.io/dagger" +) + +// Sha256 returns a dagger.File which contains the sha256 for the provided file. +func Sha256(d *dagger.Client, file *dagger.File) *dagger.File { + return d.Container().From("busybox"). + WithFile("/src/file", file). + WithExec([]string{"/bin/sh", "-c", "sha256sum /src/file | awk '{print $1}' > /src/file.sha256"}). + File("/src/file.sha256") +} diff --git a/pkg/build/daggerbuild/containers/test_backend.go b/pkg/build/daggerbuild/containers/test_backend.go new file mode 100644 index 00000000000..dfecf2c4dea --- /dev/null +++ b/pkg/build/daggerbuild/containers/test_backend.go @@ -0,0 +1,11 @@ +package containers + +// func BackendTestShort(d *dagger.Client, platform dagger.Platform, dir *dagger.Directory) *dagger.Container { +// return GrafanaContainer(d, platform, GetGoImageAlpine("1.21.0"), dir). +// WithExec([]string{"go", "test", "-tags", "requires_buildifer", "-short", "-covermode", "atomic", "-timeout", "5m", "./pkg/..."}) +// } +// +// func BackendTestIntegration(d *dagger.Client, platform dagger.Platform, dir *dagger.Directory) *dagger.Container { +// return GrafanaContainer(d, platform, GetGoImageAlpine("1.21.0"), dir). +// WithExec([]string{"go", "test", "-run", "Integration", "-covermode", "atomic", "-timeout", "5m", "./pkg/..."}) +// } diff --git a/pkg/build/daggerbuild/containers/version.go b/pkg/build/daggerbuild/containers/version.go new file mode 100644 index 00000000000..499eff25d57 --- /dev/null +++ b/pkg/build/daggerbuild/containers/version.go @@ -0,0 +1,24 @@ +package containers + +import ( + "context" + "fmt" + "strings" + + "dagger.io/dagger" +) + +// GetJSONValue gets the value of a JSON field from a JSON file in the 'src' directory. +func GetJSONValue(ctx context.Context, d *dagger.Client, src *dagger.Directory, file string, field string) (string, error) { + c := d.Container().From("alpine"). + WithExec([]string{"apk", "--update", "add", "jq"}). + WithMountedDirectory("/src", src). + WithWorkdir("/src"). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("cat %s | jq -r .%s", file, field)}) + + if stdout, err := c.Stdout(ctx); err == nil { + return strings.TrimSpace(stdout), nil + } + + return c.Stderr(ctx) +} diff --git a/pkg/build/daggerbuild/containers/with_embedded_fs.go b/pkg/build/daggerbuild/containers/with_embedded_fs.go new file mode 100644 index 00000000000..07e7217bfa7 --- /dev/null +++ b/pkg/build/daggerbuild/containers/with_embedded_fs.go @@ -0,0 +1,39 @@ +package containers + +import ( + "embed" + "io/fs" + "path/filepath" + + "dagger.io/dagger" +) + +func WithEmbeddedFS(client *dagger.Client, c *dagger.Container, path string, e embed.FS) (*dagger.Container, error) { + dir := client.Directory() + + err := fs.WalkDir(e, ".", func(path string, entry fs.DirEntry, err error) error { + if entry.IsDir() { + return nil + } + if err != nil { + return err + } + + content, err := e.ReadFile(path) + if err != nil { + return err + } + rel, err := filepath.Rel("scripts/packaging/windows", path) + if err != nil { + return err + } + + dir = dir.WithNewFile(rel, string(content)) + return nil + }) + if err != nil { + return nil, err + } + + return c.WithDirectory(path, dir), nil +} diff --git a/pkg/build/daggerbuild/containers/withenv.go b/pkg/build/daggerbuild/containers/withenv.go new file mode 100644 index 00000000000..f3b65210b10 --- /dev/null +++ b/pkg/build/daggerbuild/containers/withenv.go @@ -0,0 +1,23 @@ +package containers + +import ( + "dagger.io/dagger" +) + +type Env struct { + Name string + Value string +} + +func EnvVar(name, value string) Env { + return Env{Name: name, Value: value} +} + +func WithEnv(c *dagger.Container, env []Env) *dagger.Container { + container := c + for _, v := range env { + container = container.WithEnvVariable(v.Name, v.Value) + } + + return container +} diff --git a/pkg/build/daggerbuild/daggerutil/hostdir.go b/pkg/build/daggerbuild/daggerutil/hostdir.go new file mode 100644 index 00000000000..64a4d683047 --- /dev/null +++ b/pkg/build/daggerbuild/daggerutil/hostdir.go @@ -0,0 +1,22 @@ +package daggerutil + +import ( + "errors" + "os" + + "dagger.io/dagger" +) + +// HostDir checks that the directory at 'path' exists and returns the dagger.Directory at 'path'. +func HostDir(d *dagger.Client, path string) (*dagger.Directory, error) { + info, err := os.Stat(path) + if err != nil { + return nil, err + } + + if !info.IsDir() { + return nil, errors.New("given hostdir is not a directory") + } + + return d.Host().Directory(path), nil +} diff --git a/pkg/build/daggerbuild/docker/build.go b/pkg/build/daggerbuild/docker/build.go new file mode 100644 index 00000000000..55a916779d7 --- /dev/null +++ b/pkg/build/daggerbuild/docker/build.go @@ -0,0 +1,69 @@ +package docker + +import ( + "fmt" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +type BuildOpts struct { + // Dockerfile is the path to the dockerfile with the '-f' command. + // If it's not provided, then the docker command will default to 'Dockerfile' in `pwd`. + Dockerfile string + + // Tags are provided as the '-t' argument, and can include the registry domain as well as the repository. + // Docker build supports building the same image with multiple tags. + // You might want to also include a 'latest' version of the tag. + Tags []string + // BuildArgs are provided to the docker command as '--build-arg' + BuildArgs []string + // Set the target build stage to build as '--target' + Target string + + // Platform, if set to the non-default value, will use buildkit's emulation to build the docker image. This can be useful if building a docker image for a platform that doesn't match the host platform. + Platform dagger.Platform +} + +func Builder(d *dagger.Client, socket *dagger.Socket, targz *dagger.File) *dagger.Container { + extracted := containers.ExtractedArchive(d, targz) + + // Instead of supplying the Platform argument here, we need to tell the host docker socket that it needs to build with the given platform. + return d.Container().From("docker"). + WithUnixSocket("/var/run/docker.sock", socket). + WithWorkdir("/src"). + WithMountedFile("/src/Dockerfile", extracted.File("Dockerfile")). + WithMountedFile("/src/packaging/docker/run.sh", extracted.File("packaging/docker/run.sh")). + WithMountedFile("/src/grafana.tar.gz", targz) +} + +func Build(d *dagger.Client, builder *dagger.Container, opts *BuildOpts) *dagger.Container { + args := []string{"docker", "buildx", "build"} + if p := opts.Platform; p != "" { + args = append(args, fmt.Sprintf("--platform=%s", string(p))) + } + dockerfile := opts.Dockerfile + if dockerfile == "" { + dockerfile = "Dockerfile" + } + + args = append(args, ".", "-f", dockerfile) + + for _, v := range opts.BuildArgs { + args = append(args, fmt.Sprintf("--build-arg=%s", v)) + } + + for _, v := range opts.Tags { + args = append(args, "-t", v) + } + + if opts.Target != "" { + args = append(args, "--target", opts.Target) + } + + return builder.WithExec(args) +} + +func Save(builder *dagger.Container, opts *BuildOpts) *dagger.File { + return builder.WithExec([]string{"docker", "save", opts.Tags[0], "-o", "image.tar.gz"}).File("image.tar.gz") +} diff --git a/pkg/build/daggerbuild/docker/opts.go b/pkg/build/daggerbuild/docker/opts.go new file mode 100644 index 00000000000..afd0ee5c62e --- /dev/null +++ b/pkg/build/daggerbuild/docker/opts.go @@ -0,0 +1,36 @@ +package docker + +type DockerOpts struct { + // Registry is the docker Registry for the image. + // If using '--save', then this will have no effect. + // Uses docker hub by default. + // Example: us.gcr.io/12345 + Registry string + + // AlpineBase is supplied as a build-arg when building the Grafana docker image. + // When building alpine versions of Grafana it uses this image as its base. + AlpineBase string + + // UbuntuBase is supplied as a build-arg when building the Grafana docker image. + // When building ubuntu versions of Grafana it uses this image as its base. + UbuntuBase string + + // Username is supplied to login to the docker registry when publishing images. + Username string + + // Password is supplied to login to the docker registry when publishing images. + Password string + + // Org overrides the organization when when publishing images. + Org string + + // Repository overrides the repository when when publishing images. + Repository string + + // Latest is supplied to also tag as latest when publishing images. + Latest bool + + // TagFormat and UbuntuTagFormat should be formatted using go template tags. + TagFormat string + UbuntuTagFormat string +} diff --git a/pkg/build/daggerbuild/docker/publish.go b/pkg/build/daggerbuild/docker/publish.go new file mode 100644 index 00000000000..4e9cd8fc7a2 --- /dev/null +++ b/pkg/build/daggerbuild/docker/publish.go @@ -0,0 +1,32 @@ +package docker + +import ( + "context" + "fmt" + + "dagger.io/dagger" +) + +func PublishPackageImage(ctx context.Context, d *dagger.Client, pkg *dagger.File, tag, username, password, registry string) (string, error) { + return d.Container().From("docker"). + WithFile("grafana.img", pkg). + WithSecretVariable("DOCKER_USERNAME", d.SetSecret("docker-username", username)). + WithSecretVariable("DOCKER_PASSWORD", d.SetSecret("docker-password", password)). + WithUnixSocket("/var/run/docker.sock", d.Host().UnixSocket("/var/run/docker.sock")). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("docker login %s -u $DOCKER_USERNAME -p $DOCKER_PASSWORD", registry)}). + WithExec([]string{"/bin/sh", "-c", "docker load -i grafana.img | awk -F 'Loaded image: ' '{print $2}' > /tmp/image_tag"}). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("docker tag $(cat /tmp/image_tag) %s", tag)}). + WithExec([]string{"docker", "push", tag}). + Stdout(ctx) +} + +func PublishManifest(ctx context.Context, d *dagger.Client, manifest string, tags []string, username, password, registry string) (string, error) { + return d.Container().From("docker"). + WithUnixSocket("/var/run/docker.sock", d.Host().UnixSocket("/var/run/docker.sock")). + WithSecretVariable("DOCKER_USERNAME", d.SetSecret("docker-username", username)). + WithSecretVariable("DOCKER_PASSWORD", d.SetSecret("docker-password", password)). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("docker login %s -u $DOCKER_USERNAME -p $DOCKER_PASSWORD", registry)}). + WithExec(append([]string{"docker", "manifest", "create", manifest}, tags...)). + WithExec([]string{"docker", "manifest", "push", manifest}). + Stdout(ctx) +} diff --git a/pkg/build/daggerbuild/docker/tags.go b/pkg/build/daggerbuild/docker/tags.go new file mode 100644 index 00000000000..ad0fd958b7e --- /dev/null +++ b/pkg/build/daggerbuild/docker/tags.go @@ -0,0 +1,80 @@ +package docker + +import ( + "bytes" + "fmt" + "strings" + "text/template" + + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" +) + +type BaseImage int + +const ( + BaseImageUbuntu BaseImage = iota + BaseImageAlpine +) + +const ( + DefaultTagFormat = "{{ .version }}-{{ .arch }}" + DefaultUbuntuTagFormat = "{{ .version }}-ubuntu-{{ .arch }}" + DefaultBoringTagFormat = "{{ .version }}-{{ .arch }}-boringcrypto" + DefaultHGTagFormat = "{{ .version }}-{{ .arch }}" +) + +// Tags returns the name of the grafana docker image based on the tar package name. +// To maintain backwards compatibility, we must keep this the same as it was before. +func Tags(org, registry string, repos []string, format string, tarOpts packages.NameOpts) ([]string, error) { + tags := make([]string, len(repos)) + + for i, repo := range repos { + tag, err := ImageTag(tarOpts.Distro, format, registry, org, repo, tarOpts.Version, tarOpts.BuildID) + if err != nil { + return nil, err + } + + tags[i] = tag + } + + return tags, nil +} + +func ImageTag(distro backend.Distribution, format, registry, org, repo, version, buildID string) (string, error) { + version, err := ImageVersion(format, TemplateValues(distro, version, buildID)) + if err != nil { + return "", err + } + + return fmt.Sprintf("%s/%s/%s:%s", registry, org, repo, version), nil +} + +func ImageVersion(format string, values map[string]string) (string, error) { + tmpl, err := template.New("version").Parse(format) + if err != nil { + return "", err + } + + buf := bytes.NewBuffer(nil) + if err := tmpl.Execute(buf, values); err != nil { + return "", err + } + + return buf.String(), nil +} + +func TemplateValues(distro backend.Distribution, version, buildID string) map[string]string { + arch := backend.FullArch(distro) + arch = strings.ReplaceAll(arch, "/", "") + arch = strings.ReplaceAll(arch, "dynamic", "") + ersion := strings.TrimPrefix(version, "v") + + semverc := strings.Split(ersion, "-") + return map[string]string{ + "arch": arch, + "version": ersion, + "version_base": semverc[0], + "buildID": buildID, + } +} diff --git a/pkg/build/daggerbuild/docker/verify.go b/pkg/build/daggerbuild/docker/verify.go new file mode 100644 index 00000000000..c6367480206 --- /dev/null +++ b/pkg/build/daggerbuild/docker/verify.go @@ -0,0 +1,45 @@ +package docker + +import ( + "context" + "fmt" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/e2e" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" +) + +// Verify uses the given package (.docker.tar.gz) and grafana source code (src) to run the e2e smoke tests. +// the returned directory is the e2e artifacts created by cypress (screenshots and videos). +func Verify( + ctx context.Context, + d *dagger.Client, + image *dagger.File, + src *dagger.Directory, + yarnCache *dagger.CacheVolume, + distro backend.Distribution, +) error { + nodeVersion, err := frontend.NodeVersion(d, src).Stdout(ctx) + if err != nil { + return fmt.Errorf("failed to get node version from source code: %w", err) + } + + var ( + platform = backend.Platform(distro) + ) + + // This grafana service runs in the background for the e2e tests + service := d.Container(dagger.ContainerOpts{ + Platform: platform, + }). + WithMountedTemp("/var/lib/grafana/plugins"). + Import(image). + WithExposedPort(3000) + + // TODO: Add LICENSE to containers and implement validation + container := e2e.ValidatePackage(d, service.AsService(), src, yarnCache, nodeVersion) + _, err = containers.ExitError(ctx, container) + return err +} diff --git a/pkg/build/daggerbuild/e2e/validate_license.go b/pkg/build/daggerbuild/e2e/validate_license.go new file mode 100644 index 00000000000..1f3037baee6 --- /dev/null +++ b/pkg/build/daggerbuild/e2e/validate_license.go @@ -0,0 +1,31 @@ +package e2e + +import ( + "context" + "fmt" + "strings" + + "dagger.io/dagger" +) + +// validateLicense uses the given container and license path to validate the license for each edition (enterprise or oss) +func ValidateLicense(ctx context.Context, service *dagger.Container, licensePath string, enterprise bool) error { + license, err := service.File(licensePath).Contents(ctx) + if err != nil { + return err + } + + if enterprise { + if !strings.Contains(license, "Grafana Enterprise") { + return fmt.Errorf("license in package is not the Grafana Enterprise license agreement") + } + + return nil + } + + if !strings.Contains(license, "GNU AFFERO GENERAL PUBLIC LICENSE") { + return fmt.Errorf("license in package is not the Grafana open-source license agreement") + } + + return nil +} diff --git a/pkg/build/daggerbuild/e2e/validate_package.go b/pkg/build/daggerbuild/e2e/validate_package.go new file mode 100644 index 00000000000..c786b4a991b --- /dev/null +++ b/pkg/build/daggerbuild/e2e/validate_package.go @@ -0,0 +1,32 @@ +package e2e + +import ( + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" +) + +func CypressImage(version string) string { + return "cypress/included:13.1.0" +} + +// CypressContainer returns a docker container with everything set up that is needed to build or run e2e tests. +func CypressContainer(d *dagger.Client, base string) *dagger.Container { + container := d.Container().From(base).WithEntrypoint([]string{}) + + return container +} + +func ValidatePackage(d *dagger.Client, service *dagger.Service, src *dagger.Directory, yarnCacheVolume *dagger.CacheVolume, nodeVersion string) *dagger.Container { + // The cypress container should never be cached + c := CypressContainer(d, CypressImage(nodeVersion)) + + c = frontend.WithYarnCache(c, yarnCacheVolume) + + return c.WithDirectory("/src", src). + WithWorkdir("/src"). + WithServiceBinding("grafana", service). + WithEnvVariable("HOST", "grafana"). + WithEnvVariable("PORT", "3000"). + WithExec([]string{"yarn", "install", "--immutable"}). + WithExec([]string{"/bin/sh", "-c", "/src/e2e/verify-release"}) +} diff --git a/pkg/build/daggerbuild/embed.go b/pkg/build/daggerbuild/embed.go new file mode 100644 index 00000000000..00a70f340a5 --- /dev/null +++ b/pkg/build/daggerbuild/embed.go @@ -0,0 +1,8 @@ +package grafanabuild + +import ( + "embed" +) + +//go:embed scripts/packaging/windows/* +var WindowsPackaging embed.FS diff --git a/pkg/build/daggerbuild/flags/distro.go b/pkg/build/daggerbuild/flags/distro.go new file mode 100644 index 00000000000..87aeff5e6e1 --- /dev/null +++ b/pkg/build/daggerbuild/flags/distro.go @@ -0,0 +1,64 @@ +package flags + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +const ( + FlagDistribution = "distro" +) + +var StaticDistributions = []backend.Distribution{ + backend.DistLinuxAMD64, + backend.DistLinuxARM64, + backend.DistLinuxARMv7, + backend.DistLinuxRISCV64, + backend.DistLinuxS390X, +} + +var DynamicDistributions = []backend.Distribution{ + backend.DistDarwinAMD64, + backend.DistDarwinARM64, + backend.DistWindowsAMD64, + backend.DistWindowsARM64, + backend.DistLinuxAMD64Dynamic, + backend.DistLinuxAMD64DynamicMusl, +} + +func DistroFlags() []pipeline.Flag { + // These distributions have specific options that set some stuff. + f := []pipeline.Flag{ + { + Name: string(backend.DistLinuxARMv6), + Options: map[pipeline.FlagOption]any{ + Distribution: string(backend.DistLinuxARMv6), + Static: true, + RPI: true, + }, + }, + } + + for _, v := range StaticDistributions { + d := string(v) + f = append(f, pipeline.Flag{ + Name: d, + Options: map[pipeline.FlagOption]any{ + Distribution: d, + Static: true, + }, + }) + } + for _, v := range DynamicDistributions { + d := string(v) + f = append(f, pipeline.Flag{ + Name: d, + Options: map[pipeline.FlagOption]any{ + Distribution: d, + Static: false, + }, + }) + } + + return f +} diff --git a/pkg/build/daggerbuild/flags/docker.go b/pkg/build/daggerbuild/flags/docker.go new file mode 100644 index 00000000000..f7a953ae15b --- /dev/null +++ b/pkg/build/daggerbuild/flags/docker.go @@ -0,0 +1,17 @@ +package flags + +import "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + +var ( + Ubuntu pipeline.FlagOption = "docker-ubuntu" + DockerRepositories pipeline.FlagOption = "docker-repos" +) + +var DockerFlags = []pipeline.Flag{ + { + Name: "ubuntu", + Options: map[pipeline.FlagOption]any{ + Ubuntu: true, + }, + }, +} diff --git a/pkg/build/daggerbuild/flags/docs.go b/pkg/build/daggerbuild/flags/docs.go new file mode 100644 index 00000000000..e027756c1c1 --- /dev/null +++ b/pkg/build/daggerbuild/flags/docs.go @@ -0,0 +1,7 @@ +// Package flags defines the "flags" that are used in various artifacts throughout the application. +// A flag is an artifact-specific string alias to a set of options. +// Examples: +// - the 'boringcrypto' flag, when used in an artifact string like `boringcrypto:targz:linux/amd64`, informs the `targz` artifact that +// the package name is 'grafana-boringcrypto', and that when it is built, the GOEXPERIMENT=boringcrypto flag must be set. +// - the 'targz' flag forces the use of the 'targz' artifact, whose exention will end in `tar.gz`, and will require the compiled 'backend' and 'frontend'. +package flags diff --git a/pkg/build/daggerbuild/flags/join.go b/pkg/build/daggerbuild/flags/join.go new file mode 100644 index 00000000000..0a58b9d17c4 --- /dev/null +++ b/pkg/build/daggerbuild/flags/join.go @@ -0,0 +1,12 @@ +package flags + +import "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" + +func JoinFlags(f ...[]pipeline.Flag) []pipeline.Flag { + r := []pipeline.Flag{} + for _, v := range f { + r = append(r, v...) + } + + return r +} diff --git a/pkg/build/daggerbuild/flags/packages.go b/pkg/build/daggerbuild/flags/packages.go new file mode 100644 index 00000000000..e6ba0149d24 --- /dev/null +++ b/pkg/build/daggerbuild/flags/packages.go @@ -0,0 +1,99 @@ +package flags + +import ( + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipeline" +) + +var DefaultTags = []string{ + "osusergo", + "timetzdata", +} + +const ( + PackageName pipeline.FlagOption = "package-name" + Distribution pipeline.FlagOption = "distribution" + Static pipeline.FlagOption = "static" + Enterprise pipeline.FlagOption = "enterprise" + WireTag pipeline.FlagOption = "wire-tag" + GoTags pipeline.FlagOption = "go-tag" + GoExperiments pipeline.FlagOption = "go-experiments" + Sign pipeline.FlagOption = "sign" + + // Pretty much only used to set the deb or RPM internal package name (and file name) to `{}-nightly` and/or `{}-rpi` + Nightly pipeline.FlagOption = "nightly" + RPI pipeline.FlagOption = "rpi" +) + +// PackageNameFlags - flags that packages (targz, deb, rpm, docker) must have. +// Essentially they must have all of the same things that the targz package has. +var PackageNameFlags = []pipeline.Flag{ + { + Name: "grafana", + Options: map[pipeline.FlagOption]any{ + DockerRepositories: []string{"grafana-image-tags", "grafana-oss-image-tags"}, + PackageName: string(packages.PackageGrafana), + Enterprise: false, + WireTag: "oss", + GoExperiments: []string{}, + GoTags: DefaultTags, + }, + }, + { + Name: "enterprise", + Options: map[pipeline.FlagOption]any{ + DockerRepositories: []string{"grafana-enterprise-image-tags"}, + PackageName: string(packages.PackageEnterprise), + Enterprise: true, + WireTag: "enterprise", + GoExperiments: []string{}, + GoTags: append(DefaultTags, "enterprise"), + }, + }, + { + Name: "pro", + Options: map[pipeline.FlagOption]any{ + DockerRepositories: []string{"grafana-pro"}, + PackageName: string(packages.PackagePro), + Enterprise: true, + WireTag: "pro", + GoExperiments: []string{}, + GoTags: append(DefaultTags, "pro"), + }, + }, + { + Name: "boring", + Options: map[pipeline.FlagOption]any{ + DockerRepositories: []string{"grafana-enterprise-image-tags"}, + PackageName: string(packages.PackageEnterpriseBoring), + Enterprise: true, + WireTag: "enterprise", + GoExperiments: []string{"boringcrypto"}, + GoTags: append(DefaultTags, "enterprise"), + }, + }, +} + +var SignFlag = pipeline.Flag{ + Name: "sign", + Options: map[pipeline.FlagOption]any{ + Sign: true, + }, +} + +var NightlyFlag = pipeline.Flag{ + Name: "nightly", + Options: map[pipeline.FlagOption]any{ + Nightly: true, + }, +} + +func StdPackageFlags() []pipeline.Flag { + distros := DistroFlags() + names := PackageNameFlags + + return JoinFlags( + distros, + names, + ) +} diff --git a/pkg/build/daggerbuild/fpm/build.go b/pkg/build/daggerbuild/fpm/build.go new file mode 100644 index 00000000000..138f166792c --- /dev/null +++ b/pkg/build/daggerbuild/fpm/build.go @@ -0,0 +1,139 @@ +package fpm + +import ( + "fmt" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" + "github.com/grafana/grafana/pkg/build/daggerbuild/versions" +) + +type PackageType string + +const ( + PackageTypeDeb PackageType = "deb" + PackageTypeRPM PackageType = "rpm" +) + +type BuildOpts struct { + Name packages.Name + Enterprise bool + Version string + BuildID string + Distribution backend.Distribution + NameOverride string + PackageType PackageType + ConfigFiles [][]string + AfterInstall string + BeforeRemove string + Depends []string + EnvFolder string + ExtraArgs []string + RPMSign bool +} + +func Build(builder *dagger.Container, opts BuildOpts, targz *dagger.File) *dagger.File { + var ( + destination = fmt.Sprintf("/src/package.%s", opts.PackageType) + fpmArgs = []string{ + "fpm", + "--input-type=dir", + "--chdir=/pkg", + fmt.Sprintf("--output-type=%s", opts.PackageType), + "--vendor=\"Grafana Labs\"", + "--url=https://grafana.com", + "--maintainer=contact@grafana.com", + fmt.Sprintf("--version=%s", strings.TrimPrefix(opts.Version, "v")), + fmt.Sprintf("--package=%s", destination), + } + + vopts = versions.OptionsFor(opts.Version) + ) + + // If this is a debian installer and this version had a prerm script (introduced in v9.5)... + // TODO: this logic means that rpms can't also have a beforeremove. Not important at the moment because it's static (in pipelines/rpm.go) and it doesn't have beforeremove set. + if vopts.DebPreRM.IsSet && vopts.DebPreRM.Value && opts.PackageType == "deb" { + if opts.BeforeRemove != "" { + fpmArgs = append(fpmArgs, fmt.Sprintf("--before-remove=%s", opts.BeforeRemove)) + } + } + + // These paths need to be absolute when installed on the machine and not the package structure. + for _, c := range opts.ConfigFiles { + fpmArgs = append(fpmArgs, fmt.Sprintf("--config-files=%s", strings.TrimPrefix(c[1], "/pkg"))) + } + + if opts.AfterInstall != "" { + fpmArgs = append(fpmArgs, fmt.Sprintf("--after-install=%s", opts.AfterInstall)) + } + + for _, d := range opts.Depends { + fpmArgs = append(fpmArgs, fmt.Sprintf("--depends=%s", d)) + } + + fpmArgs = append(fpmArgs, opts.ExtraArgs...) + + if arch := backend.PackageArch(opts.Distribution); arch != "" { + fpmArgs = append(fpmArgs, fmt.Sprintf("--architecture=%s", arch)) + } + + packageName := string(opts.Name) + // Honestly we don't care about making fpm installers for non-enterprise or non-grafana flavors of grafana + if opts.Enterprise { + fpmArgs = append(fpmArgs, "--description=\"Grafana Enterprise\"") + fpmArgs = append(fpmArgs, "--conflicts=grafana") + } else { + fpmArgs = append(fpmArgs, "--description=Grafana") + fpmArgs = append(fpmArgs, "--license=AGPLv3") + } + + if n := opts.NameOverride; n != "" { + packageName = n + } + + fpmArgs = append(fpmArgs, fmt.Sprintf("--name=%s", packageName)) + + // The last fpm arg which is required to say, "use the PWD to build the package". + fpmArgs = append(fpmArgs, ".") + + var ( + // fpm is going to create us a package that is going to essentially rsync the folders from the package into the filesystem. + // These paths are the paths where grafana package contents will be placed. + packagePaths = []string{ + "/pkg/usr/sbin", + "/pkg/usr/share", + // holds default environment variables for the grafana-server service + opts.EnvFolder, + // /etc/grafana is empty in the installation, but is set up by the postinstall script and must be created first. + "/pkg/etc/grafana", + // these are our systemd unit files that allow systemd to start/stop/restart/enable the grafana service. + "/pkg/usr/lib/systemd/system", + } + ) + + // init.d scripts are service management scripts that start/stop/restart/enable the grafana service without systemd. + // these are likely to be deprecated as systemd is now the default pretty much everywhere. + if opts.PackageType != PackageTypeRPM { + packagePaths = append(packagePaths, "/pkg/etc/init.d") + } + + container := builder. + WithFile("/src/grafana.tar.gz", targz). + WithEnvVariable("XZ_DEFAULTS", "-T0"). + WithExec([]string{"tar", "--exclude=storybook", "--strip-components=1", "-xvf", "/src/grafana.tar.gz", "-C", "/src"}). + WithExec([]string{"rm", "/src/grafana.tar.gz"}) + + container = container. + WithExec(append([]string{"mkdir", "-p"}, packagePaths...)). + // the "wrappers" scripts are the same as grafana-cli/grafana-server but with some extra shell commands before/after execution. + WithExec([]string{"cp", "/src/packaging/wrappers/grafana-server", "/src/packaging/wrappers/grafana-cli", "/pkg/usr/sbin"}). + WithExec([]string{"cp", "-r", "/src", "/pkg/usr/share/grafana"}) + + for _, conf := range opts.ConfigFiles { + container = container.WithExec(append([]string{"cp", "-r"}, conf...)) + } + + return container.WithExec(fpmArgs).File(destination) +} diff --git a/pkg/build/daggerbuild/fpm/builder.go b/pkg/build/daggerbuild/fpm/builder.go new file mode 100644 index 00000000000..32760c55951 --- /dev/null +++ b/pkg/build/daggerbuild/fpm/builder.go @@ -0,0 +1,14 @@ +package fpm + +import "dagger.io/dagger" + +const RubyContainer = "ruby:3.2.2-bullseye" + +func Builder(d *dagger.Client) *dagger.Container { + return d.Container(). + From(RubyContainer). + WithEntrypoint(nil). + WithExec([]string{"gem", "install", "fpm"}). + WithExec([]string{"apt-get", "update"}). + WithExec([]string{"apt-get", "install", "-yq", "rpm", "gnupg2"}) +} diff --git a/pkg/build/daggerbuild/fpm/verify.go b/pkg/build/daggerbuild/fpm/verify.go new file mode 100644 index 00000000000..d4bf2a48902 --- /dev/null +++ b/pkg/build/daggerbuild/fpm/verify.go @@ -0,0 +1,83 @@ +package fpm + +import ( + "context" + "fmt" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/e2e" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "github.com/grafana/grafana/pkg/build/daggerbuild/gpg" +) + +func VerifyDeb(ctx context.Context, d *dagger.Client, file *dagger.File, src *dagger.Directory, yarn *dagger.CacheVolume, distro backend.Distribution, enterprise bool) error { + nodeVersion, err := frontend.NodeVersion(d, src).Stdout(ctx) + if err != nil { + return fmt.Errorf("failed to get node version from source code: %w", err) + } + + var ( + platform = backend.Platform(distro) + ) + + // This grafana service runs in the background for the e2e tests + service := d.Container(dagger.ContainerOpts{ + Platform: platform, + }).From("debian:latest"). + WithFile("/src/package.deb", file). + WithExec([]string{"apt-get", "update"}). + WithExec([]string{"apt-get", "install", "-y", "/src/package.deb"}). + WithWorkdir("/usr/share/grafana") + + if err := e2e.ValidateLicense(ctx, service, "/usr/share/grafana/LICENSE", enterprise); err != nil { + return err + } + + svc := service. + WithExec([]string{"grafana-server"}). + WithExposedPort(3000).AsService() + + if _, err := containers.ExitError(ctx, e2e.ValidatePackage(d, svc, src, yarn, nodeVersion)); err != nil { + return err + } + + return nil +} + +func VerifyRpm(ctx context.Context, d *dagger.Client, file *dagger.File, src *dagger.Directory, yarn *dagger.CacheVolume, distro backend.Distribution, enterprise, sign bool, pubkey, privkey, passphrase string) error { + nodeVersion, err := frontend.NodeVersion(d, src).Stdout(ctx) + if err != nil { + return fmt.Errorf("failed to get node version from source code: %w", err) + } + + var ( + platform = backend.Platform(distro) + ) + + // This grafana service runs in the background for the e2e tests + service := d.Container(dagger.ContainerOpts{ + Platform: platform, + }).From("redhat/ubi8:latest"). + WithFile("/src/package.rpm", file). + WithExec([]string{"yum", "install", "-y", "/src/package.rpm"}). + WithWorkdir("/usr/share/grafana") + + if err := e2e.ValidateLicense(ctx, service, "/usr/share/grafana/LICENSE", enterprise); err != nil { + return err + } + + service = service. + WithExec([]string{"grafana-server"}). + WithExposedPort(3000) + + if _, err := containers.ExitError(ctx, e2e.ValidatePackage(d, service.AsService(), src, yarn, nodeVersion)); err != nil { + return err + } + if !sign { + return nil + } + + return gpg.VerifySignature(ctx, d, file, pubkey, privkey, passphrase) +} diff --git a/pkg/build/daggerbuild/frontend/build.go b/pkg/build/daggerbuild/frontend/build.go new file mode 100644 index 00000000000..b04cdc01767 --- /dev/null +++ b/pkg/build/daggerbuild/frontend/build.go @@ -0,0 +1,31 @@ +package frontend + +import ( + "dagger.io/dagger" +) + +func Build(builder *dagger.Container) *dagger.Directory { + public := builder. + WithExec([]string{"yarn", "run", "build"}). + WithExec([]string{"/bin/sh", "-c", "find /src/public -type d -name node_modules -print0 | xargs -0 rm -rf"}). + Directory("/src/public") + + return public +} + +func BuildPlugins(builder *dagger.Container) *dagger.Directory { + public := builder. + WithExec([]string{"yarn", "install", "--immutable"}). + WithExec([]string{"/bin/sh", "-c", `if [ -d /src/plugins-bundled ]; then yarn run plugins:build-bundled; else mkdir /src/plugins-bundled; fi`}). + WithExec([]string{"/bin/sh", "-c", "find /src/plugins-bundled -type d -name node_modules -print0 | xargs -0 rm -rf"}). + Directory("/src/plugins-bundled") + + return public +} + +// WithYarnCache mounts the given YarnCacheDir in the provided container +func WithYarnCache(container *dagger.Container, vol *dagger.CacheVolume) *dagger.Container { + yarnCacheDir := "/yarn/cache" + c := container.WithEnvVariable("YARN_CACHE_FOLDER", yarnCacheDir) + return c.WithMountedCache(yarnCacheDir, vol) +} diff --git a/pkg/build/daggerbuild/frontend/builder.go b/pkg/build/daggerbuild/frontend/builder.go new file mode 100644 index 00000000000..f2873770f3f --- /dev/null +++ b/pkg/build/daggerbuild/frontend/builder.go @@ -0,0 +1,55 @@ +package frontend + +import ( + "dagger.io/dagger" +) + +// Builder mounts all of the necessary files to run yarn build commands and includes a yarn install exec +func Builder(d *dagger.Client, platform dagger.Platform, src *dagger.Directory, nodeVersion string, cache *dagger.CacheVolume) *dagger.Container { + container := WithYarnCache( + NodeContainer(d, NodeImage(nodeVersion), platform), + cache, + ). + WithDirectory("/src", + src. + WithoutFile("go.mod"). + WithoutFile("go.sum"). + WithoutFile("go.work"). + WithoutFile("go.work.sum"). + WithoutDirectory("devenv"). + WithoutDirectory(".github"). + WithoutDirectory("docs"). + WithoutDirectory("pkg"). + WithoutDirectory("apps"). + WithoutDirectory(".nx"), + dagger.ContainerWithDirectoryOpts{ + Exclude: []string{ + "*drone*", + "*.go", + "*.md", + }, + }, + ). + WithWorkdir("/src") + + // TODO: Should figure out exactly what we can include without all the extras so we can take advantage of caching better. + // This had to be commented because storybook builds on branches older than 10.1.x were failing. + + // container = containers.WithDirectories(container, map[string]*dagger.Directory{ + // ".yarn": src.Directory(".yarn"), + // "packages": src.Directory("packages"), + // "plugins-bundled": src.Directory("plugins-bundled"), + // "public": src.Directory("public"), + // "scripts": src.Directory("scripts"), + // }) + + // container = containers.WithFiles(container, map[string]*dagger.File{ + // "package.json": src.File("package.json"), + // "lerna.json": src.File("lerna.json"), + // "yarn.lock": src.File("yarn.lock"), + // ".yarnrc.yml": src.File(".yarnrc.yml"), + // }) + + // This yarn install is ran just to rebuild the yarn pnp files; all of the dependencies should be in the cache by now + return container.WithExec([]string{"yarn", "install", "--immutable"}) +} diff --git a/pkg/build/daggerbuild/frontend/node.go b/pkg/build/daggerbuild/frontend/node.go new file mode 100644 index 00000000000..27084dcbd3a --- /dev/null +++ b/pkg/build/daggerbuild/frontend/node.go @@ -0,0 +1,32 @@ +package frontend + +import ( + "fmt" + "strings" + + "dagger.io/dagger" +) + +// NodeVersionContainer returns a container whose `stdout` will return the node version from the '.nvmrc' file in the directory 'src'. +func NodeVersion(d *dagger.Client, src *dagger.Directory) *dagger.Container { + return d.Container().From("alpine:3.17"). + WithMountedDirectory("/src", src). + WithWorkdir("/src"). + WithExec([]string{"cat", ".nvmrc"}) +} + +func NodeImage(version string) string { + return fmt.Sprintf("node:%s-slim", strings.TrimPrefix(strings.TrimSpace(version), "v")) +} + +// NodeContainer returns a docker container with everything set up that is needed to build or run frontend tests. +func NodeContainer(d *dagger.Client, base string, platform dagger.Platform) *dagger.Container { + container := d.Container(dagger.ContainerOpts{ + Platform: platform, + }).From(base). + WithExec([]string{"apt-get", "update", "-yq"}). + WithExec([]string{"apt-get", "install", "-yq", "make", "git", "g++", "python3"}). + WithEnvVariable("NODE_OPTIONS", "--max_old_space_size=8000") + + return container +} diff --git a/pkg/build/daggerbuild/frontend/npm.go b/pkg/build/daggerbuild/frontend/npm.go new file mode 100644 index 00000000000..fdbc0e2f4eb --- /dev/null +++ b/pkg/build/daggerbuild/frontend/npm.go @@ -0,0 +1,61 @@ +package frontend + +import ( + "context" + "fmt" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +// NPMPackages versions and packs the npm packages into tarballs into `npm-packages` directory. +// It then returns the npm-packages directory as a dagger.Directory. +func NPMPackages(builder *dagger.Container, d *dagger.Client, log *slog.Logger, src *dagger.Directory, ersion string) (*dagger.Directory, error) { + // Check if the version of Grafana uses lerna or nx to manage package versioning. + var ( + out = fmt.Sprintf("/src/npm-packages/%%s-%v.tgz", "v"+ersion) + + lernaBuild = fmt.Sprintf("yarn run packages:build && yarn lerna version %s --exact --no-git-tag-version --no-push --force-publish -y", ersion) + lernaPack = fmt.Sprintf("yarn lerna exec --no-private -- yarn pack --out %s", out) + + nxBuild = fmt.Sprintf("yarn run packages:build && yarn nx release version %s --no-git-commit --no-git-tag --no-stage-changes --group grafanaPackages", ersion) + nxPack = fmt.Sprintf("yarn nx exec --projects=$(cat nx.json | jq -r '.relase.groups.grafanaPackages.projects | join(\",\")') -- yarn pack --out %s", out) + ) + + return builder.WithExec([]string{"mkdir", "npm-packages"}). + WithEnvVariable("SHELL", "/bin/bash"). + WithExec([]string{"yarn", "install", "--immutable"}). + WithExec([]string{"/bin/bash", "-c", fmt.Sprintf("if [ -f lerna.json ]; then %s; else %s; fi", lernaBuild, nxBuild)}). + WithExec([]string{"/bin/bash", "-c", fmt.Sprintf("if [ -f lerna.json ]; then %s; else %s; fi", lernaPack, nxPack)}). + Directory("./npm-packages"), nil +} + +// PublishNPM publishes a npm package to the given destination. +func PublishNPM(ctx context.Context, d *dagger.Client, pkg *dagger.File, token, registry string, tags []string) (string, error) { + src := containers.ExtractedArchive(d, pkg) + + version, err := containers.GetJSONValue(ctx, d, src, "package.json", "version") + if err != nil { + return "", err + } + + name, err := containers.GetJSONValue(ctx, d, src, "package.json", "name") + if err != nil { + return "", err + } + + tokenSecret := d.SetSecret("npm-token", token) + + c := d.Container().From(NodeImage("lts")). + WithFile("/pkg.tgz", pkg). + WithSecretVariable("NPM_TOKEN", tokenSecret). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("npm set //%s/:_authToken $NPM_TOKEN", registry)}). + WithExec([]string{"npm", "publish", "/pkg.tgz", fmt.Sprintf("--registry https://%s", registry), "--tag", tags[0]}) + + for _, tag := range tags[1:] { + c = c.WithExec([]string{"npm", "dist-tag", "add", fmt.Sprintf("%s@%s", name, version), tag}) + } + + return c.Stdout(ctx) +} diff --git a/pkg/build/daggerbuild/frontend/storybook.go b/pkg/build/daggerbuild/frontend/storybook.go new file mode 100644 index 00000000000..8aebc9a7238 --- /dev/null +++ b/pkg/build/daggerbuild/frontend/storybook.go @@ -0,0 +1,10 @@ +package frontend + +import "dagger.io/dagger" + +// Storybook returns a dagger.Directory which contains the built storybook server. +func Storybook(builder *dagger.Container, src *dagger.Directory, version string) *dagger.Directory { + return builder. + WithExec([]string{"yarn", "run", "storybook:build"}). + Directory("./packages/grafana-ui/dist/storybook") +} diff --git a/pkg/build/daggerbuild/frontend/yarn.go b/pkg/build/daggerbuild/frontend/yarn.go new file mode 100644 index 00000000000..a2e32f4feb2 --- /dev/null +++ b/pkg/build/daggerbuild/frontend/yarn.go @@ -0,0 +1,10 @@ +package frontend + +import "dagger.io/dagger" + +func YarnInstall(c *dagger.Client, src *dagger.Directory, version string, cache *dagger.CacheVolume, platform dagger.Platform) *dagger.Container { + return WithYarnCache(NodeContainer(c, NodeImage(version), platform), cache). + WithMountedDirectory("/src", src). + WithWorkdir("/src"). + WithExec([]string{"yarn", "install", "--immutable", "--inline-builds"}) +} diff --git a/pkg/build/daggerbuild/gcom/opts.go b/pkg/build/daggerbuild/gcom/opts.go new file mode 100644 index 00000000000..b2a97839e0b --- /dev/null +++ b/pkg/build/daggerbuild/gcom/opts.go @@ -0,0 +1,34 @@ +package gcom + +import ( + "net/url" + + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" +) + +// GCOMOpts are options used when making requests to grafana.com. +type GCOMOpts struct { + URL *url.URL + DownloadURL *url.URL + ApiKey string + Beta bool + Nightly bool +} + +func GCOMOptsFromFlags(c cliutil.CLIContext) (*GCOMOpts, error) { + apiUrl, err := url.Parse(c.String("api-url")) + if err != nil { + return nil, err + } + downloadUrl, err := url.Parse(c.String("download-url")) + if err != nil { + return nil, err + } + return &GCOMOpts{ + URL: apiUrl, + DownloadURL: downloadUrl, + ApiKey: c.String("api-key"), + Beta: c.Bool("beta"), + Nightly: c.Bool("nightly"), + }, nil +} diff --git a/pkg/build/daggerbuild/gcom/publish.go b/pkg/build/daggerbuild/gcom/publish.go new file mode 100644 index 00000000000..8c656f0acf9 --- /dev/null +++ b/pkg/build/daggerbuild/gcom/publish.go @@ -0,0 +1,60 @@ +package gcom + +import ( + "context" + "encoding/json" + "fmt" + + "dagger.io/dagger" +) + +type GCOMVersionPayload struct { + Version string `json:"version"` + ReleaseDate string `json:"releaseDate"` + Stable bool `json:"stable"` + Beta bool `json:"beta"` + Nightly bool `json:"nightly"` + WhatsNewURL string `json:"whatsNewUrl"` + ReleaseNotesURL string `json:"releaseNotesUrl"` +} + +type GCOMPackagePayload struct { + OS string `json:"os"` + URL string `json:"url"` + Sha256 string `json:"sha256"` + Arch string `json:"arch"` +} + +// PublishGCOMVersion publishes a version to grafana.com. +func PublishGCOMVersion(ctx context.Context, d *dagger.Client, versionPayload *GCOMVersionPayload, opts *GCOMOpts) (string, error) { + versionApiUrl := opts.URL.JoinPath("/versions") + + jsonVersionPayload, err := json.Marshal(versionPayload) + if err != nil { + return "", err + } + + apiKeySecret := d.SetSecret("gcom-api-key", opts.ApiKey) + + return d.Container().From("alpine/curl"). + WithSecretVariable("GCOM_API_KEY", apiKeySecret). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`curl -H "Content-Type: application/json" -H "Authorization: Bearer $GCOM_API_KEY" -d '%s' %s`, string(jsonVersionPayload), versionApiUrl.String())}). + Stdout(ctx) +} + +// PublishGCOMPackage publishes a package to grafana.com. +func PublishGCOMPackage(ctx context.Context, d *dagger.Client, packagePayload *GCOMPackagePayload, opts *GCOMOpts, version string) (string, error) { + packagesApiUrl := opts.URL.JoinPath("/versions/", version, "/packages") + + jsonPackagePayload, err := json.Marshal(packagePayload) + if err != nil { + return "", err + } + + apiKeySecret := d.SetSecret("gcom-api-key", opts.ApiKey) + + return d.Container().From("alpine/curl"). + WithSecretVariable("GCOM_API_KEY", apiKeySecret). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`curl -H "Content-Type: application/json" -H "Authorization: Bearer $GCOM_API_KEY" -d '%s' %s`, string(jsonPackagePayload), packagesApiUrl.String())}). + Stdout(ctx) +} diff --git a/pkg/build/daggerbuild/git/clone.go b/pkg/build/daggerbuild/git/clone.go new file mode 100644 index 00000000000..cd99cdbeecd --- /dev/null +++ b/pkg/build/daggerbuild/git/clone.go @@ -0,0 +1 @@ +package git diff --git a/pkg/build/daggerbuild/git/container.go b/pkg/build/daggerbuild/git/container.go new file mode 100644 index 00000000000..7bf00cce545 --- /dev/null +++ b/pkg/build/daggerbuild/git/container.go @@ -0,0 +1,139 @@ +package git + +import ( + "context" + "errors" + "fmt" + "log" + "net/url" + "path/filepath" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +const GitImage = "alpine/git" + +type GitCloneOptions struct { + Ref string + URL string + + SSHKeyPath string + + // Username is injected into the final URL used for cloning + Username string + // Password is injected into the final URL used for cloning + Password string +} + +// CloneContainer returns the container definition that uses git clone to clone the 'git url' and checks out the ref provided at 'ref'. +// Multiple refs can be provided via a space character (' '). If multiple refs are provided, then the container will attempt to checkout +// each ref at a time, stopping at the first one that is successful. +// This can be useful in PRs which have a coupled association with another codebase. +// A practical example (and why this exists): "${pr_source_branch} ${pr_target_branch} ${main}" will first attempt to checkout the PR source branch, then the PR target branch, then "main"; whichever is successul first. +func CloneContainer(d *dagger.Client, opts *GitCloneOptions) (*dagger.Container, error) { + var err error + if opts.URL == "" { + return nil, errors.New("URL can not be empty") + } + + if opts.SSHKeyPath != "" && (opts.Username != "" || opts.Password != "") { + return nil, fmt.Errorf("conflicting options: use either username/password or an SSH key") + } + + cloneURL := opts.URL + if opts.Username != "" && opts.Password != "" { + cloneURL, err = injectURLCredentials(cloneURL, opts.Username, opts.Password) + if err != nil { + return nil, fmt.Errorf("failed to inject credentials into cloning URL: %w", err) + } + } + + cloneArgs := []string{"git", "clone"} + + cloneArgs = append(cloneArgs, "${GIT_CLONE_URL}", "src") + + container := d.Container().From(GitImage). + WithEnvVariable("REF", opts.Ref). + WithEnvVariable("UNAUTHENTICATED_CLONE_URL", opts.URL). + WithEntrypoint([]string{}) + + if opts.SSHKeyPath != "" { + if !strings.Contains(opts.URL, "@") { + return nil, errors.New("git URL with SSH needs an '@'") + } + if !strings.Contains(opts.URL, ":") { + return nil, errors.New("git URL with SSH needs a ':'") + } + + host := opts.URL[strings.Index(opts.URL, "@")+1 : strings.Index(opts.URL, ":")] + + container = container. + WithExec([]string{"mkdir", "-p", "/root/.ssh"}). + WithMountedFile("/root/.ssh/id_rsa", d.Host().Directory(filepath.Dir(opts.SSHKeyPath)).File(filepath.Base(opts.SSHKeyPath))). + WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`ssh-keyscan %s > /root/.ssh/known_hosts`, host)}) + } + + cloneURLSecret := d.SetSecret("git-clone-url", cloneURL) + + // GIT_REFS is included as an environment variable here to control caching. + // 1. We should ALWAYS be using the commit hash to clone / checkout git refs. + // 2. If the ref changes, then we should run 'fetch' again. + container = container. + WithSecretVariable("GIT_CLONE_URL", cloneURLSecret). + WithExec([]string{"/bin/sh", "-c", strings.Join(cloneArgs, " ")}). + WithEnvVariable("GIT_REFS", opts.Ref). + WithExec([]string{"git", "-C", "src", "fetch"}) + + ref := "main" + if opts.Ref != "" { + ref = opts.Ref + } + + // TODO: this section really needs to be its own function with unit tests, or an interface or something. + var ( + checkouts = strings.Split(ref, " ") + checkoutArgs = []string{fmt.Sprintf(`if git -C src checkout %[1]s; then echo "checked out %[1]s";`, checkouts[0])} + ) + + for _, v := range checkouts[1:] { + checkoutArgs = append(checkoutArgs, fmt.Sprintf(`elif git -C src checkout %[1]s; then echo "checked out %[1]s";`, v)) + } + + checkoutArgs = append(checkoutArgs, "else exit 3; fi") + + container = container.WithExec([]string{"/bin/sh", "-c", strings.Join(checkoutArgs, " ")}) + log.Println(strings.Join(checkoutArgs, " ")) + return container, nil +} + +func CloneWithGitHubToken(d *dagger.Client, token, url, ref string) (*dagger.Directory, error) { + container, err := CloneContainer(d, &GitCloneOptions{ + URL: url, + Ref: ref, + Username: "x-oauth-token", + Password: token, + }) + if err != nil { + return nil, err + } + + container, err = containers.ExitError(context.Background(), container) + if err != nil { + return nil, err + } + + return container.Directory("src"), nil +} + +// injectURLCredentials modifies as provided URL to set the given username and password in it. +func injectURLCredentials(u string, username string, password string) (string, error) { + rawURL, err := url.Parse(u) + if err != nil { + return "", err + } + ui := url.UserPassword(username, password) + rawURL.User = ui + return rawURL.String(), nil +} diff --git a/pkg/build/daggerbuild/git/container_test.go b/pkg/build/daggerbuild/git/container_test.go new file mode 100644 index 00000000000..6a678088424 --- /dev/null +++ b/pkg/build/daggerbuild/git/container_test.go @@ -0,0 +1,17 @@ +package git + +import ( + "testing" +) + +func TestInjectURLCredentials(t *testing.T) { + expected := "https://username:password@example.org/somepath?query=param" + input := "https://example.org/somepath?query=param" + output, err := injectURLCredentials(input, "username", "password") + if err != nil { + t.Fatal("Unexpected error from injectURLCredentials:", err) + } + if expected != output { + t.Fatalf("Unexpected output. Expected '%s', got '%s'", expected, output) + } +} diff --git a/pkg/build/daggerbuild/git/github.go b/pkg/build/daggerbuild/git/github.go new file mode 100644 index 00000000000..01970aa3b59 --- /dev/null +++ b/pkg/build/daggerbuild/git/github.go @@ -0,0 +1,44 @@ +package git + +import ( + "bytes" + "context" + "fmt" + "log" + "os" + "os/exec" + "strings" +) + +// LookupGitHubToken will try to find a GitHub access token that can then be used for various API calls but also cloning of private repositories. +func LookupGitHubToken(ctx context.Context) (string, error) { + log.Print("Looking for a GitHub token") + + // First try: Check if it's in the environment. This can override everything! + token := os.Getenv("GITHUB_TOKEN") + if token != "" { + log.Print("Using GitHub token provided via environment variable") + return token, nil + } + + // Next, check if the user has gh installed and *it* has a token set: + var data bytes.Buffer + var errData bytes.Buffer + ghPath, err := exec.LookPath("gh") + if err != nil { + return "", fmt.Errorf("GitHub CLI not installed (expected a --github-token flag, a GITHUB_TOKEN environment variable, or a configured GitHub CLI)") + } + + //nolint:gosec + cmd := exec.CommandContext(ctx, ghPath, "auth", "token") + cmd.Stdout = &data + cmd.Stderr = &errData + + if err := cmd.Run(); err != nil { + log.Printf("Querying gh for an access token failed: %s", errData.String()) + return "", fmt.Errorf("lookup in gh failed: %w", err) + } + + log.Print("Using GitHub token provided via gh") + return strings.TrimSpace(data.String()), nil +} diff --git a/pkg/build/daggerbuild/golang/cache.go b/pkg/build/daggerbuild/golang/cache.go new file mode 100644 index 00000000000..09d7f7b1e03 --- /dev/null +++ b/pkg/build/daggerbuild/golang/cache.go @@ -0,0 +1,28 @@ +package golang + +import ( + "fmt" + + "dagger.io/dagger" +) + +func DownloadURL(version, arch string) string { + return fmt.Sprintf("https://go.dev/dl/go%s.linux-%s.tar.gz", version, arch) +} + +func Container(d *dagger.Client, platform dagger.Platform, version string) *dagger.Container { + opts := dagger.ContainerOpts{ + Platform: platform, + } + + goImage := fmt.Sprintf("golang:%s-alpine", version) + + return d.Container(opts).From(goImage) +} + +func WithCachedGoDependencies(container *dagger.Container, cache *dagger.CacheVolume) *dagger.Container { + return container. + WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). + WithMountedCache("/go/pkg/mod", cache). + WithExec([]string{"ls", "-al", "/go/pkg/mod"}) +} diff --git a/pkg/build/daggerbuild/gpg/sign.go b/pkg/build/daggerbuild/gpg/sign.go new file mode 100644 index 00000000000..b9304f5d730 --- /dev/null +++ b/pkg/build/daggerbuild/gpg/sign.go @@ -0,0 +1,65 @@ +package gpg + +import ( + "dagger.io/dagger" +) + +const RPMMacros = ` +%_signature gpg +%_gpg_path /root/.gnupg +%_gpg_name Grafana +%_gpgbin /usr/bin/gpg2 +%__gpg_sign_cmd %{__gpg} gpg \ + --batch --yes --no-armor --pinentry-mode loopback \ + --passphrase-file /root/.rpmdb/passkeys/grafana.key \ + --no-secmem-warning -u "%{_gpg_name}" -sbo %{__signature_filename} \ + %{?_gpg_digest_algo:--digest-algo %{_gpg_digest_algo}} %{__plaintext_filename} +` + +type GPGOpts struct { + GPGPrivateKey string + GPGPublicKey string + GPGPassphrase string +} + +func Signer(d *dagger.Client, pubkey, privkey, passphrase string) *dagger.Container { + var ( + gpgPublicKeySecret = d.SetSecret("gpg-public-key", pubkey) + gpgPrivateKeySecret = d.SetSecret("gpg-private-key", privkey) + gpgPassphraseSecret = d.SetSecret("gpg-passphrase", passphrase) + ) + + return d.Container().From("debian:stable"). + WithExec([]string{"apt-get", "update"}). + WithExec([]string{"apt-get", "install", "-yq", "rpm", "gnupg2", "file"}). + WithMountedSecret("/root/.rpmdb/privkeys/grafana.key", gpgPrivateKeySecret). + WithMountedSecret("/root/.rpmdb/pubkeys/grafana.key", gpgPublicKeySecret). + WithMountedSecret("/root/.rpmdb/passkeys/grafana.key", gpgPassphraseSecret). + WithExec([]string{"/bin/sh", "-c", ` + echo "DEBUG: Mounted RPM Pub Key file detected to be: $(file "/root/.rpmdb/pubkeys/grafana.key")"; + echo "DEBUG: Mounted RPM Pub Key file has $(wc -c "/root/.rpmdb/pubkeys/grafana.key") bytes"; + echo "DEBUG: Mounted RPM Pub Key file has $(wc -l "/root/.rpmdb/pubkeys/grafana.key") lines"; + if grep -q "PUBLIC KEY" "/root/.rpmdb/pubkeys/grafana.key"; then + cp "/root/.rpmdb/pubkeys/grafana.key" "/tmp/grafana.key"; + else + gpg --enarmor "/root/.rpmdb/pubkeys/grafana.key" > "/tmp/grafana.key"; + fi; + if [ "$(tail -n 1 "/tmp/grafana.key" | wc -l)" = 0 ]; then + echo >> "/tmp/grafana.key"; + fi; + echo "DEBUG: Final RPM Pub Key file has $(wc -c "/tmp/grafana.key") bytes"; + echo "DEBUG: Final RPM Pub Key file has $(wc -l "/tmp/grafana.key") lines"; + `}). + WithExec([]string{"rpm", "--import", "/tmp/grafana.key"}). + WithNewFile("/root/.rpmmacros", RPMMacros, dagger.ContainerWithNewFileOpts{ + Permissions: 0400, + }). + WithExec([]string{"gpg", "--batch", "--yes", "--no-tty", "--allow-secret-key-import", "--import", "/root/.rpmdb/privkeys/grafana.key"}) +} + +func Sign(d *dagger.Client, file *dagger.File, opts GPGOpts) *dagger.File { + return Signer(d, opts.GPGPublicKey, opts.GPGPrivateKey, opts.GPGPassphrase). + WithMountedFile("/src/package.rpm", file). + WithExec([]string{"rpm", "--addsign", "/src/package.rpm"}). + File("/src/package.rpm") +} diff --git a/pkg/build/daggerbuild/gpg/verify.go b/pkg/build/daggerbuild/gpg/verify.go new file mode 100644 index 00000000000..005ec8b8b87 --- /dev/null +++ b/pkg/build/daggerbuild/gpg/verify.go @@ -0,0 +1,20 @@ +package gpg + +import ( + "context" + "fmt" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +func VerifySignature(ctx context.Context, d *dagger.Client, file *dagger.File, pubKey, privKey, passphrase string) error { + container := Signer(d, pubKey, privKey, passphrase). + WithFile("/src/package.rpm", file). + WithExec([]string{"/bin/sh", "-c", "rpm --checksig /src/package.rpm"}) + + if _, err := containers.ExitError(ctx, container); err != nil { + return fmt.Errorf("failed to validate gpg signature for rpm package: %w", err) + } + return nil +} diff --git a/pkg/build/daggerbuild/mkdocs.yml b/pkg/build/daggerbuild/mkdocs.yml new file mode 100755 index 00000000000..603decb1278 --- /dev/null +++ b/pkg/build/daggerbuild/mkdocs.yml @@ -0,0 +1,32 @@ +docs_dir: docs +edit_uri: edit/main/docs/ +markdown_extensions: + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format +nav: + - index.md + - "Why Dagger?": why-dagger.md + - "Guides": + - guides/building.md + - guides/tracing.md + - "Artifact types": + - "Overview": artifact-types/index.md + - "Tarball": artifact-types/tarball.md + - "RPM": artifact-types/rpm.md + - "Debian": artifact-types/deb.md + - "Windows installer": artifact-types/windows-installer.md + - "Docker image": artifact-types/docker-image.md + - "ZIP": artifact-types/zip.md + - "Meta": + - meta/docs.md +repo_url: https://github.com/grafana/grafana-build +site_name: Grafana Build +theme: + features: + - content.action.edit + - content.code.copy + - navigation.footer + name: material diff --git a/pkg/build/daggerbuild/msi/build.go b/pkg/build/daggerbuild/msi/build.go new file mode 100644 index 00000000000..109b6580f00 --- /dev/null +++ b/pkg/build/daggerbuild/msi/build.go @@ -0,0 +1,67 @@ +package msi + +import ( + "fmt" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +func Build(d *dagger.Client, builder *dagger.Container, targz *dagger.File, version string, enterprise bool) (*dagger.File, error) { + wxsFiles, err := WXSFiles(version, enterprise) + if err != nil { + return nil, fmt.Errorf("error generating wxs files: %w", err) + } + + f := containers.ExtractedArchive(d, targz) + builder = builder.WithDirectory("/src/grafana", f, dagger.ContainerWithDirectoryOpts{ + // Hack from grafana/build-pipeline: Remove files with names too long... + Exclude: []string{ + "public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_querystring_builder.test.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_querystring_builder.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_datasource.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_datasource.test.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/insights_analytics/insights_analytics_datasource.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_filter_builder.test.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_filter_builder.ts", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.test.tsx", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AzureCredentialsForm.test.tsx", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.test.tsx", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/AnalyticsConfig.test.tsx.snap", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/AzureCredentialsForm.test.tsx.snap", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/InsightsConfig.test.tsx.snap", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/ConfigEditor.test.tsx.snap", + "storybook", + }, + }).WithWorkdir("/src") + + for _, v := range wxsFiles { + builder = builder.WithNewFile(v.Name, v.Contents) + } + + // 1. `heat`: create 'grafana.wxs' + // 2. 'candle': Compile .wxs files into .wixobj + // 3. `light`: assembles the MSI + builder = builder. + WithExec([]string{"/bin/sh", "-c", "cp -r /src/resources/resources/* /src && rm -rf /src/resources"}). + WithExec([]string{"/bin/sh", "-c", `WINEPATH=$(winepath /src/wix3) wine heat dir /src -platform x64 -sw5150 -srd -cg GrafanaX64 -gg -sfrag -dr GrafanaX64Dir -template fragment -out $(winepath -w grafana.wxs)`}). + WithExec([]string{"winepath"}). + WithExec([]string{"mkdir", "/root/.wine/drive_c/temp"}) + + for _, name := range []string{ + "grafana-service.wxs", + "grafana-firewall.wxs", + "grafana.wxs", + "grafana-product.wxs", + } { + builder = builder.WithExec([]string{"/bin/sh", "-c", fmt.Sprintf(`WINEPATH=$(winepath /src/wix3) wine candle -ext WixFirewallExtension -ext WixUtilExtension -v -arch x64 $(winepath -w %s)`, name)}) + } + builder = builder. + WithExec([]string{"/bin/bash", "-c", "WINEPATH=$(winepath /src/wix3) wine light -cultures:en-US -ext WixUIExtension.dll -ext WixFirewallExtension -ext WixUtilExtension -v -sval -spdb grafana-service.wixobj grafana-firewall.wixobj grafana.wixobj grafana-product.wixobj -out $(winepath -w /src/grafana.msi)"}) + + return builder.File("/src/grafana.msi"), nil +} diff --git a/pkg/build/daggerbuild/msi/builder.go b/pkg/build/daggerbuild/msi/builder.go new file mode 100644 index 00000000000..3af334c27eb --- /dev/null +++ b/pkg/build/daggerbuild/msi/builder.go @@ -0,0 +1,28 @@ +package msi + +import ( + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +func Builder(d *dagger.Client) (*dagger.Container, error) { + nssm := d.Container().From("busybox"). + WithExec([]string{"wget", "https://nssm.cc/release/nssm-2.24.zip"}). + WithExec([]string{"unzip", "nssm-2.24.zip"}). + Directory("nssm-2.24") + + wix3 := d.Container().From("busybox"). + WithWorkdir("/src"). + WithExec([]string{"wget", "https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip"}). + WithExec([]string{"unzip", "wix314-binaries.zip"}). + WithExec([]string{"rm", "wix314-binaries.zip"}). + Directory("/src") + + builder := d.Container().From("scottyhardy/docker-wine:stable-9.0"). + WithEntrypoint([]string{}). + WithMountedDirectory("/src/nssm-2.24", nssm). + WithMountedDirectory("/src/wix3", wix3). + WithWorkdir("/src") + + return containers.WithEmbeddedFS(d, builder, "/src/resources", resources) +} diff --git a/pkg/build/daggerbuild/msi/embed.go b/pkg/build/daggerbuild/msi/embed.go new file mode 100644 index 00000000000..3f1152eda27 --- /dev/null +++ b/pkg/build/daggerbuild/msi/embed.go @@ -0,0 +1,6 @@ +package msi + +import "embed" + +//go:embed resources/* +var resources embed.FS diff --git a/pkg/build/daggerbuild/msi/resources/EE_LICENSE.rtf b/pkg/build/daggerbuild/msi/resources/EE_LICENSE.rtf new file mode 100644 index 00000000000..31b05d12df4 --- /dev/null +++ b/pkg/build/daggerbuild/msi/resources/EE_LICENSE.rtf @@ -0,0 +1,1332 @@ +{\rtf1\ansi\ansicpg1252\uc0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deff0\adeff0{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f2\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}{\f3\fnil\fcharset0 Lemon;}{\f4\fnil\fcharset0 Helvetica Neue +;}{\f5\fnil\fcharset0 Georgia;}}{\colortbl;\red0\green0\blue0;\red102\green102\blue102;}{\stylesheet{\s0\snext0\sqformat\spriority0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1 Normal;}{\s1\sbasedon0\snext0\styrsid15694742 +\sqformat\spriority0\keep\keepn\fi0\sb480\sa120\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs48\ltrch\b\i0\fs48\f0\strike0\ulnone\cf1 heading 1;}{\s2\sbasedon0\snext0\styrsid15694742\sqformat\spriority0 +\keep\keepn\fi0\sb360\sa80\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs36\ltrch\b\i0\fs36\f0\strike0\ulnone\cf1 heading 2;}{\s3\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb280\sa80 +\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs28\ltrch\b\i0\fs28\f0\strike0\ulnone\cf1 heading 3;}{\s4\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb240\sa40\aspalpha\aspnum +\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs24\ltrch\b\i0\fs24\f0\strike0\ulnone\cf1 heading 4;}{\s5\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb220\sa40\aspalpha\aspnum\adjustright\widctlpar +\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs22\ltrch\b\i0\fs22\f0\strike0\ulnone\cf1 heading 5;}{\s6\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb200\sa40\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0 +\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs20\ltrch\b\i0\fs20\f0\strike0\ulnone\cf1 heading 6;}{\*\cs10\additive\ssemihidden\spriority0 Default Paragraph Font;}{\s15\sbasedon0\snext15\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb480\sa120 +\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs72\ltrch\b\i0\fs72\f0\strike0\ulnone\cf1 Title;}{\s16\sbasedon0\snext16\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb360\sa80\aspalpha\aspnum +\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai\af5\afs48\ltrch\b0\i\fs48\loch\af5\dbch\af5\hich\f5\strike0\ulnone\cf2 Subtitle;}}{\*\rsidtbl\rsid10976062}{\*\generator Aspose.Words for Java 13.12.0.0;}{\info\version1\edmins0\nofpages1\nofwords0\nofchars0\nofcharsws0}{\mmathPr\mbrkBin0\mbrkBinSub0\mdefJc1\mdispDef1\minterSp0\mintLim0\mintraSp0\mlMargin0\mmathFont0\mnaryLim1\mpostSp0\mpreSp0\mrMargin0\msmallFrac0\mwrapIndent1440\mwrapRight0} +\deflang1033\deflangfe2052\adeflang1025\jexpand\showxmlerrors1\validatexml1{\*\wgrffmtfilter 013f}\viewkind1\viewscale100\fet0\ftnbj\aenddoc\ftnrstcont\aftnrstcont\ftnnar\aftnnrlc\widowctrl\nospaceforul\nolnhtadjtbl\alntblind\lyttblrtgr\dntblnsbdb\noxlattoyen +\wrppunct\nobrkwrptbl\expshrtn\snaptogridincell\asianbrkrule\htmautsp\noultrlspc\useltbaln\splytwnine\ftnlytwnine\lytcalctblwd\allowfieldendsel\lnbrkrule\nouicompat\nofeaturethrottle1\formshade\nojkernpunct\dghspace180\dgvspace180\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1 +\dgmargin\pgbrdrhead\pgbrdrfoot\sectd\sectlinegrid360\pgwsxn12240\pghsxn15840\marglsxn720\margrsxn720\margtsxn1440\margbsxn1440\guttersxn0\headery708\footery708\colsx708\ltrsect{\header\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw +\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1\par}}{\footer\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha +\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1\par}}\pard +\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl +\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par} +\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PLEASE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 READ}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CAREFULLY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 "), }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WHICH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 CONSTITUTES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LEGALLY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BINDING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GOVERNS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 ALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOUR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WHICH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCLUDED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (\u8220 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 \u8221 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 THAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PROVIDED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OBJECT}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CODE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FORMAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INSTALLING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 USING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GOVERNED}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FREE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 VERSION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ENTERPRISE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 ARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ASSENTING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 IF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NOT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NOT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 INSTALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 GOVERNED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IF}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 INSTALLING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ON}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BEHALF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LEGAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ENTITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 REPRESENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 WARRANT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 HAVE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ACTUAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AUTHORITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ON}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BEHALF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ENTITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar +\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Posted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Date}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 : }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Jan}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 10, 2020}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entered}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 into}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 between}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Inc}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 (\u8220 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ") }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 legal}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 behalf}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whom}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 acting}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ").}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OBJECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CODE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 END}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESTRICTIONS} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIRD}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 PARTY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OPEN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOURCE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl +\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par} +\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 End}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 User}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conditions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Section}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 hereby}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grants}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 AT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CHARGE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 so}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 long}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 you}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provision}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 free}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 features}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 functions}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Enterprise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Reservation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Rights}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ; }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Restrictions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 As}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 between}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 licensors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 own}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 title}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 interest}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 expressly}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 set}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 forth}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Sections}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 no}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 granted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 under}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 implication}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 estoppel}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 agree}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 : (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 i}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reverse}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 engineer}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 decompile}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 decrypt}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 disassemble}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reduce}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 portion}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 thereof}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 only}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 extent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 restriction}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 prohibited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 , (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ii}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 expressly}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 permitted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Section}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 1.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 above}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transfer}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sell}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 rent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 lease}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 distribute}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sublicense}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 loan}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transfer}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whole}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 part}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ; (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 iii}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 providing}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 time}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 sharing}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 services}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 service}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 service}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 bureau}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 services}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 part}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 an}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 application}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 services}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 provider}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 service}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 offering}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 collectively}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , "}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ") }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 obtaining}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 access}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 features}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 functions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 primary}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reason}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 substantial}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 motivation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 users}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 access}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 /}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ("}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Prohibited} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "); (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 iv}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 circumvent}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limitations}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 format}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 imposed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 preserved}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Key}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 v}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 alter}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 remove}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Marks}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Notices}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 If}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 question}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 whether}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 specific}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 constitutes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Prohibited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 interested}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 obtaining}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 '}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 s}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 permission}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 engage}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 distribution}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 please}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contact}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sales}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 @}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grafana}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 com}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.3 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 libraries}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 components}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 utilities} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 collectively}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "), }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 identified}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 website}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 designated}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Notwithstanding} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 anything}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contrary}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 herein}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 conditions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 extent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 required}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 licensor} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 restrict}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 rights}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 granted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 hereunder}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 additional}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 rights}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ). }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 To}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 extent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 condition}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conflicts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 govern}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 respect}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 only}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 also}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 separately}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provide} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 you}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 certain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 licensed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 governed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1 +\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMINATION}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 automatically}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terminate}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whether}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 receive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 notice}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 from}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 if}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provisions}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Post}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Upon}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reason}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 promptly}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 cease}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 format}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 For}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 avoidance}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 doubt}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 affect}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 either}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 formats}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 made}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 available}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 under}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Apache}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Version}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.0.}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.3 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Survival}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Sections}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.2, 2.2. 2.3, 3 } +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 4 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 survive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 expiration}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 3. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DISCLAIMER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANTIES}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LIMITATION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LIABILITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 3.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Disclaimer}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Warranties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAXIMUM}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 EXTENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERMITTED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 UNDER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 APPLICABLE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LAW}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PROVIDED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AS}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITHOUT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 WARRANTY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 KIND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ITS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSORS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAKE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANTIES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 WHETHER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EXPRESSED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IMPLIED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 STATUTORY}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 REGARDING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 RELATING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LAB}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAXIMUM}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EXTENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERMITTED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 UNDER}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 APPLICABLE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LAW}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ITS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSORS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SPECIFICALLY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DISCLAIM}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 ALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IMPLIED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANTIES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MERCHANTABILITY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FITNESS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PARTICULAR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PURPOSE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NON}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INFRINGEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESPECT}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESPECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOREGOING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FURTHER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DOES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NOT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANT}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESULTS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WILL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 ERROR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FREE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 UNINTERRUPTED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard +\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 3.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Limitation}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Liability}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IN}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EVENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 SHALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ITS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSORS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 LIABLE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIRD}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PARTY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DIRECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INDIRECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DAMAGES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCLUDING} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITHOUT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LIMITATION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LOSS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PROFITS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LOSS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BUSINESS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INTERRUPTION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 LOSS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DATA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 COST}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SUBSTITUTE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GOODS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SERVICES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SPECIAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCIDENTAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONSEQUENTIAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DAMAGES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 KIND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONNECTION}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ARISING}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OUT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INABILITY}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERFORMANCE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FAILURE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERFORM}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WHETHER} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ALLEGED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BREACH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 CONTRACT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TORTIOUS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDUCT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCLUDING} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NEGLIGENCE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EVEN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 HAS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BEEN}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ADVISED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 POSSIBILITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DAMAGES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar +\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 4. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MISCELLANEOUS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 completely}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 exclusively}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 states}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entire}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 agreement}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 regarding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 matter}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 herein}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 it}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 supersedes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 govern}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 prior}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 proposals}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 agreements}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 communications}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 between}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 oral}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 written}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 regarding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 matter}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modified}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 from}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 time}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 time}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modifications}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 effective}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 upon}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Posted}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Date}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 set}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 forth}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 top}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modified}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 If}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provision}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 hereof}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 held}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 unenforceable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 continue}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 said}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provision}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 interpreted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reflect}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 original}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 intent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contractual}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 obligation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 arising} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 out}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 it}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 governed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 exclusively} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 New}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 York}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 governed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1980 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 UN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Convention}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contracts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 International}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Sale}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Goods}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 All}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 disputes}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 arising}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 out}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 existence}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 validity}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 resolved}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 courts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 jurisdiction}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 New}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 York}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 City}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 mandatory}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provides}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 courts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 another}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 location}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 United}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 States}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 jurisdiction}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 hereby}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 irrevocably}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 waive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 claims}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 defenses}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 either}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 might}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 action}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 proceeding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 courts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 based}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 upon}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 alleged}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 lack}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 personal}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 jurisdiction}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 improper}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 venue}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 forum}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conveniens}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 similar}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 claim}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 defense}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 threatened}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Section}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 cause}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 irreparable}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 harm}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 damages}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provide}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 adequate}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 relief}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 therefore}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entitled}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 seek}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 injunctive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 relief}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 being}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 required}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 post}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 bond}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 assign}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 operation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 merger}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 acquisition}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ), }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whole}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 part}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 prior}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 written}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 consent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 withheld}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 granted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sole}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 absolute}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 discretion} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 assignment}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 violation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 preceding}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sentence}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 void}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Notices}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 also}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 legal}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 @}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 com}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb +\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard +\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DEFINITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par} +\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 following}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 meanings}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ascribed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 :}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0 +\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.1 "} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliate}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 respect}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 controls}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 controlled}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 under}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 common}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 control}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 control}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ownership}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 least}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 fifty}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 percent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (50%) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 outstanding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 voting} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shares}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contractual}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 establish}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 policy}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 manage}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 operations}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0 +\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0 +\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.2 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercially}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 free}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 version}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Enterprise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Enterprise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 5.3 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 exclusive}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transferable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 fully}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 paid}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 up}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 royalty}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 free}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grant}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 authorize}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sublicenses}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 solely}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 internal}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 business}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 operations} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 i}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 install}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Features}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Functions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ii}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 permit}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contractors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliates}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 set}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 forth}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 i}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 above}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contractors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 must}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 solely}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 benefit}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 /}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 benefit}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliates}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 responsible}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 acts}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 omissions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contractors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliates}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 their}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 contrary}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conditions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 5.4 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Key}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sequence}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 bytes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 JSON}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 blob}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 used}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 enable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 certain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 features}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 functions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.5 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Marks}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Notices}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 trademarks}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 trade}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 names}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 logos}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 notices}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 present}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Documentation}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 originally}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1 +\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.6 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 production}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Environment}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 an}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 environment}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 development}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 testing}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 quality}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 assurance}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 used}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 production}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 purposes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.7 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 form}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 resulting}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 from}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 mechanical}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transformation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 translation}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 form}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 compiled}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 generated}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 documentation}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conversions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 media}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 types}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.8 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 preferred}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 form}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 computer}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 making}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modifications}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 documentation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 configuration}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 files}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.9 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Subscription}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 receive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Support}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Services}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af4\afs22 +\ltrch\b0\i0\fs22\loch\af4\dbch\af4\hich\f4\insrsid10976062\strike0\ulnone\cf1\par}{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef0{\lsdlockedexcept\lsdqformat1 Normal;\lsdqformat1 heading 1;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 2;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 3 +;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 4;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 5;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 6;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 7;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 8 +;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 9;\lsdsemihidden1\lsdunhideused1\lsdqformat1 caption;\lsdqformat1 Title;\lsdqformat1 Subtitle;\lsdqformat1 Strong;\lsdqformat1 Emphasis;\lsdsemihidden1\lsdpriority99 Placeholder Text;\lsdqformat1\lsdpriority1 No Spacing +;\lsdpriority60 Light Shading;\lsdpriority61 Light List;\lsdpriority62 Light Grid;\lsdpriority63 Medium Shading 1;\lsdpriority64 Medium Shading 2;\lsdpriority65 Medium List 1;\lsdpriority66 Medium List 2;\lsdpriority67 Medium Grid 1;\lsdpriority68 Medium Grid 2 +;\lsdpriority69 Medium Grid 3;\lsdpriority70 Dark List;\lsdpriority71 Colorful Shading;\lsdpriority72 Colorful List;\lsdpriority73 Colorful Grid;\lsdpriority60 Light Shading Accent 1;\lsdpriority61 Light List Accent 1;\lsdpriority62 Light Grid Accent 1;\lsdpriority63 Medium Shading 1 Accent 1 +;\lsdpriority64 Medium Shading 2 Accent 1;\lsdpriority65 Medium List 1 Accent 1;\lsdsemihidden1\lsdpriority99 Revision;\lsdqformat1\lsdpriority34 List Paragraph;\lsdqformat1\lsdpriority29 Quote;\lsdqformat1\lsdpriority30 Intense Quote;\lsdpriority66 Medium List 2 Accent 1 +;\lsdpriority67 Medium Grid 1 Accent 1;\lsdpriority68 Medium Grid 2 Accent 1;\lsdpriority69 Medium Grid 3 Accent 1;\lsdpriority70 Dark List Accent 1;\lsdpriority71 Colorful Shading Accent 1;\lsdpriority72 Colorful List Accent 1;\lsdpriority73 Colorful Grid Accent 1 +;\lsdpriority60 Light Shading Accent 2;\lsdpriority61 Light List Accent 2;\lsdpriority62 Light Grid Accent 2;\lsdpriority63 Medium Shading 1 Accent 2;\lsdpriority64 Medium Shading 2 Accent 2;\lsdpriority65 Medium List 1 Accent 2;\lsdpriority66 Medium List 2 Accent 2 +;\lsdpriority67 Medium Grid 1 Accent 2;\lsdpriority68 Medium Grid 2 Accent 2;\lsdpriority69 Medium Grid 3 Accent 2;\lsdpriority70 Dark List Accent 2;\lsdpriority71 Colorful Shading Accent 2;\lsdpriority72 Colorful List Accent 2;\lsdpriority73 Colorful Grid Accent 2 +;\lsdpriority60 Light Shading Accent 3;\lsdpriority61 Light List Accent 3;\lsdpriority62 Light Grid Accent 3;\lsdpriority63 Medium Shading 1 Accent 3;\lsdpriority64 Medium Shading 2 Accent 3;\lsdpriority65 Medium List 1 Accent 3;\lsdpriority66 Medium List 2 Accent 3 +;\lsdpriority67 Medium Grid 1 Accent 3;\lsdpriority68 Medium Grid 2 Accent 3;\lsdpriority69 Medium Grid 3 Accent 3;\lsdpriority70 Dark List Accent 3;\lsdpriority71 Colorful Shading Accent 3;\lsdpriority72 Colorful List Accent 3;\lsdpriority73 Colorful Grid Accent 3 +;\lsdpriority60 Light Shading Accent 4;\lsdpriority61 Light List Accent 4;\lsdpriority62 Light Grid Accent 4;\lsdpriority63 Medium Shading 1 Accent 4;\lsdpriority64 Medium Shading 2 Accent 4;\lsdpriority65 Medium List 1 Accent 4;\lsdpriority66 Medium List 2 Accent 4 +;\lsdpriority67 Medium Grid 1 Accent 4;\lsdpriority68 Medium Grid 2 Accent 4;\lsdpriority69 Medium Grid 3 Accent 4;\lsdpriority70 Dark List Accent 4;\lsdpriority71 Colorful Shading Accent 4;\lsdpriority72 Colorful List Accent 4;\lsdpriority73 Colorful Grid Accent 4 +;\lsdpriority60 Light Shading Accent 5;\lsdpriority61 Light List Accent 5;\lsdpriority62 Light Grid Accent 5;\lsdpriority63 Medium Shading 1 Accent 5;\lsdpriority64 Medium Shading 2 Accent 5;\lsdpriority65 Medium List 1 Accent 5;\lsdpriority66 Medium List 2 Accent 5 +;\lsdpriority67 Medium Grid 1 Accent 5;\lsdpriority68 Medium Grid 2 Accent 5;\lsdpriority69 Medium Grid 3 Accent 5;\lsdpriority70 Dark List Accent 5;\lsdpriority71 Colorful Shading Accent 5;\lsdpriority72 Colorful List Accent 5;\lsdpriority73 Colorful Grid Accent 5 +;\lsdpriority60 Light Shading Accent 6;\lsdpriority61 Light List Accent 6;\lsdpriority62 Light Grid Accent 6;\lsdpriority63 Medium Shading 1 Accent 6;\lsdpriority64 Medium Shading 2 Accent 6;\lsdpriority65 Medium List 1 Accent 6;\lsdpriority66 Medium List 2 Accent 6 +;\lsdpriority67 Medium Grid 1 Accent 6;\lsdpriority68 Medium Grid 2 Accent 6;\lsdpriority69 Medium Grid 3 Accent 6;\lsdpriority70 Dark List Accent 6;\lsdpriority71 Colorful Shading Accent 6;\lsdpriority72 Colorful List Accent 6;\lsdpriority73 Colorful Grid Accent 6 +;\lsdqformat1\lsdpriority19 Subtle Emphasis;\lsdqformat1\lsdpriority21 Intense Emphasis;\lsdqformat1\lsdpriority31 Subtle Reference;\lsdqformat1\lsdpriority32 Intense Reference;\lsdqformat1\lsdpriority33 Book Title;\lsdsemihidden1\lsdunhideused1\lsdpriority37 Bibliography +;\lsdsemihidden1\lsdunhideused1\lsdqformat1\lsdpriority39 TOC Heading;}}} \ No newline at end of file diff --git a/pkg/build/daggerbuild/msi/resources/LICENSE.md b/pkg/build/daggerbuild/msi/resources/LICENSE.md new file mode 100644 index 00000000000..be3f7b28e56 --- /dev/null +++ b/pkg/build/daggerbuild/msi/resources/LICENSE.md @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/pkg/build/daggerbuild/msi/resources/LICENSE.rtf b/pkg/build/daggerbuild/msi/resources/LICENSE.rtf new file mode 100644 index 00000000000..f7c0f8ad10b --- /dev/null +++ b/pkg/build/daggerbuild/msi/resources/LICENSE.rtf @@ -0,0 +1,667 @@ +{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Courier New;}} +{\colortbl ;\red0\green0\blue255;} +{\*\generator Riched20 10.0.19041}\viewkind4\uc1 +\pard\f0\fs22\lang1033 GNU AFFERO GENERAL PUBLIC LICENSE\par + Version 3, 19 November 2007\par +\par + Copyright (C) 2007 Free Software Foundation, Inc. <{{\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt{https://fsf.org/\ul0\cf0}}}}\f0\fs22 >\par + Everyone is permitted to copy and distribute verbatim copies\par + of this license document, but changing it is not allowed.\par +\par + Preamble\par +\par + The GNU Affero General Public License is a free, copyleft license for\par +software and other kinds of works, specifically designed to ensure\par +cooperation with the community in the case of network server software.\par +\par + The licenses for most software and other practical works are designed\par +to take away your freedom to share and change the works. By contrast,\par +our General Public Licenses are intended to guarantee your freedom to\par +share and change all versions of a program--to make sure it remains free\par +software for all its users.\par +\par + When we speak of free software, we are referring to freedom, not\par +price. Our General Public Licenses are designed to make sure that you\par +have the freedom to distribute copies of free software (and charge for\par +them if you wish), that you receive source code or can get it if you\par +want it, that you can change the software or use pieces of it in new\par +free programs, and that you know you can do these things.\par +\par + Developers that use our General Public Licenses protect your rights\par +with two steps: (1) assert copyright on the software, and (2) offer\par +you this License which gives you legal permission to copy, distribute\par +and/or modify the software.\par +\par + A secondary benefit of defending all users' freedom is that\par +improvements made in alternate versions of the program, if they\par +receive widespread use, become available for other developers to\par +incorporate. Many developers of free software are heartened and\par +encouraged by the resulting cooperation. However, in the case of\par +software used on network servers, this result may fail to come about.\par +The GNU General Public License permits making a modified version and\par +letting the public access it on a server without ever releasing its\par +source code to the public.\par +\par + The GNU Affero General Public License is designed specifically to\par +ensure that, in such cases, the modified source code becomes available\par +to the community. It requires the operator of a network server to\par +provide the source code of the modified version running there to the\par +users of that server. Therefore, public use of a modified version, on\par +a publicly accessible server, gives the public access to the source\par +code of the modified version.\par +\par + An older license, called the Affero General Public License and\par +published by Affero, was designed to accomplish similar goals. This is\par +a different license, not a version of the Affero GPL, but Affero has\par +released a new version of the Affero GPL which permits relicensing under\par +this license.\par +\par + The precise terms and conditions for copying, distribution and\par +modification follow.\par +\par + TERMS AND CONDITIONS\par +\par + 0. Definitions.\par +\par + "This License" refers to version 3 of the GNU Affero General Public License.\par +\par + "Copyright" also means copyright-like laws that apply to other kinds of\par +works, such as semiconductor masks.\par +\par + "The Program" refers to any copyrightable work licensed under this\par +License. Each licensee is addressed as "you". "Licensees" and\par +"recipients" may be individuals or organizations.\par +\par + To "modify" a work means to copy from or adapt all or part of the work\par +in a fashion requiring copyright permission, other than the making of an\par +exact copy. The resulting work is called a "modified version" of the\par +earlier work or a work "based on" the earlier work.\par +\par + A "covered work" means either the unmodified Program or a work based\par +on the Program.\par +\par + To "propagate" a work means to do anything with it that, without\par +permission, would make you directly or secondarily liable for\par +infringement under applicable copyright law, except executing it on a\par +computer or modifying a private copy. Propagation includes copying,\par +distribution (with or without modification), making available to the\par +public, and in some countries other activities as well.\par +\par + To "convey" a work means any kind of propagation that enables other\par +parties to make or receive copies. Mere interaction with a user through\par +a computer network, with no transfer of a copy, is not conveying.\par +\par + An interactive user interface displays "Appropriate Legal Notices"\par +to the extent that it includes a convenient and prominently visible\par +feature that (1) displays an appropriate copyright notice, and (2)\par +tells the user that there is no warranty for the work (except to the\par +extent that warranties are provided), that licensees may convey the\par +work under this License, and how to view a copy of this License. If\par +the interface presents a list of user commands or options, such as a\par +menu, a prominent item in the list meets this criterion.\par +\par + 1. Source Code.\par +\par + The "source code" for a work means the preferred form of the work\par +for making modifications to it. "Object code" means any non-source\par +form of a work.\par +\par + A "Standard Interface" means an interface that either is an official\par +standard defined by a recognized standards body, or, in the case of\par +interfaces specified for a particular programming language, one that\par +is widely used among developers working in that language.\par +\par + The "System Libraries" of an executable work include anything, other\par +than the work as a whole, that (a) is included in the normal form of\par +packaging a Major Component, but which is not part of that Major\par +Component, and (b) serves only to enable use of the work with that\par +Major Component, or to implement a Standard Interface for which an\par +implementation is available to the public in source code form. A\par +"Major Component", in this context, means a major essential component\par +(kernel, window system, and so on) of the specific operating system\par +(if any) on which the executable work runs, or a compiler used to\par +produce the work, or an object code interpreter used to run it.\par +\par + The "Corresponding Source" for a work in object code form means all\par +the source code needed to generate, install, and (for an executable\par +work) run the object code and to modify the work, including scripts to\par +control those activities. However, it does not include the work's\par +System Libraries, or general-purpose tools or generally available free\par +programs which are used unmodified in performing those activities but\par +which are not part of the work. For example, Corresponding Source\par +includes interface definition files associated with source files for\par +the work, and the source code for shared libraries and dynamically\par +linked subprograms that the work is specifically designed to require,\par +such as by intimate data communication or control flow between those\par +subprograms and other parts of the work.\par +\par + The Corresponding Source need not include anything that users\par +can regenerate automatically from other parts of the Corresponding\par +Source.\par +\par + The Corresponding Source for a work in source code form is that\par +same work.\par +\par + 2. Basic Permissions.\par +\par + All rights granted under this License are granted for the term of\par +copyright on the Program, and are irrevocable provided the stated\par +conditions are met. This License explicitly affirms your unlimited\par +permission to run the unmodified Program. The output from running a\par +covered work is covered by this License only if the output, given its\par +content, constitutes a covered work. This License acknowledges your\par +rights of fair use or other equivalent, as provided by copyright law.\par +\par + You may make, run and propagate covered works that you do not\par +convey, without conditions so long as your license otherwise remains\par +in force. You may convey covered works to others for the sole purpose\par +of having them make modifications exclusively for you, or provide you\par +with facilities for running those works, provided that you comply with\par +the terms of this License in conveying all material for which you do\par +not control copyright. Those thus making or running the covered works\par +for you must do so exclusively on your behalf, under your direction\par +and control, on terms that prohibit them from making any copies of\par +your copyrighted material outside their relationship with you.\par +\par + Conveying under any other circumstances is permitted solely under\par +the conditions stated below. Sublicensing is not allowed; section 10\par +makes it unnecessary.\par +\par + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\par +\par + No covered work shall be deemed part of an effective technological\par +measure under any applicable law fulfilling obligations under article\par +11 of the WIPO copyright treaty adopted on 20 December 1996, or\par +similar laws prohibiting or restricting circumvention of such\par +measures.\par +\par + When you convey a covered work, you waive any legal power to forbid\par +circumvention of technological measures to the extent such circumvention\par +is effected by exercising rights under this License with respect to\par +the covered work, and you disclaim any intention to limit operation or\par +modification of the work as a means of enforcing, against the work's\par +users, your or third parties' legal rights to forbid circumvention of\par +technological measures.\par +\par + 4. Conveying Verbatim Copies.\par +\par + You may convey verbatim copies of the Program's source code as you\par +receive it, in any medium, provided that you conspicuously and\par +appropriately publish on each copy an appropriate copyright notice;\par +keep intact all notices stating that this License and any\par +non-permissive terms added in accord with section 7 apply to the code;\par +keep intact all notices of the absence of any warranty; and give all\par +recipients a copy of this License along with the Program.\par +\par + You may charge any price or no price for each copy that you convey,\par +and you may offer support or warranty protection for a fee.\par +\par + 5. Conveying Modified Source Versions.\par +\par + You may convey a work based on the Program, or the modifications to\par +produce it from the Program, in the form of source code under the\par +terms of section 4, provided that you also meet all of these conditions:\par +\par + a) The work must carry prominent notices stating that you modified\par + it, and giving a relevant date.\par +\par + b) The work must carry prominent notices stating that it is\par + released under this License and any conditions added under section\par + 7. This requirement modifies the requirement in section 4 to\par + "keep intact all notices".\par +\par + c) You must license the entire work, as a whole, under this\par + License to anyone who comes into possession of a copy. This\par + License will therefore apply, along with any applicable section 7\par + additional terms, to the whole of the work, and all its parts,\par + regardless of how they are packaged. This License gives no\par + permission to license the work in any other way, but it does not\par + invalidate such permission if you have separately received it.\par +\par + d) If the work has interactive user interfaces, each must display\par + Appropriate Legal Notices; however, if the Program has interactive\par + interfaces that do not display Appropriate Legal Notices, your\par + work need not make them do so.\par +\par + A compilation of a covered work with other separate and independent\par +works, which are not by their nature extensions of the covered work,\par +and which are not combined with it such as to form a larger program,\par +in or on a volume of a storage or distribution medium, is called an\par +"aggregate" if the compilation and its resulting copyright are not\par +used to limit the access or legal rights of the compilation's users\par +beyond what the individual works permit. Inclusion of a covered work\par +in an aggregate does not cause this License to apply to the other\par +parts of the aggregate.\par +\par + 6. Conveying Non-Source Forms.\par +\par + You may convey a covered work in object code form under the terms\par +of sections 4 and 5, provided that you also convey the\par +machine-readable Corresponding Source under the terms of this License,\par +in one of these ways:\par +\par + a) Convey the object code in, or embodied in, a physical product\par + (including a physical distribution medium), accompanied by the\par + Corresponding Source fixed on a durable physical medium\par + customarily used for software interchange.\par +\par + b) Convey the object code in, or embodied in, a physical product\par + (including a physical distribution medium), accompanied by a\par + written offer, valid for at least three years and valid for as\par + long as you offer spare parts or customer support for that product\par + model, to give anyone who possesses the object code either (1) a\par + copy of the Corresponding Source for all the software in the\par + product that is covered by this License, on a durable physical\par + medium customarily used for software interchange, for a price no\par + more than your reasonable cost of physically performing this\par + conveying of source, or (2) access to copy the\par + Corresponding Source from a network server at no charge.\par +\par + c) Convey individual copies of the object code with a copy of the\par + written offer to provide the Corresponding Source. This\par + alternative is allowed only occasionally and noncommercially, and\par + only if you received the object code with such an offer, in accord\par + with subsection 6b.\par +\par + d) Convey the object code by offering access from a designated\par + place (gratis or for a charge), and offer equivalent access to the\par + Corresponding Source in the same way through the same place at no\par + further charge. You need not require recipients to copy the\par + Corresponding Source along with the object code. If the place to\par + copy the object code is a network server, the Corresponding Source\par + may be on a different server (operated by you or a third party)\par + that supports equivalent copying facilities, provided you maintain\par + clear directions next to the object code saying where to find the\par + Corresponding Source. Regardless of what server hosts the\par + Corresponding Source, you remain obligated to ensure that it is\par + available for as long as needed to satisfy these requirements.\par +\par + e) Convey the object code using peer-to-peer transmission, provided\par + you inform other peers where the object code and Corresponding\par + Source of the work are being offered to the general public at no\par + charge under subsection 6d.\par +\par + A separable portion of the object code, whose source code is excluded\par +from the Corresponding Source as a System Library, need not be\par +included in conveying the object code work.\par +\par + A "User Product" is either (1) a "consumer product", which means any\par +tangible personal property which is normally used for personal, family,\par +or household purposes, or (2) anything designed or sold for incorporation\par +into a dwelling. In determining whether a product is a consumer product,\par +doubtful cases shall be resolved in favor of coverage. For a particular\par +product received by a particular user, "normally used" refers to a\par +typical or common use of that class of product, regardless of the status\par +of the particular user or of the way in which the particular user\par +actually uses, or expects or is expected to use, the product. A product\par +is a consumer product regardless of whether the product has substantial\par +commercial, industrial or non-consumer uses, unless such uses represent\par +the only significant mode of use of the product.\par +\par + "Installation Information" for a User Product means any methods,\par +procedures, authorization keys, or other information required to install\par +and execute modified versions of a covered work in that User Product from\par +a modified version of its Corresponding Source. The information must\par +suffice to ensure that the continued functioning of the modified object\par +code is in no case prevented or interfered with solely because\par +modification has been made.\par +\par + If you convey an object code work under this section in, or with, or\par +specifically for use in, a User Product, and the conveying occurs as\par +part of a transaction in which the right of possession and use of the\par +User Product is transferred to the recipient in perpetuity or for a\par +fixed term (regardless of how the transaction is characterized), the\par +Corresponding Source conveyed under this section must be accompanied\par +by the Installation Information. But this requirement does not apply\par +if neither you nor any third party retains the ability to install\par +modified object code on the User Product (for example, the work has\par +been installed in ROM).\par +\par + The requirement to provide Installation Information does not include a\par +requirement to continue to provide support service, warranty, or updates\par +for a work that has been modified or installed by the recipient, or for\par +the User Product in which it has been modified or installed. Access to a\par +network may be denied when the modification itself materially and\par +adversely affects the operation of the network or violates the rules and\par +protocols for communication across the network.\par +\par + Corresponding Source conveyed, and Installation Information provided,\par +in accord with this section must be in a format that is publicly\par +documented (and with an implementation available to the public in\par +source code form), and must require no special password or key for\par +unpacking, reading or copying.\par +\par + 7. Additional Terms.\par +\par + "Additional permissions" are terms that supplement the terms of this\par +License by making exceptions from one or more of its conditions.\par +Additional permissions that are applicable to the entire Program shall\par +be treated as though they were included in this License, to the extent\par +that they are valid under applicable law. If additional permissions\par +apply only to part of the Program, that part may be used separately\par +under those permissions, but the entire Program remains governed by\par +this License without regard to the additional permissions.\par +\par + When you convey a copy of a covered work, you may at your option\par +remove any additional permissions from that copy, or from any part of\par +it. (Additional permissions may be written to require their own\par +removal in certain cases when you modify the work.) You may place\par +additional permissions on material, added by you to a covered work,\par +for which you have or can give appropriate copyright permission.\par +\par + Notwithstanding any other provision of this License, for material you\par +add to a covered work, you may (if authorized by the copyright holders of\par +that material) supplement the terms of this License with terms:\par +\par + a) Disclaiming warranty or limiting liability differently from the\par + terms of sections 15 and 16 of this License; or\par +\par + b) Requiring preservation of specified reasonable legal notices or\par + author attributions in that material or in the Appropriate Legal\par + Notices displayed by works containing it; or\par +\par + c) Prohibiting misrepresentation of the origin of that material, or\par + requiring that modified versions of such material be marked in\par + reasonable ways as different from the original version; or\par +\par + d) Limiting the use for publicity purposes of names of licensors or\par + authors of the material; or\par +\par + e) Declining to grant rights under trademark law for use of some\par + trade names, trademarks, or service marks; or\par +\par + f) Requiring indemnification of licensors and authors of that\par + material by anyone who conveys the material (or modified versions of\par + it) with contractual assumptions of liability to the recipient, for\par + any liability that these contractual assumptions directly impose on\par + those licensors and authors.\par +\par + All other non-permissive additional terms are considered "further\par +restrictions" within the meaning of section 10. If the Program as you\par +received it, or any part of it, contains a notice stating that it is\par +governed by this License along with a term that is a further\par +restriction, you may remove that term. If a license document contains\par +a further restriction but permits relicensing or conveying under this\par +License, you may add to a covered work material governed by the terms\par +of that license document, provided that the further restriction does\par +not survive such relicensing or conveying.\par +\par + If you add terms to a covered work in accord with this section, you\par +must place, in the relevant source files, a statement of the\par +additional terms that apply to those files, or a notice indicating\par +where to find the applicable terms.\par +\par + Additional terms, permissive or non-permissive, may be stated in the\par +form of a separately written license, or stated as exceptions;\par +the above requirements apply either way.\par +\par + 8. Termination.\par +\par + You may not propagate or modify a covered work except as expressly\par +provided under this License. Any attempt otherwise to propagate or\par +modify it is void, and will automatically terminate your rights under\par +this License (including any patent licenses granted under the third\par +paragraph of section 11).\par +\par + However, if you cease all violation of this License, then your\par +license from a particular copyright holder is reinstated (a)\par +provisionally, unless and until the copyright holder explicitly and\par +finally terminates your license, and (b) permanently, if the copyright\par +holder fails to notify you of the violation by some reasonable means\par +prior to 60 days after the cessation.\par +\par + Moreover, your license from a particular copyright holder is\par +reinstated permanently if the copyright holder notifies you of the\par +violation by some reasonable means, this is the first time you have\par +received notice of violation of this License (for any work) from that\par +copyright holder, and you cure the violation prior to 30 days after\par +your receipt of the notice.\par +\par + Termination of your rights under this section does not terminate the\par +licenses of parties who have received copies or rights from you under\par +this License. If your rights have been terminated and not permanently\par +reinstated, you do not qualify to receive new licenses for the same\par +material under section 10.\par +\par + 9. Acceptance Not Required for Having Copies.\par +\par + You are not required to accept this License in order to receive or\par +run a copy of the Program. Ancillary propagation of a covered work\par +occurring solely as a consequence of using peer-to-peer transmission\par +to receive a copy likewise does not require acceptance. However,\par +nothing other than this License grants you permission to propagate or\par +modify any covered work. These actions infringe copyright if you do\par +not accept this License. Therefore, by modifying or propagating a\par +covered work, you indicate your acceptance of this License to do so.\par +\par + 10. Automatic Licensing of Downstream Recipients.\par +\par + Each time you convey a covered work, the recipient automatically\par +receives a license from the original licensors, to run, modify and\par +propagate that work, subject to this License. You are not responsible\par +for enforcing compliance by third parties with this License.\par +\par + An "entity transaction" is a transaction transferring control of an\par +organization, or substantially all assets of one, or subdividing an\par +organization, or merging organizations. If propagation of a covered\par +work results from an entity transaction, each party to that\par +transaction who receives a copy of the work also receives whatever\par +licenses to the work the party's predecessor in interest had or could\par +give under the previous paragraph, plus a right to possession of the\par +Corresponding Source of the work from the predecessor in interest, if\par +the predecessor has it or can get it with reasonable efforts.\par +\par + You may not impose any further restrictions on the exercise of the\par +rights granted or affirmed under this License. For example, you may\par +not impose a license fee, royalty, or other charge for exercise of\par +rights granted under this License, and you may not initiate litigation\par +(including a cross-claim or counterclaim in a lawsuit) alleging that\par +any patent claim is infringed by making, using, selling, offering for\par +sale, or importing the Program or any portion of it.\par +\par + 11. Patents.\par +\par + A "contributor" is a copyright holder who authorizes use under this\par +License of the Program or a work on which the Program is based. The\par +work thus licensed is called the contributor's "contributor version".\par +\par + A contributor's "essential patent claims" are all patent claims\par +owned or controlled by the contributor, whether already acquired or\par +hereafter acquired, that would be infringed by some manner, permitted\par +by this License, of making, using, or selling its contributor version,\par +but do not include claims that would be infringed only as a\par +consequence of further modification of the contributor version. For\par +purposes of this definition, "control" includes the right to grant\par +patent sublicenses in a manner consistent with the requirements of\par +this License.\par +\par + Each contributor grants you a non-exclusive, worldwide, royalty-free\par +patent license under the contributor's essential patent claims, to\par +make, use, sell, offer for sale, import and otherwise run, modify and\par +propagate the contents of its contributor version.\par +\par + In the following three paragraphs, a "patent license" is any express\par +agreement or commitment, however denominated, not to enforce a patent\par +(such as an express permission to practice a patent or covenant not to\par +sue for patent infringement). To "grant" such a patent license to a\par +party means to make such an agreement or commitment not to enforce a\par +patent against the party.\par +\par + If you convey a covered work, knowingly relying on a patent license,\par +and the Corresponding Source of the work is not available for anyone\par +to copy, free of charge and under the terms of this License, through a\par +publicly available network server or other readily accessible means,\par +then you must either (1) cause the Corresponding Source to be so\par +available, or (2) arrange to deprive yourself of the benefit of the\par +patent license for this particular work, or (3) arrange, in a manner\par +consistent with the requirements of this License, to extend the patent\par +license to downstream recipients. "Knowingly relying" means you have\par +actual knowledge that, but for the patent license, your conveying the\par +covered work in a country, or your recipient's use of the covered work\par +in a country, would infringe one or more identifiable patents in that\par +country that you have reason to believe are valid.\par +\par + If, pursuant to or in connection with a single transaction or\par +arrangement, you convey, or propagate by procuring conveyance of, a\par +covered work, and grant a patent license to some of the parties\par +receiving the covered work authorizing them to use, propagate, modify\par +or convey a specific copy of the covered work, then the patent license\par +you grant is automatically extended to all recipients of the covered\par +work and works based on it.\par +\par + A patent license is "discriminatory" if it does not include within\par +the scope of its coverage, prohibits the exercise of, or is\par +conditioned on the non-exercise of one or more of the rights that are\par +specifically granted under this License. You may not convey a covered\par +work if you are a party to an arrangement with a third party that is\par +in the business of distributing software, under which you make payment\par +to the third party based on the extent of your activity of conveying\par +the work, and under which the third party grants, to any of the\par +parties who would receive the covered work from you, a discriminatory\par +patent license (a) in connection with copies of the covered work\par +conveyed by you (or copies made from those copies), or (b) primarily\par +for and in connection with specific products or compilations that\par +contain the covered work, unless you entered into that arrangement,\par +or that patent license was granted, prior to 28 March 2007.\par +\par + Nothing in this License shall be construed as excluding or limiting\par +any implied license or other defenses to infringement that may\par +otherwise be available to you under applicable patent law.\par +\par + 12. No Surrender of Others' Freedom.\par +\par + If conditions are imposed on you (whether by court order, agreement or\par +otherwise) that contradict the conditions of this License, they do not\par +excuse you from the conditions of this License. If you cannot convey a\par +covered work so as to satisfy simultaneously your obligations under this\par +License and any other pertinent obligations, then as a consequence you may\par +not convey it at all. For example, if you agree to terms that obligate you\par +to collect a royalty for further conveying from those to whom you convey\par +the Program, the only way you could satisfy both those terms and this\par +License would be to refrain entirely from conveying the Program.\par +\par + 13. Remote Network Interaction; Use with the GNU General Public License.\par +\par + Notwithstanding any other provision of this License, if you modify the\par +Program, your modified version must prominently offer all users\par +interacting with it remotely through a computer network (if your version\par +supports such interaction) an opportunity to receive the Corresponding\par +Source of your version by providing access to the Corresponding Source\par +from a network server at no charge, through some standard or customary\par +means of facilitating copying of software. This Corresponding Source\par +shall include the Corresponding Source for any work covered by version 3\par +of the GNU General Public License that is incorporated pursuant to the\par +following paragraph.\par +\par + Notwithstanding any other provision of this License, you have\par +permission to link or combine any covered work with a work licensed\par +under version 3 of the GNU General Public License into a single\par +combined work, and to convey the resulting work. The terms of this\par +License will continue to apply to the part which is the covered work,\par +but the work with which it is combined will remain governed by version\par +3 of the GNU General Public License.\par +\par + 14. Revised Versions of this License.\par +\par + The Free Software Foundation may publish revised and/or new versions of\par +the GNU Affero General Public License from time to time. Such new versions\par +will be similar in spirit to the present version, but may differ in detail to\par +address new problems or concerns.\par +\par + Each version is given a distinguishing version number. If the\par +Program specifies that a certain numbered version of the GNU Affero General\par +Public License "or any later version" applies to it, you have the\par +option of following the terms and conditions either of that numbered\par +version or of any later version published by the Free Software\par +Foundation. If the Program does not specify a version number of the\par +GNU Affero General Public License, you may choose any version ever published\par +by the Free Software Foundation.\par +\par + If the Program specifies that a proxy can decide which future\par +versions of the GNU Affero General Public License can be used, that proxy's\par +public statement of acceptance of a version permanently authorizes you\par +to choose that version for the Program.\par +\par + Later license versions may give you additional or different\par +permissions. However, no additional obligations are imposed on any\par +author or copyright holder as a result of your choosing to follow a\par +later version.\par +\par + 15. Disclaimer of Warranty.\par +\par + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\par +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\par +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\par +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\par +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\par +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\par +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\par +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\par +\par + 16. Limitation of Liability.\par +\par + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\par +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\par +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\par +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\par +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\par +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\par +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\par +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\par +SUCH DAMAGES.\par +\par + 17. Interpretation of Sections 15 and 16.\par +\par + If the disclaimer of warranty and limitation of liability provided\par +above cannot be given local legal effect according to their terms,\par +reviewing courts shall apply local law that most closely approximates\par +an absolute waiver of all civil liability in connection with the\par +Program, unless a warranty or assumption of liability accompanies a\par +copy of the Program in return for a fee.\par +\par + END OF TERMS AND CONDITIONS\par +\par + How to Apply These Terms to Your New Programs\par +\par + If you develop a new program, and you want it to be of the greatest\par +possible use to the public, the best way to achieve this is to make it\par +free software which everyone can redistribute and change under these terms.\par +\par + To do so, attach the following notices to the program. It is safest\par +to attach them to the start of each source file to most effectively\par +state the exclusion of warranty; and each file should have at least\par +the "copyright" line and a pointer to where the full notice is found.\par +\par + \par + Copyright (C) \par +\par + This program is free software: you can redistribute it and/or modify\par + it under the terms of the GNU Affero General Public License as published by\par + the Free Software Foundation, either version 3 of the License, or\par + (at your option) any later version.\par +\par + This program is distributed in the hope that it will be useful,\par + but WITHOUT ANY WARRANTY; without even the implied warranty of\par + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\par + GNU Affero General Public License for more details.\par +\par + You should have received a copy of the GNU Affero General Public License\par + along with this program. If not, see <{{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{https://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs22 >.\par +\par +Also add information on how to contact you by electronic and paper mail.\par +\par + If your software can interact with users remotely through a computer\par +network, you should also make sure that it provides a way for users to\par +get its source. For example, if your program is a web application, its\par +interface could display a "Source" link that leads users to an archive\par +of the code. There are many ways you could offer source, and different\par +solutions will be better for different programs; see section 13 for the\par +specific requirements.\par +\par + You should also get your employer (if you work as a programmer) or school,\par +if any, to sign a "copyright disclaimer" for the program, if necessary.\par +For more information on this, and how to apply and follow the GNU AGPL, see\par +<{{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{https://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs22 >.\par +\par +} + \ No newline at end of file diff --git a/pkg/build/daggerbuild/msi/resources/grafana_dialog_background.bmp b/pkg/build/daggerbuild/msi/resources/grafana_dialog_background.bmp new file mode 100644 index 00000000000..1975e7a492e Binary files /dev/null and b/pkg/build/daggerbuild/msi/resources/grafana_dialog_background.bmp differ diff --git a/pkg/build/daggerbuild/msi/resources/grafana_dialog_background.png b/pkg/build/daggerbuild/msi/resources/grafana_dialog_background.png new file mode 100644 index 00000000000..ab262097128 Binary files /dev/null and b/pkg/build/daggerbuild/msi/resources/grafana_dialog_background.png differ diff --git a/pkg/build/daggerbuild/msi/resources/grafana_icon.ico b/pkg/build/daggerbuild/msi/resources/grafana_icon.ico new file mode 100644 index 00000000000..6f13cb3210a Binary files /dev/null and b/pkg/build/daggerbuild/msi/resources/grafana_icon.ico differ diff --git a/pkg/build/daggerbuild/msi/resources/grafana_top_banner.bmp b/pkg/build/daggerbuild/msi/resources/grafana_top_banner.bmp new file mode 100644 index 00000000000..b4faabb92de Binary files /dev/null and b/pkg/build/daggerbuild/msi/resources/grafana_top_banner.bmp differ diff --git a/pkg/build/daggerbuild/msi/resources/grafana_top_banner.png b/pkg/build/daggerbuild/msi/resources/grafana_top_banner.png new file mode 100644 index 00000000000..905d54414f2 Binary files /dev/null and b/pkg/build/daggerbuild/msi/resources/grafana_top_banner.png differ diff --git a/pkg/build/daggerbuild/msi/resources/grafana_top_banner_white.bmp b/pkg/build/daggerbuild/msi/resources/grafana_top_banner_white.bmp new file mode 100644 index 00000000000..c72380151d2 Binary files /dev/null and b/pkg/build/daggerbuild/msi/resources/grafana_top_banner_white.bmp differ diff --git a/pkg/build/daggerbuild/msi/wxs.go b/pkg/build/daggerbuild/msi/wxs.go new file mode 100644 index 00000000000..f283dfd6a48 --- /dev/null +++ b/pkg/build/daggerbuild/msi/wxs.go @@ -0,0 +1,241 @@ +package msi + +import ( + "bytes" + "fmt" + "regexp" + "strings" + "text/template" +) + +type wxsCfg struct { + GrafanaVersion string + UpgradeCode string + ProductName string + Title string + Manufacturer string + License string +} + +var semverRegex = regexp.MustCompile(`^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) + +// WxsVersion converts a grafana version string (no v) to a 4-digit MSI version. +func WxsVersion(ersion string) string { + match := semverRegex.FindStringSubmatch(ersion) + result := make(map[string]string) + for i, name := range semverRegex.SubexpNames() { + if i != 0 && name != "" { + result[name] = match[i] + } + } + var major, minor, patch string + if v, ok := result["major"]; ok { + major = v + } + if v, ok := result["minor"]; ok { + minor = v + } + if v, ok := result["patch"]; ok { + patch = v + } + + if v, ok := result["buildmetadata"]; ok && v != "" { + return fmt.Sprintf("%s.%s.%s.%s", result["major"], result["minor"], result["patch"], strings.TrimPrefix(v, "security-")) + } + if v, ok := result["prerelease"]; ok && v != "" { + v := strings.TrimPrefix(v, "beta") + v = strings.TrimPrefix(v, "pre") + return fmt.Sprintf("%s.%s.%s.%s", major, minor, patch, v) + } + return fmt.Sprintf("%s.%s.%s.0", major, minor, patch) +} + +type WXSFile struct { + Name string + Contents string +} + +func WXSFiles(version string, enterprise bool) ([]WXSFile, error) { + upgradeCode := "35c7d2a9-6e23-4645-b975-e8693a1cef10" + prodName := "GrafanaOSS" + title := "Grafana OSS" + license := "LICENSE.rtf" + + if enterprise { + upgradeCode = "d534ec50-476b-4edc-a25e-fe854c949f4f" + prodName = "GrafanaEnterprise" + title = "Grafana Enterprise" + license = "EE_LICENSE.rtf" + } + + ersion := strings.TrimPrefix(version, "v") + + cfg := wxsCfg{ + GrafanaVersion: WxsVersion(ersion), + UpgradeCode: upgradeCode, + ProductName: prodName, + Title: title, + Manufacturer: "Grafana Labs", + License: license, + } + + files := make([]WXSFile, len(wxsTemplates)) + for i, t := range wxsTemplates { + name := fmt.Sprintf("grafana-%s.wxs", t.Name()) + buf := bytes.NewBuffer(nil) + if err := t.Execute(buf, cfg); err != nil { + return nil, err + } + + files[i] = WXSFile{ + Name: name, + Contents: buf.String(), + } + } + + return files, nil +} + +var wxsTemplates = []*template.Template{ + template.Must(template.New("firewall").Parse(firewallTemplate)), + template.Must(template.New("service").Parse(svcTemplate)), + template.Must(template.New("product").Parse(prodTemplate)), +} + +const firewallTemplate = ` + + + + + + + + + + + +` + +const prodTemplate = ` + + + {{ $version := .GrafanaVersion }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +` + +const svcTemplate = ` + + + + + + + + + + + + + + + + + + + + + LOG_LEVEL=DEBUG + + + + + + + + + + + + + + + + + + + + + + +` diff --git a/pkg/build/daggerbuild/msi/wxs_test.go b/pkg/build/daggerbuild/msi/wxs_test.go new file mode 100644 index 00000000000..8b21f01a2a3 --- /dev/null +++ b/pkg/build/daggerbuild/msi/wxs_test.go @@ -0,0 +1,22 @@ +package msi_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/daggerbuild/msi" +) + +func TestVersion(t *testing.T) { + tests := map[string]string{ + "1.2.3+security-01": "1.2.3.01", + "1.2.3-beta1": "1.2.3.1", + "1.2.3": "1.2.3.0", + } + + for input, expect := range tests { + res := msi.WxsVersion(input) + if res != expect { + t.Fatalf("for '%s' got '%s', expected '%s'", input, res, expect) + } + } +} diff --git a/pkg/build/daggerbuild/packages/names.go b/pkg/build/daggerbuild/packages/names.go new file mode 100644 index 00000000000..d242e2ed609 --- /dev/null +++ b/pkg/build/daggerbuild/packages/names.go @@ -0,0 +1,45 @@ +package packages + +import ( + "fmt" + "strings" + + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" +) + +type Name string + +const ( + PackageGrafana Name = "grafana" + PackageEnterprise Name = "grafana-enterprise" + PackageEnterpriseBoring Name = "grafana-enterprise-boringcrypto" + PackagePro Name = "grafana-pro" + PackageNightly Name = "grafana-nightly" +) + +type NameOpts struct { + // Name is the name of the product in the package. 99% of the time, this will be "grafana" or "grafana-enterprise". + Name Name + Version string + BuildID string + Distro backend.Distribution + Extension string +} + +// FileName returns a file name that matches this format: {grafana|grafana-enterprise}_{version}_{os}_{arch}_{build_number}.tar.gz +func FileName(name Name, version, buildID string, distro backend.Distribution, extension string) (string, error) { + var ( + // This should return something like "linux", "arm" + os, arch = backend.OSAndArch(distro) + // If applicable this will be set to something like "7" (for arm7) + archv = backend.ArchVersion(distro) + ) + + if archv != "" { + arch = strings.Join([]string{arch, archv}, "-") + } + + p := []string{string(name), version, buildID, os, arch} + + return fmt.Sprintf("%s.%s", strings.Join(p, "_"), extension), nil +} diff --git a/pkg/build/daggerbuild/packages/names_test.go b/pkg/build/daggerbuild/packages/names_test.go new file mode 100644 index 00000000000..84e97e7011b --- /dev/null +++ b/pkg/build/daggerbuild/packages/names_test.go @@ -0,0 +1,71 @@ +package packages_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" +) + +func TestFileName(t *testing.T) { + t.Run("It should use the correct name if Enterprise is false", func(t *testing.T) { + distro := backend.Distribution("plan9/amd64") + opts := packages.NameOpts{ + Name: "grafana", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + Extension: "tar.gz", + } + + expected := "grafana_v1.0.1-test_333_plan9_amd64.tar.gz" + if name, _ := packages.FileName(opts.Name, opts.Version, opts.BuildID, opts.Distro, opts.Extension); name != expected { + t.Errorf("name '%s' does not match expected name '%s'", name, expected) + } + }) + t.Run("It should use the correct name if Enterprise is true", func(t *testing.T) { + distro := backend.Distribution("plan9/amd64") + opts := packages.NameOpts{ + Name: "grafana-enterprise", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + Extension: "tar.gz", + } + + expected := "grafana-enterprise_v1.0.1-test_333_plan9_amd64.tar.gz" + if name, _ := packages.FileName(opts.Name, opts.Version, opts.BuildID, opts.Distro, opts.Extension); name != expected { + t.Errorf("name '%s' does not match expected name '%s'", name, expected) + } + }) + t.Run("It should use include the arch version if one is supplied in the distro", func(t *testing.T) { + distro := backend.Distribution("plan9/arm/v6") + opts := packages.NameOpts{ + Name: "grafana-enterprise", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + Extension: "tar.gz", + } + + expected := "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz" + if name, _ := packages.FileName(opts.Name, opts.Version, opts.BuildID, opts.Distro, opts.Extension); name != expected { + t.Errorf("name '%s' does not match expected name '%s'", name, expected) + } + }) + t.Run("It should support grafana names with multiple hyphens", func(t *testing.T) { + distro := backend.Distribution("plan9/arm/v6") + opts := packages.NameOpts{ + Name: "grafana-enterprise-rpi", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + Extension: "tar.gz", + } + + expected := "grafana-enterprise-rpi_v1.0.1-test_333_plan9_arm-6.tar.gz" + if name, _ := packages.FileName(opts.Name, opts.Version, opts.BuildID, opts.Distro, opts.Extension); name != expected { + t.Errorf("name '%s' does not match expected name '%s'", name, expected) + } + }) +} diff --git a/pkg/build/daggerbuild/pipeline/argument.go b/pkg/build/daggerbuild/pipeline/argument.go new file mode 100644 index 00000000000..bb8836a63f9 --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/argument.go @@ -0,0 +1,227 @@ +package pipeline + +import ( + "context" + "errors" + "fmt" + "log/slog" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" + "github.com/urfave/cli/v2" +) + +var ( + ErrorFlagNotProvided = errors.New("flag not provided, ex: '--go-version=1.21.0'") +) + +type ArgumentType int + +const ( + ArgumentTypeString ArgumentType = iota + ArgumentTypeInt64 + ArgumentTypeDirectory + ArgumentTypeCacheVolume + ArgumentTypeFile + ArgumentTypeBool +) + +type ArgumentOpts struct { + Log *slog.Logger + CLIContext cliutil.CLIContext + Client *dagger.Client + State StateHandler + Platform dagger.Platform +} + +type ArgumentValueFunc func(ctx context.Context, opts *ArgumentOpts) (any, error) + +// An Argument is an input to a artifact command. +// It wraps the concept of a general CLI "Flag" to allow it to +// All arguments are required. +type Argument struct { + ArgumentType ArgumentType + Name string + Description string + + // ValueFunc defines the behavior for how this artifact is populated. + // Maybe this could be an interface instead. + ValueFunc ArgumentValueFunc + + // If Flags are set here, then it is safe to assume that these flags will be globally set and any other pipeline / artifact using this + // argument will be able to use these same flags. + // Example: `--grafana-dir`, `--grafana-ref`, etc. + Flags []cli.Flag + + // Some arguments require other arguments to be set in order to derive their value. + // For example, the "version" argument(s) require the GrafanaDir (if the --version flag) was not set. + Requires []Argument +} + +func (a Argument) Directory(ctx context.Context, opts *ArgumentOpts) (*dagger.Directory, error) { + if a.ValueFunc == nil { + return nil, fmt.Errorf("error: %w. Flag missing: %s (%s)", ErrorFlagNotProvided, a.Name, a.Description) + } + value, err := a.ValueFunc(ctx, opts) + if err != nil { + return nil, err + } + dir, ok := value.(*dagger.Directory) + if !ok { + return nil, errors.New("value returned by valuefunc is not a *dagger.Directory") + } + + return dir, nil +} + +func (a Argument) MustDirectory(ctx context.Context, opts *ArgumentOpts) *dagger.Directory { + v, err := a.Directory(ctx, opts) + if err != nil { + panic(err) + } + + return v +} + +func (a Argument) String(ctx context.Context, opts *ArgumentOpts) (string, error) { + if a.ValueFunc == nil { + return "", fmt.Errorf("error: %w. %s (%s)", ErrorFlagNotProvided, a.Name, a.Description) + } + + value, err := a.ValueFunc(ctx, opts) + if err != nil { + return "", err + } + v, ok := value.(string) + if !ok { + return "", errors.New("value returned by valuefunc is not a string") + } + + return v, nil +} + +func (a Argument) MustString(ctx context.Context, opts *ArgumentOpts) string { + v, err := a.String(ctx, opts) + if err != nil { + panic(err) + } + + return v +} + +func (a Argument) Int64(ctx context.Context, opts *ArgumentOpts) (int64, error) { + if a.ValueFunc == nil { + return 0, fmt.Errorf("error: %w. %s (%s)", ErrorFlagNotProvided, a.Name, a.Description) + } + value, err := a.ValueFunc(ctx, opts) + if err != nil { + return 0, err + } + v, ok := value.(int64) + if !ok { + return 0, errors.New("value returned by valuefunc is not an int64") + } + + return v, nil +} + +func (a Argument) MustInt64(ctx context.Context, opts *ArgumentOpts) int64 { + v, err := a.Int64(ctx, opts) + if err != nil { + panic(err) + } + + return v +} + +func (a Argument) Bool(ctx context.Context, opts *ArgumentOpts) (bool, error) { + if a.ValueFunc == nil { + return false, fmt.Errorf("error: %w. %s (%s)", ErrorFlagNotProvided, a.Name, a.Description) + } + value, err := a.ValueFunc(ctx, opts) + if err != nil { + return false, err + } + v, ok := value.(bool) + if !ok { + return false, errors.New("value returned by valuefunc is not a bool") + } + + return v, nil +} + +func (a Argument) MustBool(ctx context.Context, opts *ArgumentOpts) bool { + v, err := a.Bool(ctx, opts) + if err != nil { + panic(err) + } + + return v +} + +func (a Argument) File(ctx context.Context, opts *ArgumentOpts) (*dagger.File, error) { + if a.ValueFunc == nil { + return nil, fmt.Errorf("error: %w. %s (%s)", ErrorFlagNotProvided, a.Name, a.Description) + } + value, err := a.ValueFunc(ctx, opts) + if err != nil { + return nil, err + } + dir, ok := value.(*dagger.File) + if !ok { + return nil, errors.New("value returned by valuefunc is not a *dagger.File") + } + + return dir, nil +} + +func (a Argument) MustFile(ctx context.Context, opts *ArgumentOpts) *dagger.File { + v, err := a.File(ctx, opts) + if err != nil { + panic(err) + } + + return v +} + +func (a Argument) CacheVolume(ctx context.Context, opts *ArgumentOpts) (*dagger.CacheVolume, error) { + if a.ValueFunc == nil { + return nil, fmt.Errorf("error: %w. %s (%s)", ErrorFlagNotProvided, a.Name, a.Description) + } + value, err := a.ValueFunc(ctx, opts) + if err != nil { + return nil, err + } + dir, ok := value.(*dagger.CacheVolume) + if !ok { + return nil, errors.New("value returned by valuefunc is not a *dagger.File") + } + + return dir, nil +} + +func (a Argument) MustCacheVolume(ctx context.Context, opts *ArgumentOpts) *dagger.CacheVolume { + v, err := a.CacheVolume(ctx, opts) + if err != nil { + panic(err) + } + + return v +} + +func StringFlagValueFunc(f *cli.StringFlag) func(context.Context, *ArgumentOpts) (any, error) { + return func(ctx context.Context, opts *ArgumentOpts) (any, error) { + return opts.CLIContext.String(f.Name), nil + } +} + +func NewStringFlagArgument(flag *cli.StringFlag) Argument { + return Argument{ + Name: flag.Name, + Description: flag.Usage, + Flags: []cli.Flag{ + flag, + }, + ValueFunc: StringFlagValueFunc(flag), + } +} diff --git a/pkg/build/daggerbuild/pipeline/artifact.go b/pkg/build/daggerbuild/pipeline/artifact.go new file mode 100644 index 00000000000..de6c8676678 --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/artifact.go @@ -0,0 +1,89 @@ +package pipeline + +import ( + "context" + "errors" + "log/slog" + + "dagger.io/dagger" +) + +var ( + ErrorNotADirectory = errors.New("not a directory argument") + ErrorOptionNotSet = errors.New("expected option not set") + ErrorDependencyNotFound = errors.New("dependency not found") +) + +type ArtifactType int + +const ( + ArtifactTypeFile ArtifactType = iota + ArtifactTypeDirectory +) + +type ArtifactContainerOpts struct { + Log *slog.Logger + Client *dagger.Client + Platform dagger.Platform + State StateHandler + Store ArtifactStore +} + +type ArtifactPublishFileOpts struct{} +type ArtifactPublishDirOpts struct{} + +type ArtifactInitializer func(context.Context, *slog.Logger, string, StateHandler) (*Artifact, error) + +// An Artifact is a file or a directory that is created when using the `-a / --artifact` flag. +// Each artifact can depend on other artifacts, and can be affected by 'flags' from the artifact string that describes this artifact. +// For example, the flags in the artifact string, 'targz:linux/amd64:grafana' +type ArtifactHandler interface { + Dependencies(ctx context.Context) ([]*Artifact, error) + Builder(ctx context.Context, opts *ArtifactContainerOpts) (*dagger.Container, error) + BuildFile(ctx context.Context, builder *dagger.Container, opts *ArtifactContainerOpts) (*dagger.File, error) + BuildDir(ctx context.Context, builder *dagger.Container, opts *ArtifactContainerOpts) (*dagger.Directory, error) + + Publisher(ctx context.Context, opts *ArtifactContainerOpts) (*dagger.Container, error) + PublishFile(ctx context.Context, opts *ArtifactPublishFileOpts) error + PublishDir(ctx context.Context, opts *ArtifactPublishDirOpts) error + + // Filename should return a deterministic file or folder name that this build will produce. + // This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output + // also affect the filename to ensure that there are no collisions. + // For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a + // `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. + Filename(ctx context.Context) (string, error) + + VerifyFile(context.Context, *dagger.Client, *dagger.File) error + VerifyDirectory(context.Context, *dagger.Client, *dagger.Directory) error +} + +type Artifact struct { + // ArtifactString is the artifact string provided by the user. + // If the artifact is being initialized as a dependency where an artifact string is not provided, + // then the artifactstring should be set with the parent's artifact string. + // For example, the targz artifact depends on the binary artifact. If a user requests a targz using the artifactstring + // 'targz:linux/amd64:grafana', then its dependencies should also have that ArtifactString. + // This value is really only used for logging. + ArtifactString string + Handler ArtifactHandler + // Type is the type of the artifact which is used when deciding whether to use BuildFile or BuildDir when building the artifact + Type ArtifactType + // Flags are the available list of flags that can individually contribute to the outcome of the artifact. Unlike arguments, flags are + // specific to the argument. + // For example, users can request the same argument with different flags: + // * targz:linux/amd64:grafana + // * targz:linux/amd64:grafana-enterprise + // The flags returned by this function should simply define what flags are allowed for this argument. + // A single flag can manipulate multiple options. For example, the 'boring' option modifies both the GOEXPERIMENT environment variable and ensures that the + // package is built with grafana enterprise. + // The options that the flag affects is in the flag itself. The options that the flag manipulates should be available to the callers by using the "Option" function. + // These flags are only set here so that the CLI can communicate what flags are possible. + Flags []Flag +} + +// Apply applies the flag into the OptionsHandler. +// This is a good opportunity for an artifact to handle being given a Flag in a different way than just storing its options. +func (a *Artifact) Apply(f Flag, o OptionsHandler) error { + return o.Apply(f) +} diff --git a/pkg/build/daggerbuild/pipeline/artifact_logger.go b/pkg/build/daggerbuild/pipeline/artifact_logger.go new file mode 100644 index 00000000000..a5552246016 --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/artifact_logger.go @@ -0,0 +1,129 @@ +package pipeline + +import ( + "context" + "log/slog" + + "dagger.io/dagger" +) + +type ArtifactHandlerLogger struct { + Handler ArtifactHandler + log *slog.Logger +} + +func (a *ArtifactHandlerLogger) Dependencies(ctx context.Context) ([]*Artifact, error) { + a.log.InfoContext(ctx, "getting dependencies...") + deps, err := a.Handler.Dependencies(ctx) + if err != nil { + a.log.InfoContext(ctx, "error getting dependencies", "error", err) + return nil, err + } + a.log.InfoContext(ctx, "got dependencies", "count", len(deps)) + + return deps, nil +} + +func (a *ArtifactHandlerLogger) Builder(ctx context.Context, opts *ArtifactContainerOpts) (*dagger.Container, error) { + a.log.InfoContext(ctx, "getting builder...") + builder, err := a.Handler.Builder(ctx, opts) + if err != nil { + a.log.InfoContext(ctx, "error getting builder", "error", err) + return nil, err + } + a.log.InfoContext(ctx, "got builder") + + return builder, nil +} + +func (a *ArtifactHandlerLogger) BuildFile(ctx context.Context, builder *dagger.Container, opts *ArtifactContainerOpts) (*dagger.File, error) { + a.log.InfoContext(ctx, "building file...") + file, err := a.Handler.BuildFile(ctx, builder, opts) + if err != nil { + a.log.InfoContext(ctx, "error building file", "error", err) + return nil, err + } + a.log.InfoContext(ctx, "done building file") + + return file, nil +} + +func (a *ArtifactHandlerLogger) BuildDir(ctx context.Context, builder *dagger.Container, opts *ArtifactContainerOpts) (*dagger.Directory, error) { + a.log.InfoContext(ctx, "building directory...") + dir, err := a.Handler.BuildDir(ctx, builder, opts) + if err != nil { + a.log.InfoContext(ctx, "error building directory", "error", err) + return nil, err + } + a.log.InfoContext(ctx, "done building directory") + + return dir, nil +} + +func (a *ArtifactHandlerLogger) Publisher(ctx context.Context, opts *ArtifactContainerOpts) (*dagger.Container, error) { + panic("not implemented") +} + +func (a *ArtifactHandlerLogger) PublishFile(ctx context.Context, opts *ArtifactPublishFileOpts) error { + panic("not implemented") +} + +func (a *ArtifactHandlerLogger) PublishDir(ctx context.Context, opts *ArtifactPublishDirOpts) error { + panic("not implemented") +} + +// Filename should return a deterministic file or folder name that this build will produce. +// This filename is used as a map key for caching, so implementers need to ensure that arguments or flags that affect the output +// also affect the filename to ensure that there are no collisions. +// For example, the backend for `linux/amd64` and `linux/arm64` should not both produce a `bin` folder, they should produce a +// `bin/linux-amd64` folder and a `bin/linux-arm64` folder. Callers can mount this as `bin` or whatever if they want. +func (a *ArtifactHandlerLogger) Filename(ctx context.Context) (string, error) { + a.log.DebugContext(ctx, "Getting filename...") + f, err := a.Handler.Filename(ctx) + if err != nil { + a.log.DebugContext(ctx, "error getting filename", "error", err) + return "", err + } + a.log.DebugContext(ctx, "done getting filename") + + return f, nil +} + +func (a *ArtifactHandlerLogger) VerifyFile(ctx context.Context, client *dagger.Client, file *dagger.File) error { + a.log.InfoContext(ctx, "verifying file...") + if err := a.Handler.VerifyFile(ctx, client, file); err != nil { + a.log.InfoContext(ctx, "error verifying file", "error", err) + return err + } + a.log.InfoContext(ctx, "done verifying file") + + return nil +} + +func (a *ArtifactHandlerLogger) VerifyDirectory(ctx context.Context, client *dagger.Client, dir *dagger.Directory) error { + a.log.InfoContext(ctx, "verifying directory...") + if err := a.Handler.VerifyDirectory(ctx, client, dir); err != nil { + a.log.InfoContext(ctx, "error verifying file", "error", err) + return err + } + a.log.InfoContext(ctx, "done verifying directory") + + return nil +} + +func ArtifactWithLogging(ctx context.Context, log *slog.Logger, a *Artifact) (*Artifact, error) { + h := a.Handler + f, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + + logger := log.With("artifact", a.ArtifactString, "filename", f, "service", "ArtifactHandler") + + a.Handler = &ArtifactHandlerLogger{ + log: logger, + Handler: h, + } + + return a, nil +} diff --git a/pkg/build/daggerbuild/pipeline/artifact_store.go b/pkg/build/daggerbuild/pipeline/artifact_store.go new file mode 100644 index 00000000000..ac3fa1cb55b --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/artifact_store.go @@ -0,0 +1,135 @@ +package pipeline + +import ( + "context" + "errors" + "fmt" + "log/slog" + "path/filepath" + "sync" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +// The Storer stores the result of artifacts. +type ArtifactStore interface { + StoreFile(ctx context.Context, a *Artifact, file *dagger.File) error + File(ctx context.Context, a *Artifact) (*dagger.File, error) + + StoreDirectory(ctx context.Context, a *Artifact, dir *dagger.Directory) error + Directory(ctx context.Context, a *Artifact) (*dagger.Directory, error) + + Export(ctx context.Context, d *dagger.Client, a *Artifact, destination string, checksum bool) ([]string, error) + Exists(ctx context.Context, a *Artifact) (bool, error) +} + +type MapArtifactStore struct { + data *sync.Map +} + +func (m *MapArtifactStore) StoreFile(ctx context.Context, a *Artifact, file *dagger.File) error { + f, err := a.Handler.Filename(ctx) + if err != nil { + return err + } + + m.data.Store(f, file) + return nil +} + +func (m *MapArtifactStore) File(ctx context.Context, a *Artifact) (*dagger.File, error) { + f, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + + v, ok := m.data.Load(f) + if !ok { + return nil, errors.New("not found") + } + + return v.(*dagger.File), nil +} + +func (m *MapArtifactStore) StoreDirectory(ctx context.Context, a *Artifact, dir *dagger.Directory) error { + f, err := a.Handler.Filename(ctx) + if err != nil { + return err + } + + m.data.Store(f, dir) + return nil +} + +func (m *MapArtifactStore) Directory(ctx context.Context, a *Artifact) (*dagger.Directory, error) { + f, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + + v, ok := m.data.Load(f) + if !ok { + return nil, errors.New("not found") + } + + return v.(*dagger.Directory), nil +} + +func (m *MapArtifactStore) Export(ctx context.Context, d *dagger.Client, a *Artifact, dst string, checksum bool) ([]string, error) { + path, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + + path = filepath.Join(dst, path) + switch a.Type { + case ArtifactTypeFile: + f, err := m.File(ctx, a) + if err != nil { + return nil, err + } + + if _, err := f.Export(ctx, path); err != nil { + return nil, err + } + + if !checksum { + return []string{path}, nil + } + if _, err := containers.Sha256(d, f).Export(ctx, path+".sha256"); err != nil { + return nil, err + } + + return []string{path, path + ".sha256"}, nil + case ArtifactTypeDirectory: + f, err := m.Directory(ctx, a) + if err != nil { + return nil, err + } + + if _, err := f.Export(ctx, path); err != nil { + return nil, err + } + + return []string{path}, nil + } + + return nil, fmt.Errorf("unrecognized artifact type: %d", a.Type) +} + +func (m *MapArtifactStore) Exists(ctx context.Context, a *Artifact) (bool, error) { + path, err := a.Handler.Filename(ctx) + if err != nil { + return false, err + } + + _, ok := m.data.Load(path) + return ok, nil +} + +func NewArtifactStore(log *slog.Logger) ArtifactStore { + return StoreWithLogging(&MapArtifactStore{ + data: &sync.Map{}, + }, log) +} diff --git a/pkg/build/daggerbuild/pipeline/artifact_store_logger.go b/pkg/build/daggerbuild/pipeline/artifact_store_logger.go new file mode 100644 index 00000000000..b5205330cd1 --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/artifact_store_logger.go @@ -0,0 +1,124 @@ +package pipeline + +import ( + "context" + "log/slog" + + "dagger.io/dagger" +) + +type ArtifactStoreLogger struct { + Store ArtifactStore + Log *slog.Logger +} + +func (m *ArtifactStoreLogger) StoreFile(ctx context.Context, a *Artifact, file *dagger.File) error { + fn, err := a.Handler.Filename(ctx) + if err != nil { + return err + } + log := m.Log.With("artifact", a.ArtifactString, "path", fn) + + log.DebugContext(ctx, "storing artifact file...") + if err := m.Store.StoreFile(ctx, a, file); err != nil { + log.DebugContext(ctx, "error storing artifact file", "error", err) + return err + } + log.DebugContext(ctx, "done storing artifact file") + return nil +} + +func (m *ArtifactStoreLogger) File(ctx context.Context, a *Artifact) (*dagger.File, error) { + fn, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + log := m.Log.With("artifact", a.ArtifactString, "path", fn) + + log.DebugContext(ctx, "fetching artifact file...") + file, err := m.Store.File(ctx, a) + if err != nil { + log.DebugContext(ctx, "error fetching artifact file", "error", err) + return nil, err + } + + log.DebugContext(ctx, "done fetching artifact file") + return file, nil +} + +func (m *ArtifactStoreLogger) StoreDirectory(ctx context.Context, a *Artifact, dir *dagger.Directory) error { + fn, err := a.Handler.Filename(ctx) + if err != nil { + return err + } + log := m.Log.With("artifact", a.ArtifactString, "path", fn) + + log.DebugContext(ctx, "storing artifact directory...") + if err := m.Store.StoreDirectory(ctx, a, dir); err != nil { + log.DebugContext(ctx, "error storing artifact directory", "error", err) + return err + } + log.DebugContext(ctx, "done storing artifact directory") + return nil +} + +func (m *ArtifactStoreLogger) Directory(ctx context.Context, a *Artifact) (*dagger.Directory, error) { + fn, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + log := m.Log.With("artifact", a.ArtifactString, "path", fn) + + log.DebugContext(ctx, "fetching artifact directory...") + dir, err := m.Store.Directory(ctx, a) + if err != nil { + log.DebugContext(ctx, "error fetching artifact directory", "error", err) + return nil, err + } + + log.DebugContext(ctx, "done fetching artifact directory") + return dir, nil +} + +func (m *ArtifactStoreLogger) Export(ctx context.Context, d *dagger.Client, a *Artifact, dst string, checksum bool) ([]string, error) { + fn, err := a.Handler.Filename(ctx) + if err != nil { + return nil, err + } + log := m.Log.With("artifact", a.ArtifactString, "path", fn, "destination", dst, "checksum", checksum) + + log.DebugContext(ctx, "exporting artifact...") + path, err := m.Store.Export(ctx, d, a, dst, checksum) + if err != nil { + log.DebugContext(ctx, "error exporting artifact", "error", err) + return nil, err + } + + log.DebugContext(ctx, "done exporting artifact") + return path, nil +} + +func (m *ArtifactStoreLogger) Exists(ctx context.Context, a *Artifact) (bool, error) { + fn, err := a.Handler.Filename(ctx) + if err != nil { + return false, err + } + log := m.Log.With("artifact", a.ArtifactString, "path", fn) + + log.DebugContext(ctx, "checking existence of artifact...") + v, err := m.Store.Exists(ctx, a) + if err != nil { + log.DebugContext(ctx, "error checking existence of artifact", "error", err) + return false, err + } + + log.DebugContext(ctx, "done checking existence of artifact") + return v, nil +} + +func StoreWithLogging(s ArtifactStore, log *slog.Logger) *ArtifactStoreLogger { + return &ArtifactStoreLogger{ + Store: s, + Log: log.With("service", "ArtifactStore"), + } +} diff --git a/pkg/build/daggerbuild/pipeline/flag.go b/pkg/build/daggerbuild/pipeline/flag.go new file mode 100644 index 00000000000..af8b165104e --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/flag.go @@ -0,0 +1,105 @@ +package pipeline + +import ( + "errors" + "fmt" + "strings" +) + +type FlagOption string + +// A Flag is a single component of an artifact string. +// For example, in the artifact string `linux/amd64:targz:enterprise`, the flags are +// `linux/amd64`, `targz`, and `enterprise`. Artifacts define what flags are allowed to be set on them, and handle applying those flags +// in their constructors. +type Flag struct { + Name string + Options map[FlagOption]any +} + +// OptionsHandler is used for storing and setting options populated from artifact flags in a map. +type OptionsHandler struct { + Artifact string + Options map[FlagOption]any +} + +func NewOptionsHandler(artifact string) *OptionsHandler { + return &OptionsHandler{ + Artifact: artifact, + Options: map[FlagOption]any{}, + } +} + +var ( + ErrorDuplicateFlagOption = errors.New("another flag has already set this option") + ErrorFlagOptionNotFound = errors.New("no flag provided the requested option") +) + +func (o *OptionsHandler) Apply(flag Flag) error { + for k, v := range flag.Options { + if _, ok := o.Options[k]; ok { + return fmt.Errorf("flag: %s, option: %s, error: %w", flag.Name, k, ErrorDuplicateFlagOption) + } + o.Options[k] = v + } + return nil +} + +func (o *OptionsHandler) Get(option FlagOption) (any, error) { + val, ok := o.Options[option] + if !ok { + return "", fmt.Errorf("[%s] %s: %w", o.Artifact, option, ErrorFlagOptionNotFound) + } + + return val, nil +} + +func (o *OptionsHandler) String(option FlagOption) (string, error) { + v, err := o.Get(option) + if err != nil { + return "", err + } + + return v.(string), nil +} + +func (o *OptionsHandler) StringSlice(option FlagOption) ([]string, error) { + v, err := o.Get(option) + if err != nil { + return nil, err + } + + return v.([]string), nil +} + +func (o *OptionsHandler) Bool(option FlagOption) (bool, error) { + v, err := o.Get(option) + if err != nil { + if errors.Is(err, ErrorFlagOptionNotFound) { + return false, nil + } + + return false, err + } + + return v.(bool), nil +} + +func ParseFlags(artifact string, flags []Flag) (*OptionsHandler, error) { + h := NewOptionsHandler(artifact) + f := strings.Split(artifact, ":") + + for _, v := range f { + for _, flag := range flags { + if flag.Name != v { + continue + } + + if err := h.Apply(flag); err != nil { + return nil, err + } + } + } + + return h, nil +} diff --git a/pkg/build/daggerbuild/pipeline/state.go b/pkg/build/daggerbuild/pipeline/state.go new file mode 100644 index 00000000000..2e7d096169b --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/state.go @@ -0,0 +1,162 @@ +package pipeline + +import ( + "context" + "errors" + "fmt" + "log/slog" + "sync" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" +) + +var ( + ErrorUnexpectedType = errors.New("unexpected type in state") +) + +type StateHandler interface { + String(context.Context, Argument) (string, error) + Int64(context.Context, Argument) (int64, error) + Bool(context.Context, Argument) (bool, error) + File(context.Context, Argument) (*dagger.File, error) + Directory(context.Context, Argument) (*dagger.Directory, error) + CacheVolume(context.Context, Argument) (*dagger.CacheVolume, error) +} + +// State stores the overall state of the application. Externally, it is read-only. +// It starts every run completely empty. As arguments are needed by other arguments, their ValueFuncs are called +// when fetched from the state and then stored for future re-use. +type State struct { + Data sync.Map + Log *slog.Logger + + // These two fields are only here so that the state can call the ValueFunc of each argument if it's not already available in the state. + CLIContext cliutil.CLIContext + Client *dagger.Client + Platform dagger.Platform +} + +func (s *State) ArgumentOpts() *ArgumentOpts { + return &ArgumentOpts{ + Log: s.Log, + CLIContext: s.CLIContext, + Client: s.Client, + State: s, + Platform: s.Platform, + } +} + +func (s *State) String(ctx context.Context, arg Argument) (string, error) { + if v, ok := s.Data.Load(arg.Name); ok { + str, ok := v.(string) + if !ok { + return "", fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name) + } + + return str, nil + } + + str, err := arg.String(ctx, s.ArgumentOpts()) + if err != nil { + return "", err + } + + s.Data.Store(arg.Name, str) + return str, nil +} + +func (s *State) Int64(ctx context.Context, arg Argument) (int64, error) { + if v, ok := s.Data.Load(arg.Name); ok { + val, ok := v.(int64) + if !ok { + return 0, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name) + } + + return val, nil + } + + val, err := arg.Int64(ctx, s.ArgumentOpts()) + if err != nil { + return 0, err + } + + s.Data.Store(arg.Name, val) + return val, nil +} + +func (s *State) Bool(ctx context.Context, arg Argument) (bool, error) { + if v, ok := s.Data.Load(arg.Name); ok { + val, ok := v.(bool) + if !ok { + return false, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name) + } + + return val, nil + } + + val, err := arg.Bool(ctx, s.ArgumentOpts()) + if err != nil { + return false, err + } + + s.Data.Store(arg.Name, val) + return val, nil +} + +func (s *State) File(ctx context.Context, arg Argument) (*dagger.File, error) { + if v, ok := s.Data.Load(arg.Name); ok { + val, ok := v.(*dagger.File) + if !ok { + return nil, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name) + } + + return val, nil + } + + f, err := arg.File(ctx, s.ArgumentOpts()) + if err != nil { + return nil, err + } + + s.Data.Store(arg.Name, f) + return f, nil +} + +func (s *State) Directory(ctx context.Context, arg Argument) (*dagger.Directory, error) { + if v, ok := s.Data.Load(arg.Name); ok { + val, ok := v.(*dagger.Directory) + if !ok { + return nil, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name) + } + + return val, nil + } + + dir, err := arg.Directory(ctx, s.ArgumentOpts()) + if err != nil { + return nil, err + } + + s.Data.Store(arg.Name, dir) + return dir, nil +} + +func (s *State) CacheVolume(ctx context.Context, arg Argument) (*dagger.CacheVolume, error) { + if v, ok := s.Data.Load(arg.Name); ok { + val, ok := v.(*dagger.CacheVolume) + if !ok { + return nil, fmt.Errorf("%w: %s", ErrorUnexpectedType, arg.Name) + } + + return val, nil + } + + dir, err := arg.CacheVolume(ctx, s.ArgumentOpts()) + if err != nil { + return nil, err + } + + s.Data.Store(arg.Name, dir) + return dir, nil +} diff --git a/pkg/build/daggerbuild/pipeline/state_log.go b/pkg/build/daggerbuild/pipeline/state_log.go new file mode 100644 index 00000000000..4af48a6b074 --- /dev/null +++ b/pkg/build/daggerbuild/pipeline/state_log.go @@ -0,0 +1,81 @@ +package pipeline + +import ( + "context" + "log/slog" + + "dagger.io/dagger" +) + +type StateLogger struct { + Log *slog.Logger + Handler StateHandler +} + +func (s *StateLogger) String(ctx context.Context, arg Argument) (string, error) { + s.Log.Debug("Getting string from state", "arg", arg.Name) + val, err := s.Handler.String(ctx, arg) + if err != nil { + s.Log.Error("Error getting string from state", "arg", arg.Name, "error", err) + } + s.Log.Debug("Got string from state", "arg", arg.Name) + + return val, err +} +func (s *StateLogger) Int64(ctx context.Context, arg Argument) (int64, error) { + s.Log.Debug("Getting int64 from state", "arg", arg.Name) + val, err := s.Handler.Int64(ctx, arg) + if err != nil { + s.Log.Error("Error getting int64 from state", "arg", arg.Name, "error", err) + } + s.Log.Debug("Got int64 from state", "arg", arg.Name) + + return val, err +} +func (s *StateLogger) Bool(ctx context.Context, arg Argument) (bool, error) { + s.Log.Debug("Getting bool from state", "arg", arg.Name) + val, err := s.Handler.Bool(ctx, arg) + if err != nil { + s.Log.Error("Error getting bool from state", "arg", arg.Name, "error", err) + } + s.Log.Debug("Got bool from state", "arg", arg.Name) + + return val, err +} +func (s *StateLogger) File(ctx context.Context, arg Argument) (*dagger.File, error) { + s.Log.Debug("Getting file from state", "arg", arg.Name) + val, err := s.Handler.File(ctx, arg) + if err != nil { + s.Log.Error("Error getting file from state", "arg", arg.Name, "error", err) + } + s.Log.Debug("Got file from state", "arg", arg.Name) + + return val, err +} +func (s *StateLogger) Directory(ctx context.Context, arg Argument) (*dagger.Directory, error) { + s.Log.Debug("Getting directory from state", "arg", arg.Name) + val, err := s.Handler.Directory(ctx, arg) + if err != nil { + s.Log.Error("Error getting directory from state", "arg", arg.Name, "error", err) + } + s.Log.Debug("Got directory from state", "arg", arg.Name) + + return val, err +} +func (s *StateLogger) CacheVolume(ctx context.Context, arg Argument) (*dagger.CacheVolume, error) { + s.Log.Debug("Getting cache volume from state", "arg", arg.Name) + val, err := s.Handler.CacheVolume(ctx, arg) + if err != nil { + s.Log.Error("Error getting cache volume from state", "arg", arg.Name, "error", err) + } + s.Log.Debug("Got cache volume from state", "arg", arg.Name) + + return val, err +} + +func StateWithLogger(log *slog.Logger, s StateHandler) StateHandler { + return &StateLogger{ + Log: log, + Handler: s, + } +} diff --git a/pkg/build/daggerbuild/pipelines/docker_publish.go b/pkg/build/daggerbuild/pipelines/docker_publish.go new file mode 100644 index 00000000000..1c714026b53 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/docker_publish.go @@ -0,0 +1,141 @@ +package pipelines + +import ( + "context" + "fmt" + "log" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/docker" + "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" +) + +func ImageManifest(tag string) string { + log.Println(tag) + log.Println(tag) + log.Println(tag) + log.Println(tag) + manifest := strings.ReplaceAll(tag, "-image-tags", "") + lastDash := strings.LastIndex(manifest, "-") + return manifest[:lastDash] +} + +func LatestManifest(tag string) string { + suffix := "" + if strings.Contains(tag, "ubuntu") { + suffix = "-ubuntu" + } + + manifest := strings.ReplaceAll(tag, "-image-tags", "") + manifestImage := strings.Split(manifest, ":")[0] + return strings.Join([]string{manifestImage, fmt.Sprintf("latest%s", suffix)}, ":") +} + +// PublishDocker is a pipeline that uses a grafana.docker.tar.gz as input and publishes a Docker image to a container registry or repository. +// Grafana's Dockerfile should support supplying a tar.gz using a --build-arg. +func PublishDocker(ctx context.Context, d *dagger.Client, args PipelineArgs) error { + opts := args.DockerOpts + packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts) + if err != nil { + return err + } + + var ( + wg = &errgroup.Group{} + sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel) + ) + + manifestTags := make(map[string][]string) + for i, name := range args.PackageInputOpts.Packages { + // For each package we retrieve the tags grafana-image-tags and grafana-oss-image-tags, or grafana-enterprise-image-tags + format := opts.TagFormat + if strings.Contains(name, "ubuntu") { + format = opts.UbuntuTagFormat + } + + tarOpts := TarOptsFromFileName(name) + + tags, err := docker.Tags(opts.Org, opts.Registry, []string{opts.Repository}, format, tarOpts.NameOpts()) + if err != nil { + return err + } + log.Println(tags) + for _, tag := range tags { + // For each tag we publish an image and add the tag to the list of tags for a specific manifest + // Since each package has a maximum of 2 tags, this for loop will only run twice on a worst case scenario + manifest := ImageManifest(tag) + manifestTags[manifest] = append(manifestTags[manifest], tag) + + if opts.Latest { + manifest := LatestManifest(tag) + manifestTags[manifest] = append(manifestTags[manifest], tag) + } + + wg.Go(PublishPackageImageFunc(ctx, sm, d, packages[i], tag, opts)) + } + } + + if err := wg.Wait(); err != nil { + // Wait for all images to be published + return err + } + + for manifest, tags := range manifestTags { + // Publish each manifest + wg.Go(PublishDockerManifestFunc(ctx, sm, d, manifest, tags, opts)) + } + + return wg.Wait() +} + +func PublishPackageImageFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, pkg *dagger.File, tag string, opts *docker.DockerOpts) func() error { + return func() error { + log.Printf("[%s] Attempting to publish image", tag) + log.Printf("[%s] Acquiring semaphore", tag) + if err := sm.Acquire(ctx, 1); err != nil { + return fmt.Errorf("failed to acquire semaphore: %w", err) + } + defer sm.Release(1) + log.Printf("[%s] Acquired semaphore", tag) + + log.Printf("[%s] Publishing image", tag) + out, err := docker.PublishPackageImage(ctx, d, pkg, tag, opts.Username, opts.Password, opts.Registry) + if err != nil { + return fmt.Errorf("[%s] error: %w", tag, err) + } + log.Printf("[%s] Done publishing image", tag) + + if _, err := fmt.Fprintln(Stdout, out); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + + return nil + } +} + +func PublishDockerManifestFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, manifest string, tags []string, opts *docker.DockerOpts) func() error { + return func() error { + log.Printf("[%s] Attempting to publish manifest", manifest) + log.Printf("[%s] Acquiring semaphore", manifest) + if err := sm.Acquire(ctx, 1); err != nil { + return fmt.Errorf("failed to acquire semaphore: %w", err) + } + defer sm.Release(1) + log.Printf("[%s] Acquired semaphore", manifest) + + log.Printf("[%s] Publishing manifest", manifest) + out, err := docker.PublishManifest(ctx, d, manifest, tags, opts.Username, opts.Password, opts.Registry) + if err != nil { + return fmt.Errorf("[%s] error: %w", manifest, err) + } + log.Printf("[%s] Done publishing manifest", manifest) + + if _, err := fmt.Fprintln(Stdout, out); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + return nil + } +} diff --git a/pkg/build/daggerbuild/pipelines/docker_publish_test.go b/pkg/build/daggerbuild/pipelines/docker_publish_test.go new file mode 100644 index 00000000000..4bcfe540ad1 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/docker_publish_test.go @@ -0,0 +1,53 @@ +package pipelines_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" +) + +func TestImageManifest(t *testing.T) { + manifests := map[string]string{ + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana:1.2.3-test.1.2.3", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3", + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana:1.2.3-test.1.2.3", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3", + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana:1.2.3-test.1.2.3-ubuntu", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3-ubuntu", + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana:1.2.3-test.1.2.3-ubuntu", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-oss:1.2.3-test.1.2.3-ubuntu", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3-ubuntu", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-enterprise:1.2.3-test.1.2.3-ubuntu", + } + + for k, v := range manifests { + if n := pipelines.ImageManifest(k); n != v { + t.Errorf("Expected '%s' manifest to equal '%s' but got '%s'", k, v, n) + } + } +} + +func TestLatestManifest(t *testing.T) { + manifests := map[string]string{ + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana:latest", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-oss:latest", + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana:latest", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-oss:latest", + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana:latest-ubuntu", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-oss:latest-ubuntu", + "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana:latest-ubuntu", + "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-oss:latest-ubuntu", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-amd64": "docker.io/grafana/grafana-enterprise:latest", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-arm64": "docker.io/grafana/grafana-enterprise:latest", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-amd64": "docker.io/grafana/grafana-enterprise:latest-ubuntu", + "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-arm64": "docker.io/grafana/grafana-enterprise:latest-ubuntu", + } + + for k, v := range manifests { + if n := pipelines.LatestManifest(k); n != v { + t.Errorf("Expected '%s' manifest to equal '%s' but got '%s'", k, v, n) + } + } +} diff --git a/pkg/build/daggerbuild/pipelines/docker_test.go b/pkg/build/daggerbuild/pipelines/docker_test.go new file mode 100644 index 00000000000..4d6aea01b94 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/docker_test.go @@ -0,0 +1,246 @@ +package pipelines_test + +// +// func TestImageName(t *testing.T) { +// // Normally I don't advocate for abstracting tests using test cases +// // but I think in this case I would really like to get a clearer view into what docker image tags will be produced. +// // Be sure that if you add additional test cases to this that you don't use formatting or concatenation; it should be obvious when looking at the test +// // what the expected output should be. And that value should not change based on another value. +// type tc struct { +// Description string +// Tags []string +// BaseImage pipelines.BaseImage +// DockerOpts *containers.DockerOpts +// TarOpts pipelines.TarFileOpts +// } +// +// var ( +// version = "v1.2.3-test.1.2.3" +// ) +// +// cases := []tc{ +// { +// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. Alpine images have no suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageAlpine, +// Tags: []string{ +// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-amd64", +// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64", +// }, +// }, +// { +// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. ARM64 images have a -arm64 suffix. Alpine images have no suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/arm64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageAlpine, +// Tags: []string{ +// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-arm64", +// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-arm64", +// }, +// }, +// { +// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. Ubuntu images have a '-ubuntu' suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageUbuntu, +// Tags: []string{ +// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-amd64", +// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-amd64", +// }, +// }, +// { +// Description: "Grafana docker images are created for both the 'docker.io/grafana/grafana-image-tags' and 'docker.io/grafana/grafana-oss-image-tags' repositories. ARM64 images have an -arm64 suffix. Ubuntu images have a '-ubuntu' suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/arm64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageUbuntu, +// Tags: []string{ +// "docker.io/grafana/grafana-image-tags:1.2.3-test.1.2.3-ubuntu-arm64", +// "docker.io/grafana/grafana-oss-image-tags:1.2.3-test.1.2.3-ubuntu-arm64", +// }, +// }, +// { +// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. Alpine images have no suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "enterprise", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageAlpine, +// Tags: []string{ +// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-amd64", +// }, +// }, +// { +// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. ARM64 images have an -arm64 suffix. Alpine images have no suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "enterprise", +// Distro: "linux/arm64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageAlpine, +// Tags: []string{ +// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-arm64", +// }, +// }, +// { +// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. Ubuntu images have a '-ubuntu' suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "enterprise", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageUbuntu, +// Tags: []string{ +// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-amd64", +// }, +// }, +// { +// Description: "Enterprise docker images are created for only the docker.io/grafana/grafana-enterprise-image-tags repository. ARM64 images have an -arm64 suffix. Ubuntu images have a '-ubuntu' suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "enterprise", +// Distro: "linux/arm64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "grafana", +// Registry: "docker.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageUbuntu, +// Tags: []string{ +// "docker.io/grafana/grafana-enterprise-image-tags:1.2.3-test.1.2.3-ubuntu-arm64", +// }, +// }, +// { +// Description: "Grafana docker images are created for both the 'registry.io/org/grafana-image-tags' and 'registry.io/org/grafana-oss-image-tags' repositories. Alpine images have no suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "org", +// Registry: "registry.io", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageAlpine, +// Tags: []string{ +// "registry.io/org/grafana-image-tags:1.2.3-test.1.2.3-amd64", +// "registry.io/org/grafana-oss-image-tags:1.2.3-test.1.2.3-amd64", +// }, +// }, +// { +// Description: "Grafana docker images are created for only the 'registry.io/org/grafana-dev' repository. Alpine images have no suffix.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "org", +// Registry: "registry.io", +// Repository: "grafana-dev", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageAlpine, +// Tags: []string{ +// "registry.io/org/grafana-dev:1.2.3-test.1.2.3-amd64", +// }, +// }, +// { +// Description: "Grafana docker images are created for only the 'registry.io/org/grafana-dev' repository.", +// TarOpts: pipelines.TarFileOpts{ +// Edition: "", +// Distro: "linux/amd64", +// Version: version, +// }, +// DockerOpts: &containers.DockerOpts{ +// Org: "org", +// Registry: "registry.io", +// Repository: "grafana-dev", +// TagFormat: pipelines.DefaultTagFormat, +// UbuntuTagFormat: pipelines.DefaultUbuntuTagFormat, +// }, +// BaseImage: pipelines.BaseImageUbuntu, +// Tags: []string{ +// "registry.io/org/grafana-dev:1.2.3-test.1.2.3-ubuntu-amd64", +// }, +// }, +// } +// +// for n, test := range cases { +// t.Run(fmt.Sprintf("[%d / %d] %s", n+1, len(cases), test.Description), func(t *testing.T) { +// expect := sort.StringSlice(test.Tags) +// res, err := pipelines.GrafanaImageTags(test.BaseImage, test.DockerOpts, test.TarOpts) +// if err != nil { +// t.Fatal("Unexpected error:", err.Error()) +// } +// +// for i := range expect { +// e := expect[i] +// r := res[i] +// if e != r { +// t.Errorf("[%d / %d]\nExpected '%s'\nReceived '%s'", i+1, len(expect), e, r) +// } +// } +// }) +// } +// } diff --git a/pkg/build/daggerbuild/pipelines/gcom_publish.go b/pkg/build/daggerbuild/pipelines/gcom_publish.go new file mode 100644 index 00000000000..7fc28d39201 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/gcom_publish.go @@ -0,0 +1,154 @@ +package pipelines + +import ( + "context" + "fmt" + "log" + "path/filepath" + "strings" + "time" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/gcom" + "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" +) + +func VersionPayloadFromFileName(name string, opts *gcom.GCOMOpts) *gcom.GCOMVersionPayload { + var ( + tarOpts = TarOptsFromFileName(name) + splitVersion = strings.Split(tarOpts.Version, ".") + stable = true + nightly = false + beta = false + ) + + if opts.Beta { + stable = false + beta = true + } + if opts.Nightly { + stable = false + beta = false + nightly = true + } + + return &gcom.GCOMVersionPayload{ + Version: tarOpts.Version, + ReleaseDate: time.Now().Format(time.RFC3339Nano), + Stable: stable, + Beta: beta, + Nightly: nightly, + WhatsNewURL: fmt.Sprintf("https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v%s-%s/", splitVersion[0], splitVersion[1]), + ReleaseNotesURL: "https://grafana.com/docs/grafana/next/release-notes/", + } +} + +func PackagePayloadFromFile(ctx context.Context, d *dagger.Client, name string, file *dagger.File, opts *gcom.GCOMOpts) (*gcom.GCOMPackagePayload, error) { + tarOpts := TarOptsFromFileName(name) + ext := filepath.Ext(name) + os, _ := backend.OSAndArch(tarOpts.Distro) + arch := strings.ReplaceAll(backend.FullArch(tarOpts.Distro), "/", "") + + if os == "windows" { + os = "win" + } + + if ext == ".deb" { + os = "deb" + } + if ext == ".rpm" { + os = "rhel" + } + if ext == ".exe" { + os = "win-installer" + } + + sha256, err := containers.Sha256(d, file).Contents(ctx) + if err != nil { + return nil, err + } + + return &gcom.GCOMPackagePayload{ + OS: os, + URL: opts.DownloadURL.JoinPath(name).String(), + Sha256: sha256, + Arch: arch, + }, nil +} + +func PublishGCOM(ctx context.Context, d *dagger.Client, args PipelineArgs) error { + var ( + opts = args.GCOMOpts + wg = &errgroup.Group{} + sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel) + ) + + packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts) + if err != nil { + return err + } + + // Extract the package versions + versionPayloads := make(map[string]*gcom.GCOMVersionPayload) + for _, name := range args.PackageInputOpts.Packages { + tarOpts := TarOptsFromFileName(name) + if _, ok := versionPayloads[tarOpts.Version]; !ok { + log.Printf("[%s] Building version payload", tarOpts.Version) + versionPayloads[tarOpts.Version] = VersionPayloadFromFileName(name, opts) + } + } + + // Publish each version only once + for _, p := range versionPayloads { + log.Printf("[%s] Attempting to publish version", p.Version) + out, err := gcom.PublishGCOMVersion(ctx, d, p, opts) + if err != nil { + return err + } + log.Printf("[%s] Done publishing version", p.Version) + if _, err := fmt.Fprintln(Stdout, strings.ReplaceAll(out, "\n", "")); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + } + + // Publish the package(s) + for i, name := range args.PackageInputOpts.Packages { + wg.Go(PublishGCOMPackageFunc(ctx, sm, d, opts, name, packages[i])) + } + return wg.Wait() +} + +func PublishGCOMPackageFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, opts *gcom.GCOMOpts, path string, file *dagger.File) func() error { + return func() error { + name := filepath.Base(path) + tarOpts := TarOptsFromFileName(name) + log.Printf("[%s] Attempting to publish package", name) + log.Printf("[%s] Acquiring semaphore", name) + if err := sm.Acquire(ctx, 1); err != nil { + return fmt.Errorf("failed to acquire semaphore: %w", err) + } + defer sm.Release(1) + log.Printf("[%s] Acquired semaphore", name) + + log.Printf("[%s] Building package payload", name) + packagePayload, err := PackagePayloadFromFile(ctx, d, name, file, opts) + if err != nil { + return fmt.Errorf("[%s] error: %w", name, err) + } + + log.Printf("[%s] Publishing package", name) + out, err := gcom.PublishGCOMPackage(ctx, d, packagePayload, opts, tarOpts.Version) + if err != nil { + return fmt.Errorf("[%s] error: %w", name, err) + } + log.Printf("[%s] Done publishing package", name) + + if _, err := fmt.Fprintln(Stdout, strings.ReplaceAll(out, "\n", "")); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + return nil + } +} diff --git a/pkg/build/daggerbuild/pipelines/npm_publish.go b/pkg/build/daggerbuild/pipelines/npm_publish.go new file mode 100644 index 00000000000..aab5366818b --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/npm_publish.go @@ -0,0 +1,69 @@ +package pipelines + +import ( + "context" + "fmt" + "log" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/frontend" + "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" +) + +func PublishNPM(ctx context.Context, d *dagger.Client, args PipelineArgs) error { + var ( + wg = &errgroup.Group{} + sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel) + ) + + packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts) + if err != nil { + return err + } + + // Extract the package(s) + for i := range args.PackageInputOpts.Packages { + var ( + // name = ReplaceExt(v, "") + targz = packages[i] + ) + + artifacts := containers.ExtractedArchive(d, targz).Directory("npm-artifacts") + + entries, err := artifacts.Entries(ctx) + if err != nil { + return err + } + + for _, path := range entries { + wg.Go(PublishNPMFunc(ctx, sm, d, artifacts.File(path), path, args.NpmToken, args.NpmRegistry, args.NpmTags)) + } + } + return wg.Wait() +} + +func PublishNPMFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, pkg *dagger.File, path, token, registry string, tags []string) func() error { + return func() error { + log.Printf("[%s] Attempting to publish package", path) + log.Printf("[%s] Acquiring semaphore", path) + if err := sm.Acquire(ctx, 1); err != nil { + return fmt.Errorf("failed to acquire semaphore: %w", err) + } + defer sm.Release(1) + log.Printf("[%s] Acquired semaphore", path) + + log.Printf("[%s] Publishing package", path) + out, err := frontend.PublishNPM(ctx, d, pkg, token, registry, tags) + if err != nil { + return fmt.Errorf("[%s] error: %w", path, err) + } + log.Printf("[%s] Done publishing package", path) + + if _, err := fmt.Fprintln(Stdout, out); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + return nil + } +} diff --git a/pkg/build/daggerbuild/pipelines/package_names.go b/pkg/build/daggerbuild/pipelines/package_names.go new file mode 100644 index 00000000000..55b4898345b --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/package_names.go @@ -0,0 +1,87 @@ +package pipelines + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/packages" +) + +type TarFileOpts struct { + // Name is the name of the product in the package. 99% of the time, this will be "grafana" or "grafana-enterprise". + Name string + Version string + BuildID string + // Edition is the flavor text after "grafana-", like "enterprise". + Edition string + Distro backend.Distribution + Suffix string +} + +func (opts *TarFileOpts) NameOpts() packages.NameOpts { + return packages.NameOpts{ + // Name is the name of the product in the package. 99% of the time, this will be "grafana" or "grafana-enterprise". + Name: packages.Name(opts.Name), + Version: opts.Version, + BuildID: opts.BuildID, + Distro: opts.Distro, + } +} + +func WithoutExt(name string) string { + ext := filepath.Ext(name) + n := strings.TrimSuffix(name, ext) + + // Explicitly handle `.gz` which might will also probably have a `.tar` extension as well. + if ext == ".gz" { + n = strings.TrimSuffix(n, ".ubuntu.docker.tar") + n = strings.TrimSuffix(n, ".docker.tar") + n = strings.TrimSuffix(n, ".tar") + } + + return n +} + +func TarOptsFromFileName(filename string) TarFileOpts { + filename = filepath.Base(filename) + n := WithoutExt(filename) + components := strings.Split(n, "_") + if len(components) != 5 { + return TarFileOpts{} + } + + var ( + name = components[0] + version = components[1] + buildID = components[2] + os = components[3] + arch = components[4] + ) + if archv := strings.Split(arch, "-"); len(archv) == 2 { + // The reverse operation of removing the 'v' for 'arm' because the golang environment variable + // GOARM doesn't want it, but the docker --platform flag either doesn't care or does want it. + if archv[0] == "arm" { + archv[1] = "v" + archv[1] + } + + // arm-7 should become arm/v7 + arch = strings.Join([]string{archv[0], archv[1]}, "/") + } + edition := "" + suffix := "" + if n := strings.Split(name, "-"); len(n) != 1 { + edition = strings.Join(n[1:], "-") + suffix = fmt.Sprintf("-%s", n[1]) + } + + return TarFileOpts{ + Name: name, + Edition: edition, + Version: version, + BuildID: buildID, + Distro: backend.Distribution(strings.Join([]string{os, arch}, "/")), + Suffix: suffix, + } +} diff --git a/pkg/build/daggerbuild/pipelines/package_names_test.go b/pkg/build/daggerbuild/pipelines/package_names_test.go new file mode 100644 index 00000000000..d4f050178fa --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/package_names_test.go @@ -0,0 +1,98 @@ +package pipelines_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" +) + +func TestWithoutExt(t *testing.T) { + names := map[string]string{ + "grafana_v1.0.1-test_333_plan9_amd64.tar.gz": "grafana_v1.0.1-test_333_plan9_amd64", + "grafana-enterprise_v1.0.1-test_333_plan9_amd64.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_amd64", + "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6", + "grafana-enterprise_v1.0.1-test_333_plan9_amd64.deb": "grafana-enterprise_v1.0.1-test_333_plan9_amd64", + "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.deb": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6", + "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.docker.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6", + "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.ubuntu.docker.tar.gz": "grafana-enterprise_v1.0.1-test_333_plan9_arm-6", + } + + for k, v := range names { + if n := pipelines.WithoutExt(k); n != v { + t.Errorf("Expected '%s' without file name to equal '%s' but got '%s'", k, v, n) + } + } +} + +func TestOptsFromFile(t *testing.T) { + t.Run("It should get the correct tar file opts from a valid name", func(t *testing.T) { + name := "grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz" + distro := backend.Distribution("plan9/arm/v6") + expect := pipelines.TarFileOpts{ + Edition: "enterprise", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + } + got := pipelines.TarOptsFromFileName(name) + if got.Edition != expect.Edition { + t.Errorf("got.Edition != expect.Edition, expected '%s'", expect.Edition) + } + if got.Version != expect.Version { + t.Errorf("got.Version != expect.Version, expected '%s', got '%s'", expect.Version, got.Version) + } + if got.BuildID != expect.BuildID { + t.Errorf("got.BuildID != expect.BuildID, expected '%s', got '%s'", expect.BuildID, got.BuildID) + } + if got.Distro != expect.Distro { + t.Errorf("got.Distro != expect.Distro, expected '%s', got '%s'", expect.Distro, got.Distro) + } + }) + t.Run("It should consider only the basename", func(t *testing.T) { + name := "somewhere/grafana-enterprise_v1.0.1-test_333_plan9_arm-6.tar.gz" + distro := backend.Distribution("plan9/arm/v6") + expect := pipelines.TarFileOpts{ + Edition: "enterprise", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + } + got := pipelines.TarOptsFromFileName(name) + if got.Edition != expect.Edition { + t.Errorf("got.Edition != expect.Edition, expected '%s'", expect.Edition) + } + if got.Version != expect.Version { + t.Errorf("got.Version != expect.Version, expected '%s', got '%s'", expect.Version, got.Version) + } + if got.BuildID != expect.BuildID { + t.Errorf("got.BuildID != expect.BuildID, expected '%s', got '%s'", expect.BuildID, got.BuildID) + } + if got.Distro != expect.Distro { + t.Errorf("got.Distro != expect.Distro, expected '%s', got '%s'", expect.Distro, got.Distro) + } + }) + t.Run("It should support editions with multiple hyphens", func(t *testing.T) { + name := "somewhere/grafana-enterprise-rpi_v1.0.1-test_333_plan9_arm-6.tar.gz" + distro := backend.Distribution("plan9/arm/v6") + expect := pipelines.TarFileOpts{ + Edition: "enterprise-rpi", + Version: "v1.0.1-test", + BuildID: "333", + Distro: distro, + } + got := pipelines.TarOptsFromFileName(name) + if got.Edition != expect.Edition { + t.Errorf("got.Edition != expect.Edition, expected '%s', got '%s'", expect.Edition, got.Edition) + } + if got.Version != expect.Version { + t.Errorf("got.Version != expect.Version, expected '%s', got '%s'", expect.Version, got.Version) + } + if got.BuildID != expect.BuildID { + t.Errorf("got.BuildID != expect.BuildID, expected '%s', got '%s'", expect.BuildID, got.BuildID) + } + if got.Distro != expect.Distro { + t.Errorf("got.Distro != expect.Distro, expected '%s', got '%s'", expect.Distro, got.Distro) + } + }) +} diff --git a/pkg/build/daggerbuild/pipelines/package_publish.go b/pkg/build/daggerbuild/pipelines/package_publish.go new file mode 100644 index 00000000000..017500dd7f5 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/package_publish.go @@ -0,0 +1,34 @@ +package pipelines + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" +) + +// PublishPackage takes one or multiple grafana.tar.gz as input and publishes it to a set destination. +func PublishPackage(ctx context.Context, d *dagger.Client, args PipelineArgs) error { + packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts) + if err != nil { + return err + } + + c := d.Container().From("alpine") + for i, name := range args.PackageInputOpts.Packages { + c = c.WithFile("/dist/"+filepath.Base(name), packages[i]) + } + + dst, err := containers.PublishDirectory(ctx, d, c.Directory("dist"), args.GCPOpts, args.PublishOpts.Destination) + if err != nil { + return err + } + if _, err := fmt.Fprintln(os.Stdout, dst); err != nil { + return fmt.Errorf("error writing to stdout: %w", err) + } + + return nil +} diff --git a/pkg/build/daggerbuild/pipelines/package_test.go b/pkg/build/daggerbuild/pipelines/package_test.go new file mode 100644 index 00000000000..75ee9bcf220 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/package_test.go @@ -0,0 +1 @@ +package pipelines_test diff --git a/pkg/build/daggerbuild/pipelines/pipeline_args.go b/pkg/build/daggerbuild/pipelines/pipeline_args.go new file mode 100644 index 00000000000..00352368027 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/pipeline_args.go @@ -0,0 +1,147 @@ +// package pipelines has functions and types that orchestrate containers. +package pipelines + +import ( + "context" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/cliutil" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/docker" + "github.com/grafana/grafana/pkg/build/daggerbuild/gcom" + "github.com/grafana/grafana/pkg/build/daggerbuild/gpg" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +type PipelineFunc func(context.Context, *dagger.Client, *dagger.Directory, PipelineArgs) error +type PipelineFuncWithPackageInput func(context.Context, *dagger.Client, PipelineArgs) error + +func DockerOptsFromFlags(c cliutil.CLIContext) *docker.DockerOpts { + return &docker.DockerOpts{ + Registry: c.String("registry"), + AlpineBase: c.String("alpine-base"), + UbuntuBase: c.String("ubuntu-base"), + Username: c.String("username"), + Password: c.String("password"), + Org: c.String("org"), + Repository: c.String("repo"), + Latest: c.Bool("latest"), + TagFormat: c.String("tag-format"), + UbuntuTagFormat: c.String("ubuntu-tag-format"), + } +} + +type ConcurrencyOpts struct { + Parallel int64 +} + +func ConcurrencyOptsFromFlags(c cliutil.CLIContext) *ConcurrencyOpts { + return &ConcurrencyOpts{ + Parallel: c.Int64("parallel"), + } +} + +type PipelineArgs struct { + // These arguments are ones that are available at the global level. + Verbose bool + + // Platform, where applicable, specifies what platform (linux/arm64, for example) to run the dagger containers on. + // This should really only be used if you know what you're doing. misusing this flag can result in really slow builds. + // Some example scenarios where you might want to use this: + // * You're on linux/amd64 and you're building a docker image for linux/armv7 or linux/arm64 + // * You're on linux/arm64 and you're building a package for linux/arm64 + Platform dagger.Platform + + // Context is available for all sub-commands that define their own flags. + Context cliutil.CLIContext + + // GrafanaOpts will be populated if the GrafanaFlags are enabled on the current sub-command. + // GrafanaOpts *containers.GrafanaOpts + + // PackageOpts will be populated if the PackageFlags are enabled on the current sub-command. + // PackageOpts *containers.PackageOpts + + // PublishOpts will be populated if the PublishFlags flags are enabled on the current sub-command + // This is set for pipelines that publish artifacts. + PublishOpts *containers.PublishOpts + + // PackageInputOpts will be populated if the PackageInputFlags are enabled on current sub-command. + // This is set for pipelines that accept a package as input. + PackageInputOpts *containers.PackageInputOpts + GPGOpts *gpg.GPGOpts + DockerOpts *docker.DockerOpts + GCPOpts *containers.GCPOpts + ConcurrencyOpts *ConcurrencyOpts + + // ProImageOpts will be populated if ProImageFlags are enabled on the current sub-command. + ProImageOpts *containers.ProImageOpts + + // NPMOpts will be populated if NPMFlags are enabled on the current sub-command. + NpmToken string + NpmRegistry string + NpmTags []string + + // GCOMOpts will be populated if GCOMFlags are enabled on the current sub-command. + GCOMOpts *gcom.GCOMOpts +} + +// PipelineArgsFromContext populates a pipelines.PipelineArgs from a CLI context. +func PipelineArgsFromContext(ctx context.Context, c cliutil.CLIContext) (PipelineArgs, error) { + // Global flags + var ( + verbose = c.Bool("v") + platform = c.String("platform") + ) + // grafanaOpts, err := containers.GrafanaOptsFromFlags(ctx, c) + // if err != nil { + // return PipelineArgs{}, err + // } + gcomOpts, err := gcom.GCOMOptsFromFlags(c) + if err != nil { + return PipelineArgs{}, err + } + + return PipelineArgs{ + Context: c, + Verbose: verbose, + Platform: dagger.Platform(platform), + // GrafanaOpts: grafanaOpts, + GPGOpts: &gpg.GPGOpts{}, + // PackageOpts: containers.PackageOptsFromFlags(c), + PublishOpts: containers.PublishOptsFromFlags(c), + PackageInputOpts: containers.PackageInputOptsFromFlags(c), + DockerOpts: DockerOptsFromFlags(c), + GCPOpts: containers.GCPOptsFromFlags(c), + ConcurrencyOpts: ConcurrencyOptsFromFlags(c), + ProImageOpts: containers.ProImageOptsFromFlags(c), + GCOMOpts: gcomOpts, + NpmToken: c.String("token"), + NpmRegistry: c.String("registry"), + NpmTags: c.StringSlice("tag"), + }, nil +} + +// InjectPipelineArgsIntoSpan is used to copy some of the arguments passed to +// the pipeline into a top-level OpenTelemtry span. Fields that might contain +// secrets are left out. +func InjectPipelineArgsIntoSpan(span trace.Span, args PipelineArgs) { + attributes := make([]attribute.KeyValue, 0, 10) + attributes = append(attributes, attribute.String("platform", string(args.Platform))) + // if args.GrafanaOpts != nil { + // attributes = append(attributes, attribute.String("go-version", args.GrafanaOpts.GoVersion)) + // attributes = append(attributes, attribute.String("version", args.GrafanaOpts.Version)) + // attributes = append(attributes, attribute.String("grafana-dir", args.GrafanaOpts.GrafanaDir)) + // attributes = append(attributes, attribute.String("grafana-ref", args.GrafanaOpts.GrafanaRef)) + // attributes = append(attributes, attribute.String("enterprise-dir", args.GrafanaOpts.EnterpriseDir)) + // attributes = append(attributes, attribute.String("enterprise-ref", args.GrafanaOpts.EnterpriseRef)) + // } + // if args.PackageOpts != nil { + // distros := []string{} + // for _, distro := range args.PackageOpts.Distros { + // distros = append(distros, string(distro)) + // } + // attributes = append(attributes, attribute.StringSlice("package-distros", distros)) + // } + span.SetAttributes(attributes...) +} diff --git a/pkg/build/daggerbuild/pipelines/pipeline_args_test.go b/pkg/build/daggerbuild/pipelines/pipeline_args_test.go new file mode 100644 index 00000000000..661daa56dec --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/pipeline_args_test.go @@ -0,0 +1,157 @@ +package pipelines_test + +// type TestCLIContext struct { +// Data map[string]interface{} +// } +// +// func (t *TestCLIContext) Bool(key string) bool { +// if _, ok := t.Data[key]; !ok { +// return false +// } +// +// return t.Data[key].(bool) +// } +// +// func (t *TestCLIContext) String(key string) string { +// if _, ok := t.Data[key]; !ok { +// return "" +// } +// +// return t.Data[key].(string) +// } +// +// func (t *TestCLIContext) Set(key string, val string) error { +// t.Data[key] = val +// +// return nil +// } +// +// func (t *TestCLIContext) StringSlice(key string) []string { +// if _, ok := t.Data[key]; !ok { +// return nil +// } +// return t.Data[key].([]string) +// } +// +// func (t *TestCLIContext) Path(key string) string { +// return t.Data[key].(string) +// } +// +// func (t *TestCLIContext) Int64(key string) int64 { +// if _, ok := t.Data[key]; !ok { +// return 0 +// } +// +// return t.Data[key].(int64) +// } +// +// func TestPipelineArgsFromContext(t *testing.T) { +// enterpriseDir, err := os.MkdirTemp("", "grafana-enterprise-*") +// if err != nil { +// t.Fatal(err) +// } +// +// validData := map[string]interface{}{ +// "v": true, +// "version": "v1.0.0", +// "grafana": true, +// "grafana-dir": "/grafana", +// "grafana-ref": "asdf", +// "enterprise": true, +// "enterprise-dir": enterpriseDir, +// "enterprise-ref": "1234", +// "build-id": "build-1234", +// "github-token": "", +// "sign": false, +// } +// +// // t.Run("It should return a PipelineArgs object if there are no errors", func(t *testing.T) { +// // args, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{ +// // Data: validData, +// // }) +// // if err != nil { +// // t.Fatal(err) +// // } +// +// // if args.Verbose != true { +// // t.Error("args.Verbose should be true") +// // } +// // // opts := args.GrafanaOpts +// // // if opts.Version != "v1.0.0" { +// // // t.Error("args.Version should be v1.0.0") +// // // } +// +// // if opts.BuildGrafana != true { +// // t.Error("args.BuildGrafana should be true") +// // } +// +// // if opts.GrafanaDir != "/grafana" { +// // t.Error("args.GrafanaDir should be /grafana") +// // } +// +// // if opts.GrafanaRef != "asdf" { +// // t.Error("args.GrafanaRef should be asdf") +// // } +// +// // if opts.BuildEnterprise != true { +// // t.Error("args.Enterprise should be true") +// // } +// +// // if opts.EnterpriseDir != enterpriseDir { +// // t.Errorf("args.EnterpriseDir should be %s", enterpriseDir) +// // } +// +// // if opts.EnterpriseRef != "1234" { +// // t.Error("args.EnterpriseRef should be 1234") +// // } +// // }) +// +// // t.Run("If no build ID is provided, a random 12-character string should be given", func(t *testing.T) { +// // data := validData +// // data["build-id"] = "" +// // args, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{ +// // Data: data, +// // }) +// // if err != nil { +// // t.Fatal(err) +// // } +// // opts := args.GrafanaOpts +// // if opts.BuildID == "" { +// // t.Fatal("BuildID should not be empty") +// // } +// // if len(opts.BuildID) != 12 { +// // t.Fatal("BuildID should be a 12-character string") +// // } +// // }) +// +// // t.Run("If the --enterprise-ref is set to a non-default value, it should set the enterprise flag to true", func(t *testing.T) { +// // data := validData +// // data["enterprise"] = false +// // data["enterprise-ref"] = "ref-1234" +// +// // args, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{ +// // Data: data, +// // }) +// // if err != nil { +// // t.Fatal(err) +// // } +// // opts := args.GrafanaOpts +// // if opts.BuildEnterprise != true { +// // t.Fatal("args.BuildEnterprise should be true") +// // } +// // }) +// +// t.Run("If the --enterprise-ref is set to a non-default value, it should set the enterprise flag to true", func(t *testing.T) { +// data := validData +// data["enterprise"] = false +// data["enterprise-ref"] = "" +// data["enterprise-dir"] = filepath.Join(enterpriseDir, "does-not-exist") +// +// _, err := pipelines.PipelineArgsFromContext(context.Background(), &TestCLIContext{ +// Data: data, +// }) +// if err == nil { +// t.Fatal("error should not be empty") +// } +// }) +// } diff --git a/pkg/build/daggerbuild/pipelines/pro_image.go b/pkg/build/daggerbuild/pipelines/pro_image.go new file mode 100644 index 00000000000..45d886fbde9 --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/pro_image.go @@ -0,0 +1,85 @@ +package pipelines + +import ( + "context" + "fmt" + "log" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/git" +) + +func ProImage(ctx context.Context, dc *dagger.Client, args PipelineArgs) error { + if len(args.PackageInputOpts.Packages) > 1 { + return fmt.Errorf("only one package is allowed: packages=%+v", args.PackageInputOpts.Packages) + } + packages, err := containers.GetPackages(ctx, dc, args.PackageInputOpts, args.GCPOpts) + if err != nil { + return fmt.Errorf("getting packages: packages=%+v %w", args.PackageInputOpts.Packages, err) + } + + debianPackageFile := packages[0] + + log.Printf("Cloning hosted Grafana...") + hostedGrafanaRepo, err := git.CloneWithGitHubToken(dc, args.ProImageOpts.GitHubToken, "https://github.com/grafana/hosted-grafana.git", "main") + if err != nil { + return fmt.Errorf("cloning hosted-grafana repo: %w", err) + } + + socketPath := "/var/run/docker.sock" + socket := dc.Host().UnixSocket(socketPath) + + hostedGrafanaImage := fmt.Sprintf("%s/%s:%s", args.ProImageOpts.ContainerRegistry, args.ProImageOpts.Repo, args.ProImageOpts.ImageTag) + + log.Printf("Building hosted Grafana image: %s", hostedGrafanaImage) + container := dc.Container().From("google/cloud-sdk:433.0.0-alpine"). + WithExec([]string{ + "/bin/sh", "-c", + "gcloud auth configure-docker --quiet", + }). + WithUnixSocket(socketPath, socket). + WithDirectory("/src", hostedGrafanaRepo). + WithFile("/src/grafana.deb", debianPackageFile). + WithWorkdir("/src"). + WithExec([]string{ + "/bin/sh", "-c", + "docker build --platform=linux/amd64 . -f ./cmd/hgrun/Dockerfile -t hgrun:latest", + }). + WithExec([]string{ + "/bin/sh", "-c", + fmt.Sprintf("docker build --platform=linux/amd64 --build-arg=RELEASE_TYPE=%s --build-arg=GRAFANA_VERSION=%s --build-arg=HGRUN_IMAGE=hgrun:latest . -f ./docker/hosted-grafana-all/Dockerfile -t %s", + args.ProImageOpts.ReleaseType, + args.ProImageOpts.GrafanaVersion, + hostedGrafanaImage, + ), + }) + + if args.ProImageOpts.Push { + if args.ProImageOpts.ContainerRegistry == "" { + return fmt.Errorf("--registry= is required") + } + + authenticator := containers.GCSAuth(dc, &containers.GCPOpts{ + ServiceAccountKey: args.GCPOpts.ServiceAccountKey, + ServiceAccountKeyBase64: args.GCPOpts.ServiceAccountKeyBase64, + }) + + authenticatedContainer, err := authenticator.Authenticate(dc, container) + if err != nil { + return fmt.Errorf("authenticating container with gcs auth: %w", err) + } + + log.Printf("Pushing hosted Grafana image to registry...") + container = authenticatedContainer.WithExec([]string{ + "/bin/sh", "-c", + fmt.Sprintf("docker push %s", hostedGrafanaImage), + }) + } + + if _, err := containers.ExitError(ctx, container); err != nil { + return fmt.Errorf("container did not exit successfully: %w", err) + } + + return nil +} diff --git a/pkg/build/daggerbuild/pipelines/publish.go b/pkg/build/daggerbuild/pipelines/publish.go new file mode 100644 index 00000000000..d7ec8de3d1f --- /dev/null +++ b/pkg/build/daggerbuild/pipelines/publish.go @@ -0,0 +1,29 @@ +package pipelines + +import ( + "io" + "os" + "sync" +) + +type SyncWriter struct { + Writer io.Writer + + mutex *sync.Mutex +} + +func NewSyncWriter(w io.Writer) *SyncWriter { + return &SyncWriter{ + Writer: w, + mutex: &sync.Mutex{}, + } +} + +func (w *SyncWriter) Write(b []byte) (int, error) { + w.mutex.Lock() + defer w.mutex.Unlock() + + return w.Writer.Write(b) +} + +var Stdout = NewSyncWriter(os.Stdout) diff --git a/pkg/build/daggerbuild/ruleguard.rules.go b/pkg/build/daggerbuild/ruleguard.rules.go new file mode 100644 index 00000000000..470d68c3656 --- /dev/null +++ b/pkg/build/daggerbuild/ruleguard.rules.go @@ -0,0 +1,16 @@ +//go:build ruleguard + +package gorules + +import "github.com/quasilyte/go-ruleguard/dsl" + +//doc:summary *cli.Context instances should have the variable name `c` or `cliCtx` +func correctNameForCLIContext(m dsl.Matcher) { + m.Import("github.com/urfave/cli/v2") + m.Match( + `func $_($varname $vartype) error { $*_ }`, + `func ($_ $_) $_($varname $vartype) error { $*_ }`, + ). + Where(m["vartype"].Type.Is("*v2.Context") && (m["varname"].Text != "c" && m["varname"].Text != "cliCtx")). + Report("*cli.Context arguments should have the name c or cliCtx but was $varname") +} diff --git a/pkg/build/daggerbuild/scripts/drone_build_main.sh b/pkg/build/daggerbuild/scripts/drone_build_main.sh new file mode 100755 index 00000000000..233f6b9022a --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_main.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env sh + +local_dst="dist/${DRONE_BUILD_EVENT}" +set -e + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all + +dagger run --silent go run ./cmd \ + artifacts \ + -a targz:grafana:linux/amd64 \ + -a targz:grafana:linux/arm64 \ + -a targz:grafana:linux/arm/v6 \ + -a targz:grafana:linux/arm/v7 \ + -a targz:grafana:windows/amd64 \ + -a targz:grafana:darwin/amd64 \ + -a deb:grafana:linux/amd64 \ + -a deb:grafana:linux/arm64 \ + -a deb:grafana:linux/arm/v6 \ + -a deb:grafana:linux/arm/v7 \ + -a docker:grafana:linux/amd64 \ + -a docker:grafana:linux/arm64 \ + -a docker:grafana:linux/arm/v7 \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --checksum \ + --verify \ + --build-id=${DRONE_BUILD_NUMBER} \ + --grafana-dir=${GRAFANA_DIR} \ + --github-token=${GITHUB_TOKEN} \ + --go-version=${GO_VERSION} \ + --ubuntu-base=${UBUNTU_BASE} \ + --alpine-base=${ALPINE_BASE} \ + --destination=${local_dst} > assets.txt + +echo "Final list of artifacts:" +cat assets.txt + +# Move the tar.gz packages to their expected locations +cat assets.txt | IS_MAIN=true go run ./scripts/move_packages.go ./dist/main diff --git a/pkg/build/daggerbuild/scripts/drone_build_main_enterprise.sh b/pkg/build/daggerbuild/scripts/drone_build_main_enterprise.sh new file mode 100755 index 00000000000..b8e88f0c1bf --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_main_enterprise.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env sh +local_dst="dist/${DRONE_BUILD_EVENT}" +set -e + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all +dagger run --silent go run ./cmd \ + artifacts \ + -a targz:enterprise:linux/amd64 \ + -a targz:enterprise:linux/arm64 \ + -a targz:enterprise:linux/arm/v6 \ + -a targz:enterprise:linux/arm/v7 \ + -a deb:enterprise:linux/amd64 \ + -a deb:enterprise:linux/arm64 \ + -a deb:enterprise:linux/arm/v6 \ + -a deb:enterprise:linux/arm/v7 \ + -a docker:enterprise:linux/amd64 \ + -a docker:enterprise:linux/arm64 \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --checksum \ + --verify \ + --build-id=${DRONE_BUILD_NUMBER} \ + --grafana-ref=${SOURCE_COMMIT} \ + --grafana-repo="https://github.com/grafana/grafana.git" \ + --enterprise-ref=${DRONE_COMMIT} \ + --github-token=${GITHUB_TOKEN} \ + --go-version=${GO_VERSION} \ + --ubuntu-base=${UBUNTU_BASE} \ + --alpine-base=${ALPINE_BASE} \ + --patches-repo=${PATCHES_REPO} \ + --patches-path=${PATCHES_PATH} \ + --destination=${local_dst} > assets.txt + +cat assets.txt + +# Move the tar.gz packages to their expected locations +cat assets.txt | DESTINATION=gs://grafana-downloads IS_MAIN=true go run ./scripts/move_packages.go ./dist/main diff --git a/pkg/build/daggerbuild/scripts/drone_build_main_pro.sh b/pkg/build/daggerbuild/scripts/drone_build_main_pro.sh new file mode 100755 index 00000000000..26f25b234d3 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_main_pro.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env sh +local_dst="./dist/${DRONE_BUILD_EVENT}" +set -e + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all +# Build all of the grafana.tar.gz packages. +dagger run --silent go run ./cmd \ + artifacts \ + -a targz:pro:linux/amd64 \ + -a targz:pro:linux/arm64 \ + -a deb:pro:linux/amd64 \ + -a deb:pro:linux/arm64 \ + -a frontend:enterprise \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --checksum \ + --verify \ + --build-id=${DRONE_BUILD_NUMBER} \ + --grafana-ref=${SOURCE_COMMIT} \ + --grafana-repo="https://github.com/grafana/grafana.git" \ + --enterprise-ref=${DRONE_COMMIT} \ + --github-token=${GITHUB_TOKEN} \ + --go-version=${GO_VERSION} \ + --ubuntu-base=${UBUNTU_BASE} \ + --alpine-base=${ALPINE_BASE} \ + --patches-repo=${PATCHES_REPO} \ + --patches-path=${PATCHES_PATH} \ + --destination=${local_dst} > assets.txt + +echo "Final list of artifacts:" +# Move the tar.gz packages to their expected locations +cat assets.txt | grep -v "public" | DESTINATION=gs://grafana-downloads-enterprise2 IS_MAIN=true go run ./scripts/move_packages.go ./dist/main +cat assets.txt | grep "public" | DESTINATION=gs://grafana-static-assets IS_MAIN=true go run ./scripts/move_packages.go ./dist/cdn diff --git a/pkg/build/daggerbuild/scripts/drone_build_nightly_enterprise.sh b/pkg/build/daggerbuild/scripts/drone_build_nightly_enterprise.sh new file mode 100755 index 00000000000..1ef23dffb2d --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_nightly_enterprise.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -e +local_dst="${DRONE_WORKSPACE}/dist" + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all + + # -a targz:enterprise:linux/arm/v6 \ + # -a targz:enterprise:linux/arm/v7 \ + # -a deb:enterprise:linux/arm/v6:nightly \ + # -a deb:enterprise:linux/arm/v7:nightly \ + # -a docker:enterprise:linux/arm/v7 \ + # -a docker:enterprise:linux/arm/v7:ubuntu \ + +dagger run --silent go run ./cmd \ + artifacts \ + -a targz:enterprise:linux/amd64 \ + -a targz:enterprise:linux/arm64 \ + -a targz:enterprise:linux/arm/v7 \ + -a targz:enterprise:linux/arm/v6 \ + -a deb:enterprise:linux/amd64:nightly \ + -a deb:enterprise:linux/arm64:nightly \ + -a deb:enterprise:linux/arm/v6:nightly \ + -a deb:enterprise:linux/arm/v7:nightly \ + -a rpm:enterprise:linux/amd64:sign:nightly \ + -a rpm:enterprise:linux/arm64:sign:nightly \ + -a targz:enterprise:windows/amd64 \ + -a targz:enterprise:windows/arm64 \ + -a targz:enterprise:darwin/amd64 \ + -a targz:enterprise:darwin/arm64 \ + -a zip:enterprise:windows/amd64 \ + -a msi:enterprise:windows/amd64 \ + -a docker:enterprise:linux/amd64 \ + -a docker:enterprise:linux/arm64 \ + -a docker:enterprise:linux/arm/v7 \ + -a docker:enterprise:linux/amd64:ubuntu \ + -a docker:enterprise:linux/arm64:ubuntu \ + -a docker:enterprise:linux/arm/v7:ubuntu \ + --checksum \ + --verify \ + --build-id=${DRONE_BUILD_NUMBER} \ + --grafana-ref=main \ + --enterprise-ref=main \ + --grafana-repo=https://github.com/grafana/grafana.git \ + --github-token=${GITHUB_TOKEN} \ + --destination=${local_dst} \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --go-version=${GO_VERSION} \ + --ubuntu-base="${UBUNTU_BASE}" \ + --alpine-base="${ALPINE_BASE}" > assets.txt + +cat assets.txt diff --git a/pkg/build/daggerbuild/scripts/drone_build_nightly_grafana.sh b/pkg/build/daggerbuild/scripts/drone_build_nightly_grafana.sh new file mode 100755 index 00000000000..96cfcf12c15 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_nightly_grafana.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -e +local_dst="${DRONE_WORKSPACE}/dist" + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all + +dagger run --silent go run ./cmd \ + artifacts \ + -a targz:grafana:linux/amd64 \ + -a targz:grafana:linux/arm64 \ + -a targz:grafana:linux/arm/v7 \ + -a targz:grafana:linux/arm/v6 \ + -a deb:grafana:linux/amd64:nightly \ + -a deb:grafana:linux/arm64:nightly \ + -a deb:grafana:linux/arm/v6:nightly \ + -a deb:grafana:linux/arm/v7:nightly \ + -a rpm:grafana:linux/amd64:sign:nightly \ + -a rpm:grafana:linux/arm64:sign:nightly \ + -a targz:grafana:windows/amd64 \ + -a targz:grafana:windows/arm64 \ + -a targz:grafana:darwin/amd64 \ + -a targz:grafana:darwin/arm64 \ + -a zip:grafana:windows/amd64 \ + -a msi:grafana:windows/amd64 \ + -a docker:grafana:linux/amd64 \ + -a docker:grafana:linux/arm64 \ + -a docker:grafana:linux/arm/v7 \ + -a docker:grafana:linux/amd64:ubuntu \ + -a docker:grafana:linux/arm64:ubuntu \ + -a docker:grafana:linux/arm/v7:ubuntu \ + --checksum \ + --verify \ + --build-id=${DRONE_BUILD_NUMBER} \ + --grafana-dir=${GRAFANA_DIR} \ + --github-token=${GITHUB_TOKEN} \ + --destination=${local_dst} \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --go-version=${GO_VERSION} \ + --ubuntu-base="${UBUNTU_BASE}" \ + --alpine-base="${ALPINE_BASE}" > assets.txt + +cat assets.txt diff --git a/pkg/build/daggerbuild/scripts/drone_build_tag_all.sh b/pkg/build/daggerbuild/scripts/drone_build_tag_all.sh new file mode 100755 index 00000000000..09ffb6a6d7e --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_tag_all.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +dst="${DESTINATION}/${DRONE_BUILD_EVENT}" +local_dst="./dist/${DRONE_BUILD_EVENT}" +set -e + +dagger run go run ./cmd artifacts \ + -a frontend:enterprise \ + -a storybook \ + -a npm:grafana \ + -a targz:grafana:linux/amd64 \ + -a targz:grafana:linux/arm64 \ + -a targz:grafana:linux/riscv64 \ + -a targz:grafana:linux/arm/v6 \ + -a targz:grafana:linux/arm/v7 \ + -a targz:enterprise:linux/amd64 \ + -a targz:enterprise:linux/arm64 \ + -a targz:enterprise:linux/riscv64 \ + -a targz:enterprise:linux/arm/v6 \ + -a targz:enterprise:linux/arm/v7 \ + -a targz:boring:linux/amd64/dynamic \ + -a deb:grafana:linux/amd64 \ + -a deb:grafana:linux/arm64 \ + -a deb:grafana:linux/arm/v6 \ + -a deb:grafana:linux/arm/v7 \ + -a deb:enterprise:linux/amd64 \ + -a deb:enterprise:linux/arm64 \ + -a deb:enterprise:linux/arm/v6 \ + -a deb:enterprise:linux/arm/v7 \ + -a rpm:grafana:linux/amd64:sign \ + -a rpm:grafana:linux/arm64:sign \ + -a rpm:enterprise:linux/amd64 \ + -a rpm:enterprise:linux/arm64 \ + -a docker:grafana:linux/amd64 \ + -a docker:grafana:linux/arm64 \ + -a docker:grafana:linux/amd64:ubuntu \ + -a docker:grafana:linux/arm64:ubuntu \ + -a docker:enterprise:linux/amd64 \ + -a docker:enterprise:linux/arm64 \ + -a docker:enterprise:linux/amd64:ubuntu \ + -a docker:enterprise:linux/arm64:ubuntu \ + -a docker:boring:linux/amd64/dynamic \ + -a zip:grafana:windows/amd64 \ + -a zip:enterprise:windows/amd64 \ + -a zip:grafana:windows/arm64 \ + -a zip:enterprise:windows/arm64 \ + -a msi:grafana:windows/amd64 \ + -a msi:enterprise:windows/amd64 \ + --parallel=2 \ + --ubuntu-base="${UBUNTU_BASE}" \ + --alpine-base="${ALPINE_BASE}" \ + --go-version="${GO_VERSION}" \ + -build-id=103 \ + --checksum > out.txt + +# Move the tar.gz packages to their expected locations +cat assets.txt | go run ./scripts/move_packages.go ./dist/prerelease diff --git a/pkg/build/daggerbuild/scripts/drone_build_tag_enterprise.sh b/pkg/build/daggerbuild/scripts/drone_build_tag_enterprise.sh new file mode 100755 index 00000000000..98c24a6472e --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_tag_enterprise.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +local_dst="dist/${DRONE_BUILD_EVENT}" +set -e + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all + +# Build all of the grafana.tar.gz packages. +dagger run go run ./cmd \ + artifacts \ + -a targz:enterprise:linux/amd64 \ + -a targz:enterprise:linux/arm64 \ + -a targz:enterprise:linux/arm/v6 \ + -a targz:enterprise:linux/arm/v7 \ + -a deb:enterprise:linux/amd64 \ + -a deb:enterprise:linux/arm64 \ + -a deb:enterprise:linux/arm/v6 \ + -a deb:enterprise:linux/arm/v7 \ + -a rpm:enterprise:linux/amd64:sign \ + -a rpm:enterprise:linux/arm64:sign \ + -a targz:enterprise:windows/amd64 \ + -a targz:enterprise:windows/arm64 \ + -a targz:enterprise:darwin/amd64 \ + -a targz:enterprise:darwin/arm64 \ + -a targz:boring:linux/amd64/dynamic \ + -a zip:enterprise:windows/amd64 \ + -a msi:enterprise:windows/amd64 \ + -a docker:enterprise:linux/amd64 \ + -a docker:enterprise:linux/arm64 \ + -a docker:enterprise:linux/arm/v7 \ + -a docker:enterprise:linux/amd64:ubuntu \ + -a docker:enterprise:linux/arm64:ubuntu \ + -a docker:enterprise:linux/arm/v7:ubuntu \ + -a docker:boring:linux/amd64/dynamic \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --verify \ + --checksum \ + --parallel=5 \ + --build-id=${DRONE_BUILD_NUMBER} \ + --enterprise-ref=${DRONE_TAG} \ + --grafana-ref=${DRONE_TAG} \ + --grafana-repo=https://github.com/grafana/grafana-security-mirror.git \ + --github-token=${GITHUB_TOKEN} \ + --go-version=${GO_VERSION} \ + --ubuntu-base="${UBUNTU_BASE}" \ + --alpine-base="${ALPINE_BASE}" \ + --version=${DRONE_TAG} \ + --destination=${local_dst} > assets.txt + +# Move the tar.gz packages to their expected locations +cat assets.txt | go run ./scripts/move_packages.go ./dist/prerelease diff --git a/pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh b/pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh new file mode 100755 index 00000000000..3d91cbc18ba --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +dst="${DESTINATION}/${DRONE_BUILD_EVENT}" +local_dst="file://dist/${DRONE_BUILD_EVENT}" +set -e + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all + +dagger run --silent go run ./cmd \ + artifacts \ + -a npm:grafana \ + -a storybook \ + -a targz:grafana:linux/amd64 \ + -a targz:grafana:linux/arm64 \ + -a targz:grafana:linux/arm/v6 \ + -a targz:grafana:linux/arm/v7 \ + -a deb:grafana:linux/amd64 \ + -a deb:grafana:linux/arm64 \ + -a deb:grafana:linux/arm/v6 \ + -a deb:grafana:linux/arm/v7 \ + -a rpm:grafana:linux/amd64:sign \ + -a rpm:grafana:linux/arm64:sign \ + -a docker:grafana:linux/amd64 \ + -a docker:grafana:linux/arm64 \ + -a docker:grafana:linux/arm/v7 \ + -a docker:grafana:linux/amd64:ubuntu \ + -a docker:grafana:linux/arm64:ubuntu \ + -a docker:grafana:linux/arm/v7:ubuntu \ + -a targz:grafana:windows/amd64 \ + -a targz:grafana:windows/arm64 \ + -a targz:grafana:darwin/amd64 \ + -a targz:grafana:darwin/arm64 \ + -a zip:grafana:windows/amd64 \ + -a msi:grafana:windows/amd64 \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --checksum \ + --verify \ + --build-id=${DRONE_BUILD_NUMBER} \ + --grafana-dir=${GRAFANA_DIR} \ + --github-token=${GITHUB_TOKEN} \ + --go-version=${GO_VERSION} \ + --ubuntu-base="${UBUNTU_BASE}" \ + --alpine-base="${ALPINE_BASE}" \ + --version=${DRONE_TAG} \ + --destination=${local_dst} > assets.txt + +cat assets.txt | go run ./scripts/move_packages.go ./dist/prerelease diff --git a/pkg/build/daggerbuild/scripts/drone_build_tag_pro.sh b/pkg/build/daggerbuild/scripts/drone_build_tag_pro.sh new file mode 100755 index 00000000000..aa0a3625696 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_build_tag_pro.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +local_dst="dist/${DRONE_BUILD_EVENT}" +set -e + +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*' +# This command enables qemu emulators for building Docker images for arm64/armv6/armv7/etc on the host. +docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all + +# Build all of the grafana.tar.gz packages. +dagger run --silent go run ./cmd \ + artifacts \ + -a frontend:enterprise \ + -a targz:pro:linux/amd64 \ + -a targz:pro:linux/arm64 \ + -a targz:pro:linux/arm/v6 \ + -a targz:pro:linux/arm/v7 \ + -a deb:pro:linux/amd64 \ + -a deb:pro:linux/arm64 \ + -a targz:pro:darwin/amd64 \ + -a targz:pro:windows/amd64 \ + -a docker:pro:linux/amd64 \ + -a docker:pro:linux/arm64 \ + -a docker:pro:linux/arm/v7 \ + -a docker:pro:linux/amd64:ubuntu \ + -a docker:pro:linux/arm64:ubuntu \ + -a docker:pro:linux/arm/v7:ubuntu \ + --checksum \ + --parallel=2 \ + --yarn-cache=${YARN_CACHE_FOLDER} \ + --build-id=${DRONE_BUILD_NUMBER} \ + --enterprise-ref=${DRONE_TAG} \ + --grafana-ref=${DRONE_TAG} \ + --grafana-repo=https://github.com/grafana/grafana-security-mirror.git \ + --github-token=${GITHUB_TOKEN} \ + --version=${DRONE_TAG} \ + --go-version=${GO_VERSION} \ + --ubuntu-base="${UBUNTU_BASE}" \ + --alpine-base="${ALPINE_BASE}" \ + --destination=${local_dst} > assets.txt + +# Move the tar.gz packages to their expected locations +cat assets.txt | go run ./scripts/move_packages.go ./dist/prerelease diff --git a/pkg/build/daggerbuild/scripts/drone_publish_nightly_enterprise.sh b/pkg/build/daggerbuild/scripts/drone_publish_nightly_enterprise.sh new file mode 100755 index 00000000000..6ae88f85a84 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_publish_nightly_enterprise.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -e +local_dir="${DRONE_WORKSPACE}/dist" + +# Publish the docker images present in the bucket +dagger run --silent go run ./cmd docker publish \ + $(find $local_dir | grep docker.tar.gz | grep -v sha256 | awk '{print "--package=file://"$0}') \ + --username=${DOCKER_USERNAME} \ + --password=${DOCKER_PASSWORD} \ + --latest \ + --repo="grafana-enterprise-dev" + +# Publish packages to the downloads bucket +dagger run --silent go run ./cmd package publish \ + $(find $local_dir | grep -e .rpm -e .tar.gz -e .exe -e .zip -e .deb | awk '{print "--package=file://"$0}') \ + --gcp-service-account-key-base64=${GCP_KEY_BASE64} \ + --destination="${DOWNLOADS_DESTINATION}/enterprise/release" + +# Publish packages to grafana.com +dagger run --silent go run ./cmd gcom publish \ + $(find $local_dir | grep -e .rpm -e .tar.gz -e .exe -e .zip -e .deb | grep -v sha256 | grep -v docker | awk '{print "--package=file://"$0}') \ + --api-key=${GCOM_API_KEY} \ + --api-url="https://grafana.com/api/grafana-enterprise" \ + --download-url="https://dl.grafana.com/enterprise/release" \ + --nightly diff --git a/pkg/build/daggerbuild/scripts/drone_publish_nightly_grafana.sh b/pkg/build/daggerbuild/scripts/drone_publish_nightly_grafana.sh new file mode 100755 index 00000000000..3d468a06c25 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/drone_publish_nightly_grafana.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -e +# ver=$(cat ${GRAFANA_DIR}/package.json | jq -r .version | sed -E "s/$/-/" | sed -E "s/-.*/-${DRONE_BUILD_NUMBER}/") +local_dir="${DRONE_WORKSPACE}/dist" + +# Publish the docker images present in the bucket +dagger run --silent go run ./cmd docker publish \ + $(find $local_dir | grep docker.tar.gz | grep -v sha256 | awk '{print "--package=file://"$0}') \ + --username=${DOCKER_USERNAME} \ + --password=${DOCKER_PASSWORD} \ + --repo="grafana-dev" + +# Publish packages to the downloads bucket +dagger run --silent go run ./cmd package publish \ + $(find $local_dir | grep -e .rpm -e .tar.gz -e .exe -e .zip -e .deb | awk '{print "--package=file://"$0}') \ + --gcp-service-account-key-base64=${GCP_KEY_BASE64} \ + --destination="${DOWNLOADS_DESTINATION}/oss/release" + +# Publish only the linux/amd64 edition storybook into the storybook bucket +# dagger run --silent go run ./cmd storybook \ +# $(find $local_dir | grep tar.gz | grep linux | grep amd64 | grep -v sha256 | grep -v docker | awk '{print "--package=file://"$0}') \ +# --gcp-service-account-key-base64=${GCP_KEY_BASE64} \ +# --destination="${STORYBOOK_DESTINATION}/${ver}" + +# # Publish only the linux/amd64 edition static assets into the static assets bucket +# dagger run --silent go run ./cmd cdn \ +# $(find $local_dir | grep tar.gz | grep linux | grep amd64 | grep -v sha256 | grep -v docker | awk '{print "--package=file://"$0}') \ +# --gcp-service-account-key-base64=${GCP_KEY_BASE64} \ +# --destination="${CDN_DESTINATION}/${ver}/public" + +# Publish only the linux/amd64 edition npm packages to npm +dagger run --silent go run ./cmd npm publish \ + $(find $local_dir | grep tar.gz | grep linux | grep amd64 | grep -v sha256 | grep -v docker | awk '{print "--package=file://"$0}') \ + --token=${NPM_TOKEN} \ + --tag="nightly" + +# Publish packages to grafana.com +dagger run --silent go run ./cmd gcom publish \ + $(find $local_dir | grep -e .rpm -e .tar.gz -e .exe -e .zip -e .deb | grep -v sha256 | grep -v docker | awk '{print "--package=file://"$0}') \ + --api-key=${GCOM_API_KEY} \ + --api-url="https://grafana.com/api/grafana" \ + --download-url="https://dl.grafana.com/oss/release" \ + --nightly \ No newline at end of file diff --git a/pkg/build/daggerbuild/scripts/move_packages.go b/pkg/build/daggerbuild/scripts/move_packages.go new file mode 100644 index 00000000000..1d90852f459 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages.go @@ -0,0 +1,495 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "dagger.io/dagger" + "github.com/grafana/grafana/pkg/build/daggerbuild/backend" + "github.com/grafana/grafana/pkg/build/daggerbuild/containers" + "github.com/grafana/grafana/pkg/build/daggerbuild/pipelines" +) + +const ( + proName = "enterprise2" + // 1: The version (with a v prefix) + // 2: The "edition". Options: 'oss', 'pro', 'enterprise'. + // 3: The full name. 'grafana', 'grafana-enterprise', 'grafana-pro + // 4: The 'ersion', or 'version' without the 'v'. + // 5: The OS: 'windows', 'linux', 'darwin' + // 6: The architecture: 'amd64', 'armv6', 'armv7', 'arm64'. + // 7: -musl, sometimes. + // 8: '.sha256', sometimes. + tarGzFormat = "artifacts/downloads%[9]s/%[1]s/%[2]s/release/%[3]s-%[4]s.%[5]s-%[6]s%[7]s.tar.gz%[8]s" + debFormat = "artifacts/downloads%[9]s/%[1]s/%[2]s/release/%[3]s_%[4]s_%[6]s.deb%[8]s" + rpmFormat = "artifacts/downloads%[9]s/%[1]s/%[2]s/release/%[3]s-%[4]s-1.%[6]s.rpm%[8]s" + exeFormat = "artifacts/downloads%[9]s/%[1]s/%[2]s/release/%[3]s_%[4]s_%[6]s.exe%[8]s" + msiFormat = "artifacts/downloads%[9]s/%[1]s/%[2]s/release/%[3]s_%[4]s_%[6]s.msi%[8]s" + + tarGzMainFormat = "%[2]s/main/%[3]s-%[4]s.%[5]s-%[6]s%[7]s.tar.gz%[8]s" + debMainFormat = "%[2]s/main/%[3]s_%[4]s_%[6]s.deb%[8]s" + + // 1: ersion + // 2. name (grafana-oss | grafana-enterprise) + // 3: '-ubuntu', if set + // 4: arch + // 5: '.sha256', if set + dockerFormat = "artifacts/docker/%[1]s/%[2]s-%[1]s%[3]s-%[4]s.img%[5]s" + + // 1: ersion + // 2. name (grafana-oss | grafana-enterprise) + cdnFormat = "artifacts/static-assets/%[2]s/%[1]s/public" + cdnMainFormat = "grafana/%s/public" + + // 1: ersion + storybookFormat = "artifacts/storybook/v%[1]s" + + // 1: version + // 2: package name (@grafana-ui-10.0.0.tgz) + npmFormat = "artifacts/npm/v%[1]s/npm-artifacts" + + sha256Ext = ".sha256" + grafana = "grafana" +) + +// One artifact and be copied to multiple different locations (like armv7 tar.gz packages should be copied to tar.gz and -musl.tar.gz) +type HandlerFunc func(name string) []string + +var Handlers = map[string]HandlerFunc{ + ".tar.gz": TarGZHandler, + ".deb": DebHandler, + ".rpm": RPMHandler, + ".docker.tar.gz": DockerHandler, + ".exe": EXEHandler, + ".msi": MSIHandler, + ".zip": ZipHandler, +} + +func IsMain() bool { + return os.Getenv("IS_MAIN") != "" +} + +func NPMHandler(name string) []string { + var ( + version = strings.TrimPrefix(os.Getenv("DRONE_TAG"), "v") + ) + + return []string{fmt.Sprintf(npmFormat, version)} +} + +func ZipHandler(name string) []string { + files := EXEHandler(strings.ReplaceAll(name, "zip", "exe")) + + for i, v := range files { + files[i] = strings.ReplaceAll(v, "exe", "zip") + } + + return files +} + +func MSIHandler(name string) []string { + files := EXEHandler(strings.ReplaceAll(name, "msi", "exe")) + + for i, v := range files { + files[i] = strings.ReplaceAll(v, "exe", "msi") + } + + return files +} + +func RPMHandler(name string) []string { + ext := filepath.Ext(name) + + // If we're copying a sha256 file and not a tar.gz then we want to add .sha256 to the template + // or just give it emptystring if it's not the sha256 file + sha256 := "" + if ext == sha256Ext { + sha256 = sha256Ext + } + + n := filepath.Base(name) // Surprisingly still works even with 'gs://' urls + opts := pipelines.TarOptsFromFileName(strings.ReplaceAll(strings.ReplaceAll(n, sha256Ext, ""), "rpm", "tar.gz")) + + // In grafana-build we just use "" to refer to "oss" + edition := "oss" + fullName := grafana + if opts.Edition != "" { + edition = opts.Edition + fullName += "-" + opts.Edition + } + + goos, arch := backend.OSAndArch(opts.Distro) + arm := backend.ArchVersion(opts.Distro) + if arch == "arm" { + if arm == "7" { + arch = "armhfp" + } + } + + if arch == "arm64" { + arch = "aarch64" + } + + if arch == "amd64" { + arch = "x86_64" + } + + enterprise2 := "" + version := opts.Version + ersion := strings.Replace(strings.TrimPrefix(version, "v"), "-", "~", 1) + + if edition == "pro" { + // "pro" in this case is called "enterprise2" + fullName = "grafana-enterprise2" + edition = proName + // and is in the 'downloads-enterprise2' folder instead of 'downloads' + enterprise2 = "-enterprise2" + // and has an period separator {version}.{arch} instead of {version}_{arch} + } + dst := fmt.Sprintf(rpmFormat, version, edition, fullName, ersion, goos, arch, edition, sha256, enterprise2) + + return []string{ + dst, + } +} + +func EXEHandler(name string) []string { + packages := DebHandler(strings.ReplaceAll(name, "exe", "deb")) + for i, v := range packages { + v = strings.ReplaceAll(v, "deb", "exe") + v = strings.ReplaceAll(v, "amd64", "windows-amd64") + v = strings.ReplaceAll(v, "_", "-") + v = strings.ReplaceAll(v, "~", "-") + v = strings.ReplaceAll(v, "-windows", ".windows") + packages[i] = v + } + + return packages +} + +func DebHandler(name string) []string { + ext := filepath.Ext(name) + format := debFormat + if IsMain() { + format = debMainFormat + } + + // If we're copying a sha256 file and not a tar.gz then we want to add .sha256 to the template + // or just give it emptystring if it's not the sha256 file + sha256 := "" + if ext == sha256Ext { + sha256 = sha256Ext + } + + n := filepath.Base(name) // Surprisingly still works even with 'gs://' urls + opts := pipelines.TarOptsFromFileName(strings.ReplaceAll(strings.ReplaceAll(n, sha256Ext, ""), "deb", "tar.gz")) + + // In grafana-build we just use "" to refer to "oss" + edition := "oss" + fullName := grafana + version := opts.Version + ersion := strings.TrimPrefix(version, "v") + ersion = strings.Replace(ersion, "-", "~", 1) + enterprise2 := "" + if opts.Edition != "" { + edition = opts.Edition + fullName += "-" + opts.Edition + if edition == "pro" { + // "pro" in this case is called "enterprise2" + fullName = "grafana-enterprise2" + edition = proName + // and is in the 'downloads-enterprise2' folder instead of 'downloads' + enterprise2 = "-enterprise2" + } + + if edition == "pro-rpi" { + // "pro" in this case is called "enterprise2" + fullName = "grafana-enterprise2-rpi" + edition = proName + // and is in the 'downloads-enterprise2' folder instead of 'downloads' + enterprise2 = "-enterprise2" + } + + if edition == "rpi" { + edition = "oss" + } + + if edition == "enterprise-rpi" { + edition = "enterprise" + } + } + + names := []string{fullName} + goos, arch := backend.OSAndArch(opts.Distro) + if arch == "arm" { + arch = "armhf" + // If we're building for arm then we also copy the same thing, but with the name '-rpi'. for osme reason? + names = []string{fullName} + } + + dst := []string{} + for _, n := range names { + dst = append(dst, fmt.Sprintf(format, opts.Version, edition, n, ersion, goos, arch, edition, sha256, enterprise2)) + } + + return dst +} + +func TarGZHandler(name string) []string { + ext := filepath.Ext(name) + + // If we're copying a sha256 file and not a tar.gz then we want to add .sha256 to the template + // or just give it emptystring if it's not the sha256 file + sha256 := "" + if ext == sha256Ext { + sha256 = sha256Ext + } + + n := filepath.Base(name) // Surprisingly still works even with 'gs://' urls + opts := pipelines.TarOptsFromFileName(strings.ReplaceAll(n, sha256Ext, "")) + + // In grafana-build we just use "" to refer to "oss" + edition := "oss" + fullName := grafana + version := opts.Version + ersion := strings.TrimPrefix(version, "v") + enterprise2 := "" + if opts.Edition != "" { + edition = opts.Edition + fullName += "-" + opts.Edition + if edition == "pro" { + enterprise2 = "-enterprise2" + fullName = "grafana-enterprise2" + edition = proName + } + } + + libc := []string{""} + goos, arch := backend.OSAndArch(opts.Distro) + + if arch == "arm64" || arch == "arm" || arch == "amd64" && goos == "linux" { + libc = []string{"", "-musl"} + } + + arm := backend.ArchVersion(opts.Distro) + if arch == "arm" { + arch += "v" + arm + // I guess we don't create an arm-6-musl? + if arm == "6" { + libc = []string{""} + } + } + format := tarGzFormat + if IsMain() { + format = tarGzMainFormat + } + dst := []string{} + for _, m := range libc { + dst = append(dst, fmt.Sprintf(format, opts.Version, edition, fullName, ersion, goos, arch, m, sha256, enterprise2)) + } + + return dst +} + +func DockerHandler(name string) []string { + ext := filepath.Ext(name) + + // If we're copying a sha256 file and not a tar.gz then we want to add .sha256 to the template + // or just give it emptystring if it's not the sha256 file + sha256 := "" + if ext == sha256Ext { + sha256 = sha256Ext + } + + n := filepath.Base(name) // Surprisingly still works even with 'gs://' urls + + // try to get .ubuntu.docker.tar.gz.sha256 / .ubuntu.docker.tar.gz / docker.tar.gz to all just end in 'tar.gz' + normalized := strings.ReplaceAll(n, sha256Ext, "") + normalized = strings.ReplaceAll(normalized, ".ubuntu", "") + normalized = strings.ReplaceAll(normalized, ".docker", "") + + opts := pipelines.TarOptsFromFileName(normalized) + + // In grafana-build we just use "" to refer to "oss" + edition := "oss" + fullName := grafana + if opts.Edition != "" { + edition = opts.Edition + if edition == "pro" { + edition = proName + } + } + + fullName += "-" + edition + ubuntu := "" + if strings.Contains(name, "ubuntu") { + ubuntu = "-ubuntu" + } + + _, arch := backend.OSAndArch(opts.Distro) + if arch == "arm" { + arch += "v" + backend.ArchVersion(opts.Distro) + } + return []string{ + fmt.Sprintf(dockerFormat, strings.TrimPrefix(opts.Version, "v"), fullName, ubuntu, arch, sha256), + } +} + +func CDNHandler(name string) []string { + if IsMain() { + // This folder is is always ${dist}/${version}/${name}/${public} + dist, err := filepath.Rel(".", filepath.Join(name, "../../../")) + if err != nil { + panic(err) + } + + path, err := filepath.Rel(dist, name) + if err != nil { + panic(err) + } + s := strings.Split(path, string(os.PathSeparator)) + return []string{fmt.Sprintf(cdnMainFormat, s[0])} + } + version := strings.TrimPrefix(os.Getenv("DRONE_TAG"), "v") + return []string{fmt.Sprintf(cdnFormat, version, grafana)} +} + +func StorybookHandler(name string) []string { + version := strings.TrimPrefix(os.Getenv("DRONE_TAG"), "v") + return []string{fmt.Sprintf(storybookFormat, version)} +} + +// A hopefully temporary script that prints the gsutil commands that will move these artifacts into the location where they were expected previously. +// Just pipe this into bash or exec or whatever to do the actual copying. +// Run without redirecting stdout to verify the operations. +func main() { + prefix := os.Args[1] + + ctx := context.Background() + client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr)) + if err != nil { + panic(err) + } + + var ( + scanner = bufio.NewScanner(os.Stdin) + authenticator = containers.GCSAuth(client, &containers.GCPOpts{ + ServiceAccountKeyBase64: os.Getenv("GCP_KEY_BASE64"), + }) + + container = client.Container().From("google/cloud-sdk:alpine") + ) + // + if c, err := authenticator.Authenticate(client, container); err == nil { + container = c + } else { + panic(err) + } + + for scanner.Scan() { + var ( + name = scanner.Text() + ) + handler, ext := getHandler(name, Handlers) + destinations := handler(name) + if ext == "" { + for _, v := range destinations { + dir := filepath.Join(prefix, filepath.Dir(v)) + v := filepath.Join(prefix, v) + + log.Println("Creating dir", dir) + if err := os.MkdirAll(dir, 0700); err != nil { + panic(err) + } + log.Println("Copying", name, "to", v) + //nolint:gosec + cmd := exec.Command("cp", "-r", strings.TrimPrefix(name, "file://"), v) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + panic(err) + } + } + continue + } + + log.Println("File:", name, "to be copied as", destinations) + for _, v := range destinations { + dir := filepath.Join(prefix, filepath.Dir(v)) + v := filepath.Join(prefix, v) + log.Println("Creating directory", dir) + if err := os.MkdirAll(dir, 0700); err != nil { + panic(err) + } + + log.Println("Copying", name, "to", dir, "as", v) + + //nolint:gosec + cmd := exec.Command("cp", strings.TrimPrefix(name, "file://"), v) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + panic(err) + } + } + } + + log.Println("Copying", prefix, "to gcs") + dst := os.Getenv("DESTINATION") + container = container.WithMountedDirectory("dist", client.Host().Directory(prefix)). + WithExec([]string{"gcloud", "storage", "cp", "-r", "/dist/*", dst}) + + stdout, err := container.Stdout(ctx) + if err != nil { + panic(err) + } + + stderr, err := container.Stdout(ctx) + if err != nil { + panic(err) + } + + fmt.Fprint(os.Stdout, stdout) + fmt.Fprint(os.Stderr, stderr) +} + +func getHandler(name string, handlers map[string]HandlerFunc) (HandlerFunc, string) { + ext := filepath.Ext(name) + // sha256 extensions should be handled the same way what precedes the extension + if ext == sha256Ext { + ext = filepath.Ext(strings.ReplaceAll(name, sha256Ext, "")) + } + + // tar.gz extensions can also have docker.tar.gz so we need to make sure we don't skip that + if ext == ".gz" { + ext = ".tar.gz" + if filepath.Ext(strings.ReplaceAll(name, ".tar.gz", "")) == ".docker" || + filepath.Ext(strings.ReplaceAll(name, ".tar.gz.sha256", "")) == ".docker" { + ext = ".docker.tar.gz" + } + } + + handler := handlers[ext] + // If there is no extension, then we are either dealing with public assets + // or the storybook, which both require some extra handling: + if ext != "" { + return handler, ext + } + + if filepath.Base(name) == "public" { + return CDNHandler, "" + } + if filepath.Base(name) == "storybook" { + return StorybookHandler, "" + } + if filepath.Base(name) == "npm-packages" { + return NPMHandler, "" + } + panic("no handler found") +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_cdn_test.go b/pkg/build/daggerbuild/scripts/move_packages_cdn_test.go new file mode 100644 index 00000000000..d4b1711d355 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_cdn_test.go @@ -0,0 +1,32 @@ +package main + +var cdnMapping = map[string]m{ + "OSS: Linux AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64/public", + output: []string{ + "artifacts/static-assets/grafana/1.2.3/public", + }, + env: map[string]string{"DRONE_TAG": "1.2.3"}, + }, + "ENT: Linux AMD64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64/public", + output: []string{ + "artifacts/static-assets/grafana/1.2.3/public", + }, + env: map[string]string{"DRONE_TAG": "1.2.3"}, + }, + "PRO: Linux AMD64": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_amd64/public", + output: []string{ + "artifacts/static-assets/grafana/1.2.3/public", + }, + env: map[string]string{"DRONE_TAG": "1.2.3"}, + }, + "main": { + input: "dist/10.3.0-62960/grafana-enterprise/public", + output: []string{ + "grafana/10.3.0-62960/public", + }, + env: map[string]string{"IS_MAIN": "true"}, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_deb_test.go b/pkg/build/daggerbuild/scripts/move_packages_deb_test.go new file mode 100644 index 00000000000..09c882a4177 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_deb_test.go @@ -0,0 +1,130 @@ +package main + +var debMapping = map[string]m{ + "OSS: Linux AMD64 on main": { + env: map[string]string{ + "IS_MAIN": "true", + }, + input: "file://dist/grafana_v1.2.3_102_linux_amd64.deb", + output: []string{ + "oss/main/grafana_1.2.3_amd64.deb", + }, + }, + "OSS: Linux AMD64 on main with - in version": { + env: map[string]string{ + "IS_MAIN": "true", + }, + input: "file://dist/grafana_v1.2.3-102_102_linux_amd64.deb", + output: []string{ + "oss/main/grafana_1.2.3~102_amd64.deb", + }, + }, + "OSS: Linux AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.deb", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana_1.2.3_amd64.deb", + }, + }, + "OSS: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.deb.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana_1.2.3_amd64.deb.sha256", + }, + }, + "OSS: Linux ARM7": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.deb", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana_1.2.3_armhf.deb", + }, + }, + "OSS: RPI ARM7": { + input: "gs://bucket/tag/grafana-rpi_v1.2.3_102_linux_arm-7.deb", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-rpi_1.2.3_armhf.deb", + }, + }, + "OSS: RPI ARM6": { + input: "gs://bucket/tag/grafana-rpi_v1.2.3_102_linux_arm-6.deb", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-rpi_1.2.3_armhf.deb", + }, + }, + "OSS: Linux ARM7 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.deb.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana_1.2.3_armhf.deb.sha256", + }, + }, + "OSS: Linux ARM64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.deb", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana_1.2.3_arm64.deb", + }, + }, + "OSS: Linux ARM64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.deb.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana_1.2.3_arm64.deb.sha256", + }, + }, + "ENT: Linux AMD64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.deb", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise_1.2.3_amd64.deb", + }, + }, + "ENT: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.deb.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise_1.2.3_amd64.deb.sha256", + }, + }, + "ENT: Linux ARM64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.deb", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise_1.2.3_arm64.deb", + }, + }, + "ENT: Linux ARM64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.deb.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise_1.2.3_arm64.deb.sha256", + }, + }, + "ENT: Linux ARM7": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.deb", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise_1.2.3_armhf.deb", + }, + }, + "ENT: RPI ARM7": { + input: "gs://bucket/tag/grafana-enterprise-rpi_v1.2.3_102_linux_arm-7.deb", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-rpi_1.2.3_armhf.deb", + }, + }, + "ENT: ARM7 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.deb.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise_1.2.3_armhf.deb.sha256", + }, + }, + "ENT2: RPI ARM7": { + input: "gs://bucket/tag/grafana-pro-rpi_v1.2.3_102_linux_arm-7.deb", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3/enterprise2/release/grafana-enterprise2-rpi_1.2.3_armhf.deb", + }, + }, + "ENT2: Pre-release AMD64": { + input: "gs://bucket/tag/grafana-pro_v1.2.3-pre.4_102_linux_amd64.deb", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2_1.2.3~pre.4_amd64.deb", + }, + }, + "ENT2: Pre-release AMD64 SHA256": { + input: "gs://bucket/tag/grafana-pro_v1.2.3-pre.4_102_linux_amd64.deb.sha256", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2_1.2.3~pre.4_amd64.deb.sha256", + }, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_docker_test.go b/pkg/build/daggerbuild/scripts/move_packages_docker_test.go new file mode 100644 index 00000000000..70660c8e04f --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_docker_test.go @@ -0,0 +1,184 @@ +package main + +var dockerMapping = map[string]m{ + "ENT: Linux AMD64 Ubuntu": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-ubuntu-amd64.img", + }, + }, + "ENT: Linux AMD64 Ubuntu SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.ubuntu.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-ubuntu-amd64.img.sha256", + }, + }, + "ENT: Linux ARM64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-arm64.img", + }, + }, + "ENT: Linux ARM64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-arm64.img.sha256", + }, + }, + "ENT: Linux ARM7": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-armv7.img", + }, + }, + "ENT: Linux ARM7 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-armv7.img.sha256", + }, + }, + "ENT: Linux ARM7 Ubuntu": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-ubuntu-armv7.img", + }, + }, + "ENT: Linux AR7 Ubuntu SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.ubuntu.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-ubuntu-armv7.img.sha256", + }, + }, + "ENT: Linux AMD64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-amd64.img", + }, + }, + "ENT: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-amd64.img.sha256", + }, + }, + "ENT: Linux ARM64 Ubuntu": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-ubuntu-arm64.img", + }, + }, + "ENT: Linux ARM64 Ubuntu SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.ubuntu.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise-1.2.3-ubuntu-arm64.img.sha256", + }, + }, + "OSS: Linux ARM7": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-armv7.img", + }, + }, + "OSS: Linux ARM7 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-armv7.img.sha256", + }, + }, + "OSS: Linux ARM7 Ubuntu": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-ubuntu-armv7.img", + }, + }, + "OSS: Linux AR7 Ubuntu SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.ubuntu.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-ubuntu-armv7.img.sha256", + }, + }, + "OSS: Linux AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-amd64.img", + }, + }, + "OSS: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-amd64.img.sha256", + }, + }, + "OSS: Linux AMD64 Ubuntu": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-ubuntu-amd64.img", + }, + }, + "OSS: Linux AMD64 Ubuntu SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.ubuntu.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-ubuntu-amd64.img.sha256", + }, + }, + "OSS: Linux ARM64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-arm64.img", + }, + }, + "OSS: Linux ARM64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-arm64.img.sha256", + }, + }, + "OSS: Linux ARM64 Ubuntu": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-ubuntu-arm64.img", + }, + }, + "OSS: Linux ARM64 Ubuntu SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.ubuntu.docker.tar.gz.sha256", + output: []string{ + "artifacts/docker/1.2.3/grafana-oss-1.2.3-ubuntu-arm64.img.sha256", + }, + }, + "PRO: Linux AMD64": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_amd64.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise2-1.2.3-amd64.img", + }, + }, + "PRO: Linux ARM64": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_arm64.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise2-1.2.3-arm64.img", + }, + }, + "PRO: Linux ARM7": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_arm-7.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise2-1.2.3-armv7.img", + }, + }, + "PRO: Linux AMD64 Ubuntu": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_amd64.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise2-1.2.3-ubuntu-amd64.img", + }, + }, + "PRO: Linux ARM64 Ubuntu": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_arm64.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise2-1.2.3-ubuntu-arm64.img", + }, + }, + "PRO: Linux ARM7 Ubuntu": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_arm-7.ubuntu.docker.tar.gz", + output: []string{ + "artifacts/docker/1.2.3/grafana-enterprise2-1.2.3-ubuntu-armv7.img", + }, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_exe_test.go b/pkg/build/daggerbuild/scripts/move_packages_exe_test.go new file mode 100644 index 00000000000..32499c805c7 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_exe_test.go @@ -0,0 +1,28 @@ +package main + +var exeMapping = map[string]m{ + "ENT": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_windows_amd64.exe", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.windows-amd64.exe", + }, + }, + "ENT SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_windows_amd64.exe.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.windows-amd64.exe.sha256", + }, + }, + "OSS": { + input: "gs://bucket/tag/grafana_v1.2.3_102_windows_amd64.exe", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.windows-amd64.exe", + }, + }, + "OSS SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_windows_amd64.exe.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.windows-amd64.exe.sha256", + }, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_msi_test.go b/pkg/build/daggerbuild/scripts/move_packages_msi_test.go new file mode 100644 index 00000000000..77db73d4b58 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_msi_test.go @@ -0,0 +1,28 @@ +package main + +var msiMapping = map[string]m{ + "ENT": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_windows_amd64.msi", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.windows-amd64.msi", + }, + }, + "ENT SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_windows_amd64.msi.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.windows-amd64.msi.sha256", + }, + }, + "OSS": { + input: "gs://bucket/tag/grafana_v1.2.3_102_windows_amd64.msi", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.windows-amd64.msi", + }, + }, + "OSS SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_windows_amd64.msi.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.windows-amd64.msi.sha256", + }, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_npm_test.go b/pkg/build/daggerbuild/scripts/move_packages_npm_test.go new file mode 100644 index 00000000000..146a1b1219b --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_npm_test.go @@ -0,0 +1,11 @@ +package main + +var npmMapping = map[string]m{ + "Grafana data": { + input: "file://dist/tag/grafana-10.2.0-pre/npm-packages", + output: []string{ + "artifacts/npm/v10.2.0-pre/npm-artifacts", + }, + env: map[string]string{"DRONE_TAG": "10.2.0-pre"}, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_rpm_test.go b/pkg/build/daggerbuild/scripts/move_packages_rpm_test.go new file mode 100644 index 00000000000..22b1d8ac8a9 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_rpm_test.go @@ -0,0 +1,88 @@ +package main + +var rpmMapping = map[string]m{ + "OSS: Linux AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.rpm", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3-1.x86_64.rpm", + }, + }, + "OSS: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.rpm.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3-1.x86_64.rpm.sha256", + }, + }, + "OSS: Linux ARM7": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.rpm", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3-1.armhfp.rpm", + }, + }, + "OSS: Linux ARM7 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.rpm.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3-1.armhfp.rpm.sha256", + }, + }, + "OSS: Linux aarch64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_aarch64.rpm", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3-1.aarch64.rpm", + }, + }, + "OSS: Linux aarch64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.rpm.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3-1.aarch64.rpm.sha256", + }, + }, + "ENT: Linux AMD64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.rpm", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3-1.x86_64.rpm", + }, + }, + "ENT: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.rpm.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3-1.x86_64.rpm.sha256", + }, + }, + "ENT: Linux ARM64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.rpm", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3-1.aarch64.rpm", + }, + }, + "ENT: Linux ARM64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.rpm.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3-1.aarch64.rpm.sha256", + }, + }, + "ENT: Linux ARM7": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.rpm", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3-1.armhfp.rpm", + }, + }, + "ENT: Linux ARM7 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.rpm.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3-1.armhfp.rpm.sha256", + }, + }, + "PRO: Linux AMD64": { + input: "gs://bucket/tag/grafana-pro_v1.2.3-pre.4_102_linux_amd64.rpm", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2-1.2.3~pre.4-1.x86_64.rpm", + }, + }, + "PRO: Linux AMD64 SHA256": { + input: "gs://bucket/tag/grafana-pro_v1.2.3-pre.4_102_linux_amd64.rpm.sha256", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2-1.2.3~pre.4-1.x86_64.rpm.sha256", + }, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_storybook_test.go b/pkg/build/daggerbuild/scripts/move_packages_storybook_test.go new file mode 100644 index 00000000000..6616d3027a2 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_storybook_test.go @@ -0,0 +1,25 @@ +package main + +var storybookMapping = map[string]m{ + "OSS": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64/storybook", + output: []string{ + "artifacts/storybook/v1.2.3", + }, + env: map[string]string{"DRONE_TAG": "1.2.3"}, + }, + "ENT": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64/storybook", + output: []string{ + "artifacts/storybook/v1.2.3", + }, + env: map[string]string{"DRONE_TAG": "1.2.3"}, + }, + "PRO": { + input: "gs://bucket/tag/grafana-pro_v1.2.3_102_linux_amd64/storybook", + output: []string{ + "artifacts/storybook/v1.2.3", + }, + env: map[string]string{"DRONE_TAG": "1.2.3"}, + }, +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_test.go b/pkg/build/daggerbuild/scripts/move_packages_test.go new file mode 100644 index 00000000000..5b1d310f386 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_test.go @@ -0,0 +1,215 @@ +package main + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/require" +) + +type m struct { + input string + output []string + env map[string]string +} + +var targzMapping = map[string]m{ + "ENT: Darwin AMD64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_darwin_amd64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.darwin-amd64.tar.gz", + }, + }, + "ENT: Darwin AMD64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_darwin_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.darwin-amd64.tar.gz.sha256", + }, + }, + "ENT: AMD64 with MUSL copy": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-amd64-musl.tar.gz", + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-amd64.tar.gz", + }, + }, + "ENT: AMD64 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-amd64-musl.tar.gz.sha256", + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-amd64.tar.gz.sha256", + }, + }, + "ENT: ARM64 with MUSL copy": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-arm64-musl.tar.gz", + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-arm64.tar.gz", + }, + }, + "ENT: ARM64 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-arm64-musl.tar.gz.sha256", + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-arm64.tar.gz.sha256", + }, + }, + "ENT: ARM6": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-6.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-armv6.tar.gz", + }, + }, + "ENT: ARM6 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-6.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-armv6.tar.gz.sha256", + }, + }, + "ENT: ARM7 with MUSL copy": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-armv7-musl.tar.gz", + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-armv7.tar.gz", + }, + }, + "ENT: ARM7 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_linux_arm-7.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-armv7-musl.tar.gz.sha256", + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.linux-armv7.tar.gz.sha256", + }, + }, + "ENT: Windows AMD64": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_windows_amd64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.windows-amd64.tar.gz", + }, + }, + "ENT: Windows AMD64 SHA256": { + input: "gs://bucket/tag/grafana-enterprise_v1.2.3_102_windows_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/enterprise/release/grafana-enterprise-1.2.3.windows-amd64.tar.gz.sha256", + }, + }, + "OSS: ARM6": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-6.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-armv6.tar.gz", + }, + }, + "OSS: ARM6 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-6.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-armv6.tar.gz.sha256", + }, + }, + "OSS: ARM7 with MUSL copy": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-armv7-musl.tar.gz", + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-armv7.tar.gz", + }, + }, + "OSS: ARM7 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm-7.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-armv7-musl.tar.gz.sha256", + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-armv7.tar.gz.sha256", + }, + }, + "OSS: Windows AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_windows_amd64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.windows-amd64.tar.gz", + }, + }, + "OSS: Windows AMD64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_windows_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.windows-amd64.tar.gz.sha256", + }, + }, + "OSS: Darwin AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3_102_darwin_amd64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.darwin-amd64.tar.gz", + }, + }, + "OSS: Darwin AMD64 SHA256": { + input: "gs://bucket/tag/grafana_v1.2.3_102_darwin_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.darwin-amd64.tar.gz.sha256", + }, + }, + "OSS: Linux AMD64 with MUSL copy": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-amd64-musl.tar.gz", + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-amd64.tar.gz", + }, + }, + "OSS: Linux AMD64 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-amd64-musl.tar.gz.sha256", + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-amd64.tar.gz.sha256", + }, + }, + "OSS: Linux ARM64 with MUSL copy": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.tar.gz", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-arm64-musl.tar.gz", + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-arm64.tar.gz", + }, + }, + "OSS: Linux ARM64 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana_v1.2.3_102_linux_arm64.tar.gz.sha256", + output: []string{ + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-arm64-musl.tar.gz.sha256", + "artifacts/downloads/v1.2.3/oss/release/grafana-1.2.3.linux-arm64.tar.gz.sha256", + }, + }, + "ENT2: Linux AMD64 with MUSL copy": { + input: "gs://bucket/tag/grafana-pro_v1.2.3-pre.4_102_linux_amd64.tar.gz", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2-1.2.3-pre.4.linux-amd64-musl.tar.gz", + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2-1.2.3-pre.4.linux-amd64.tar.gz", + }, + }, + "ENT2: Linux AMD64 SHA256 with MUSL copy": { + input: "gs://bucket/tag/grafana-pro_v1.2.3-pre.4_102_linux_amd64.tar.gz.sha256", + output: []string{ + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2-1.2.3-pre.4.linux-amd64-musl.tar.gz.sha256", + "artifacts/downloads-enterprise2/v1.2.3-pre.4/enterprise2/release/grafana-enterprise2-1.2.3-pre.4.linux-amd64.tar.gz.sha256", + }, + }, +} + +func TestGetHandler(t *testing.T) { + runTests(t, "TARGZ: ", targzMapping) + runTests(t, "DOCKER: ", dockerMapping) + runTests(t, "CDN: ", cdnMapping) + runTests(t, "ZIP: ", zipMapping) + runTests(t, "MSI: ", msiMapping) + runTests(t, "NPM: ", npmMapping) + runTests(t, "DEB: ", debMapping) + runTests(t, "RPM: ", rpmMapping) + runTests(t, "EXE: ", exeMapping) + runTests(t, "STORYBOOK: ", storybookMapping) +} + +func runTests(t *testing.T, namePrefix string, tests map[string]m) { + t.Helper() + for testname, testcase := range tests { + t.Run(namePrefix+testname, func(t *testing.T) { + for envName, envValue := range testcase.env { + t.Setenv(envName, envValue) + } + handler, _ := getHandler(testcase.input, Handlers) + output := handler(testcase.input) + sort.Strings(output) + require.Equal(t, testcase.output, output) + }) + } +} diff --git a/pkg/build/daggerbuild/scripts/move_packages_zip_test.go b/pkg/build/daggerbuild/scripts/move_packages_zip_test.go new file mode 100644 index 00000000000..af121e1e7f5 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/move_packages_zip_test.go @@ -0,0 +1,22 @@ +package main + +var zipMapping = map[string]m{ + "OSS: Windows AMD64": { + input: "gs://bucket/tag/grafana_v1.2.3-test.1_102_windows_amd64.zip", + output: []string{ + "artifacts/downloads/v1.2.3-test.1/oss/release/grafana-1.2.3-test.1.windows-amd64.zip", + }, + }, + "OSS: Windows AMD64 from file://": { + input: "file://bucket/tag/grafana_v1.2.3-test.1_102_windows_amd64.zip", + output: []string{ + "artifacts/downloads/v1.2.3-test.1/oss/release/grafana-1.2.3-test.1.windows-amd64.zip", + }, + }, + "OSS: Windows AMD64 main from file://": { + input: "file://bucket/tag/grafana_main_102_windows_amd64.zip", + output: []string{ + "artifacts/downloads/main/oss/release/grafana-main.windows-amd64.zip", + }, + }, +} diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/AGPLv3.rtf b/pkg/build/daggerbuild/scripts/packaging/windows/AGPLv3.rtf new file mode 100755 index 00000000000..f7c0f8ad10b --- /dev/null +++ b/pkg/build/daggerbuild/scripts/packaging/windows/AGPLv3.rtf @@ -0,0 +1,667 @@ +{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Courier New;}} +{\colortbl ;\red0\green0\blue255;} +{\*\generator Riched20 10.0.19041}\viewkind4\uc1 +\pard\f0\fs22\lang1033 GNU AFFERO GENERAL PUBLIC LICENSE\par + Version 3, 19 November 2007\par +\par + Copyright (C) 2007 Free Software Foundation, Inc. <{{\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt{https://fsf.org/\ul0\cf0}}}}\f0\fs22 >\par + Everyone is permitted to copy and distribute verbatim copies\par + of this license document, but changing it is not allowed.\par +\par + Preamble\par +\par + The GNU Affero General Public License is a free, copyleft license for\par +software and other kinds of works, specifically designed to ensure\par +cooperation with the community in the case of network server software.\par +\par + The licenses for most software and other practical works are designed\par +to take away your freedom to share and change the works. By contrast,\par +our General Public Licenses are intended to guarantee your freedom to\par +share and change all versions of a program--to make sure it remains free\par +software for all its users.\par +\par + When we speak of free software, we are referring to freedom, not\par +price. Our General Public Licenses are designed to make sure that you\par +have the freedom to distribute copies of free software (and charge for\par +them if you wish), that you receive source code or can get it if you\par +want it, that you can change the software or use pieces of it in new\par +free programs, and that you know you can do these things.\par +\par + Developers that use our General Public Licenses protect your rights\par +with two steps: (1) assert copyright on the software, and (2) offer\par +you this License which gives you legal permission to copy, distribute\par +and/or modify the software.\par +\par + A secondary benefit of defending all users' freedom is that\par +improvements made in alternate versions of the program, if they\par +receive widespread use, become available for other developers to\par +incorporate. Many developers of free software are heartened and\par +encouraged by the resulting cooperation. However, in the case of\par +software used on network servers, this result may fail to come about.\par +The GNU General Public License permits making a modified version and\par +letting the public access it on a server without ever releasing its\par +source code to the public.\par +\par + The GNU Affero General Public License is designed specifically to\par +ensure that, in such cases, the modified source code becomes available\par +to the community. It requires the operator of a network server to\par +provide the source code of the modified version running there to the\par +users of that server. Therefore, public use of a modified version, on\par +a publicly accessible server, gives the public access to the source\par +code of the modified version.\par +\par + An older license, called the Affero General Public License and\par +published by Affero, was designed to accomplish similar goals. This is\par +a different license, not a version of the Affero GPL, but Affero has\par +released a new version of the Affero GPL which permits relicensing under\par +this license.\par +\par + The precise terms and conditions for copying, distribution and\par +modification follow.\par +\par + TERMS AND CONDITIONS\par +\par + 0. Definitions.\par +\par + "This License" refers to version 3 of the GNU Affero General Public License.\par +\par + "Copyright" also means copyright-like laws that apply to other kinds of\par +works, such as semiconductor masks.\par +\par + "The Program" refers to any copyrightable work licensed under this\par +License. Each licensee is addressed as "you". "Licensees" and\par +"recipients" may be individuals or organizations.\par +\par + To "modify" a work means to copy from or adapt all or part of the work\par +in a fashion requiring copyright permission, other than the making of an\par +exact copy. The resulting work is called a "modified version" of the\par +earlier work or a work "based on" the earlier work.\par +\par + A "covered work" means either the unmodified Program or a work based\par +on the Program.\par +\par + To "propagate" a work means to do anything with it that, without\par +permission, would make you directly or secondarily liable for\par +infringement under applicable copyright law, except executing it on a\par +computer or modifying a private copy. Propagation includes copying,\par +distribution (with or without modification), making available to the\par +public, and in some countries other activities as well.\par +\par + To "convey" a work means any kind of propagation that enables other\par +parties to make or receive copies. Mere interaction with a user through\par +a computer network, with no transfer of a copy, is not conveying.\par +\par + An interactive user interface displays "Appropriate Legal Notices"\par +to the extent that it includes a convenient and prominently visible\par +feature that (1) displays an appropriate copyright notice, and (2)\par +tells the user that there is no warranty for the work (except to the\par +extent that warranties are provided), that licensees may convey the\par +work under this License, and how to view a copy of this License. If\par +the interface presents a list of user commands or options, such as a\par +menu, a prominent item in the list meets this criterion.\par +\par + 1. Source Code.\par +\par + The "source code" for a work means the preferred form of the work\par +for making modifications to it. "Object code" means any non-source\par +form of a work.\par +\par + A "Standard Interface" means an interface that either is an official\par +standard defined by a recognized standards body, or, in the case of\par +interfaces specified for a particular programming language, one that\par +is widely used among developers working in that language.\par +\par + The "System Libraries" of an executable work include anything, other\par +than the work as a whole, that (a) is included in the normal form of\par +packaging a Major Component, but which is not part of that Major\par +Component, and (b) serves only to enable use of the work with that\par +Major Component, or to implement a Standard Interface for which an\par +implementation is available to the public in source code form. A\par +"Major Component", in this context, means a major essential component\par +(kernel, window system, and so on) of the specific operating system\par +(if any) on which the executable work runs, or a compiler used to\par +produce the work, or an object code interpreter used to run it.\par +\par + The "Corresponding Source" for a work in object code form means all\par +the source code needed to generate, install, and (for an executable\par +work) run the object code and to modify the work, including scripts to\par +control those activities. However, it does not include the work's\par +System Libraries, or general-purpose tools or generally available free\par +programs which are used unmodified in performing those activities but\par +which are not part of the work. For example, Corresponding Source\par +includes interface definition files associated with source files for\par +the work, and the source code for shared libraries and dynamically\par +linked subprograms that the work is specifically designed to require,\par +such as by intimate data communication or control flow between those\par +subprograms and other parts of the work.\par +\par + The Corresponding Source need not include anything that users\par +can regenerate automatically from other parts of the Corresponding\par +Source.\par +\par + The Corresponding Source for a work in source code form is that\par +same work.\par +\par + 2. Basic Permissions.\par +\par + All rights granted under this License are granted for the term of\par +copyright on the Program, and are irrevocable provided the stated\par +conditions are met. This License explicitly affirms your unlimited\par +permission to run the unmodified Program. The output from running a\par +covered work is covered by this License only if the output, given its\par +content, constitutes a covered work. This License acknowledges your\par +rights of fair use or other equivalent, as provided by copyright law.\par +\par + You may make, run and propagate covered works that you do not\par +convey, without conditions so long as your license otherwise remains\par +in force. You may convey covered works to others for the sole purpose\par +of having them make modifications exclusively for you, or provide you\par +with facilities for running those works, provided that you comply with\par +the terms of this License in conveying all material for which you do\par +not control copyright. Those thus making or running the covered works\par +for you must do so exclusively on your behalf, under your direction\par +and control, on terms that prohibit them from making any copies of\par +your copyrighted material outside their relationship with you.\par +\par + Conveying under any other circumstances is permitted solely under\par +the conditions stated below. Sublicensing is not allowed; section 10\par +makes it unnecessary.\par +\par + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\par +\par + No covered work shall be deemed part of an effective technological\par +measure under any applicable law fulfilling obligations under article\par +11 of the WIPO copyright treaty adopted on 20 December 1996, or\par +similar laws prohibiting or restricting circumvention of such\par +measures.\par +\par + When you convey a covered work, you waive any legal power to forbid\par +circumvention of technological measures to the extent such circumvention\par +is effected by exercising rights under this License with respect to\par +the covered work, and you disclaim any intention to limit operation or\par +modification of the work as a means of enforcing, against the work's\par +users, your or third parties' legal rights to forbid circumvention of\par +technological measures.\par +\par + 4. Conveying Verbatim Copies.\par +\par + You may convey verbatim copies of the Program's source code as you\par +receive it, in any medium, provided that you conspicuously and\par +appropriately publish on each copy an appropriate copyright notice;\par +keep intact all notices stating that this License and any\par +non-permissive terms added in accord with section 7 apply to the code;\par +keep intact all notices of the absence of any warranty; and give all\par +recipients a copy of this License along with the Program.\par +\par + You may charge any price or no price for each copy that you convey,\par +and you may offer support or warranty protection for a fee.\par +\par + 5. Conveying Modified Source Versions.\par +\par + You may convey a work based on the Program, or the modifications to\par +produce it from the Program, in the form of source code under the\par +terms of section 4, provided that you also meet all of these conditions:\par +\par + a) The work must carry prominent notices stating that you modified\par + it, and giving a relevant date.\par +\par + b) The work must carry prominent notices stating that it is\par + released under this License and any conditions added under section\par + 7. This requirement modifies the requirement in section 4 to\par + "keep intact all notices".\par +\par + c) You must license the entire work, as a whole, under this\par + License to anyone who comes into possession of a copy. This\par + License will therefore apply, along with any applicable section 7\par + additional terms, to the whole of the work, and all its parts,\par + regardless of how they are packaged. This License gives no\par + permission to license the work in any other way, but it does not\par + invalidate such permission if you have separately received it.\par +\par + d) If the work has interactive user interfaces, each must display\par + Appropriate Legal Notices; however, if the Program has interactive\par + interfaces that do not display Appropriate Legal Notices, your\par + work need not make them do so.\par +\par + A compilation of a covered work with other separate and independent\par +works, which are not by their nature extensions of the covered work,\par +and which are not combined with it such as to form a larger program,\par +in or on a volume of a storage or distribution medium, is called an\par +"aggregate" if the compilation and its resulting copyright are not\par +used to limit the access or legal rights of the compilation's users\par +beyond what the individual works permit. Inclusion of a covered work\par +in an aggregate does not cause this License to apply to the other\par +parts of the aggregate.\par +\par + 6. Conveying Non-Source Forms.\par +\par + You may convey a covered work in object code form under the terms\par +of sections 4 and 5, provided that you also convey the\par +machine-readable Corresponding Source under the terms of this License,\par +in one of these ways:\par +\par + a) Convey the object code in, or embodied in, a physical product\par + (including a physical distribution medium), accompanied by the\par + Corresponding Source fixed on a durable physical medium\par + customarily used for software interchange.\par +\par + b) Convey the object code in, or embodied in, a physical product\par + (including a physical distribution medium), accompanied by a\par + written offer, valid for at least three years and valid for as\par + long as you offer spare parts or customer support for that product\par + model, to give anyone who possesses the object code either (1) a\par + copy of the Corresponding Source for all the software in the\par + product that is covered by this License, on a durable physical\par + medium customarily used for software interchange, for a price no\par + more than your reasonable cost of physically performing this\par + conveying of source, or (2) access to copy the\par + Corresponding Source from a network server at no charge.\par +\par + c) Convey individual copies of the object code with a copy of the\par + written offer to provide the Corresponding Source. This\par + alternative is allowed only occasionally and noncommercially, and\par + only if you received the object code with such an offer, in accord\par + with subsection 6b.\par +\par + d) Convey the object code by offering access from a designated\par + place (gratis or for a charge), and offer equivalent access to the\par + Corresponding Source in the same way through the same place at no\par + further charge. You need not require recipients to copy the\par + Corresponding Source along with the object code. If the place to\par + copy the object code is a network server, the Corresponding Source\par + may be on a different server (operated by you or a third party)\par + that supports equivalent copying facilities, provided you maintain\par + clear directions next to the object code saying where to find the\par + Corresponding Source. Regardless of what server hosts the\par + Corresponding Source, you remain obligated to ensure that it is\par + available for as long as needed to satisfy these requirements.\par +\par + e) Convey the object code using peer-to-peer transmission, provided\par + you inform other peers where the object code and Corresponding\par + Source of the work are being offered to the general public at no\par + charge under subsection 6d.\par +\par + A separable portion of the object code, whose source code is excluded\par +from the Corresponding Source as a System Library, need not be\par +included in conveying the object code work.\par +\par + A "User Product" is either (1) a "consumer product", which means any\par +tangible personal property which is normally used for personal, family,\par +or household purposes, or (2) anything designed or sold for incorporation\par +into a dwelling. In determining whether a product is a consumer product,\par +doubtful cases shall be resolved in favor of coverage. For a particular\par +product received by a particular user, "normally used" refers to a\par +typical or common use of that class of product, regardless of the status\par +of the particular user or of the way in which the particular user\par +actually uses, or expects or is expected to use, the product. A product\par +is a consumer product regardless of whether the product has substantial\par +commercial, industrial or non-consumer uses, unless such uses represent\par +the only significant mode of use of the product.\par +\par + "Installation Information" for a User Product means any methods,\par +procedures, authorization keys, or other information required to install\par +and execute modified versions of a covered work in that User Product from\par +a modified version of its Corresponding Source. The information must\par +suffice to ensure that the continued functioning of the modified object\par +code is in no case prevented or interfered with solely because\par +modification has been made.\par +\par + If you convey an object code work under this section in, or with, or\par +specifically for use in, a User Product, and the conveying occurs as\par +part of a transaction in which the right of possession and use of the\par +User Product is transferred to the recipient in perpetuity or for a\par +fixed term (regardless of how the transaction is characterized), the\par +Corresponding Source conveyed under this section must be accompanied\par +by the Installation Information. But this requirement does not apply\par +if neither you nor any third party retains the ability to install\par +modified object code on the User Product (for example, the work has\par +been installed in ROM).\par +\par + The requirement to provide Installation Information does not include a\par +requirement to continue to provide support service, warranty, or updates\par +for a work that has been modified or installed by the recipient, or for\par +the User Product in which it has been modified or installed. Access to a\par +network may be denied when the modification itself materially and\par +adversely affects the operation of the network or violates the rules and\par +protocols for communication across the network.\par +\par + Corresponding Source conveyed, and Installation Information provided,\par +in accord with this section must be in a format that is publicly\par +documented (and with an implementation available to the public in\par +source code form), and must require no special password or key for\par +unpacking, reading or copying.\par +\par + 7. Additional Terms.\par +\par + "Additional permissions" are terms that supplement the terms of this\par +License by making exceptions from one or more of its conditions.\par +Additional permissions that are applicable to the entire Program shall\par +be treated as though they were included in this License, to the extent\par +that they are valid under applicable law. If additional permissions\par +apply only to part of the Program, that part may be used separately\par +under those permissions, but the entire Program remains governed by\par +this License without regard to the additional permissions.\par +\par + When you convey a copy of a covered work, you may at your option\par +remove any additional permissions from that copy, or from any part of\par +it. (Additional permissions may be written to require their own\par +removal in certain cases when you modify the work.) You may place\par +additional permissions on material, added by you to a covered work,\par +for which you have or can give appropriate copyright permission.\par +\par + Notwithstanding any other provision of this License, for material you\par +add to a covered work, you may (if authorized by the copyright holders of\par +that material) supplement the terms of this License with terms:\par +\par + a) Disclaiming warranty or limiting liability differently from the\par + terms of sections 15 and 16 of this License; or\par +\par + b) Requiring preservation of specified reasonable legal notices or\par + author attributions in that material or in the Appropriate Legal\par + Notices displayed by works containing it; or\par +\par + c) Prohibiting misrepresentation of the origin of that material, or\par + requiring that modified versions of such material be marked in\par + reasonable ways as different from the original version; or\par +\par + d) Limiting the use for publicity purposes of names of licensors or\par + authors of the material; or\par +\par + e) Declining to grant rights under trademark law for use of some\par + trade names, trademarks, or service marks; or\par +\par + f) Requiring indemnification of licensors and authors of that\par + material by anyone who conveys the material (or modified versions of\par + it) with contractual assumptions of liability to the recipient, for\par + any liability that these contractual assumptions directly impose on\par + those licensors and authors.\par +\par + All other non-permissive additional terms are considered "further\par +restrictions" within the meaning of section 10. If the Program as you\par +received it, or any part of it, contains a notice stating that it is\par +governed by this License along with a term that is a further\par +restriction, you may remove that term. If a license document contains\par +a further restriction but permits relicensing or conveying under this\par +License, you may add to a covered work material governed by the terms\par +of that license document, provided that the further restriction does\par +not survive such relicensing or conveying.\par +\par + If you add terms to a covered work in accord with this section, you\par +must place, in the relevant source files, a statement of the\par +additional terms that apply to those files, or a notice indicating\par +where to find the applicable terms.\par +\par + Additional terms, permissive or non-permissive, may be stated in the\par +form of a separately written license, or stated as exceptions;\par +the above requirements apply either way.\par +\par + 8. Termination.\par +\par + You may not propagate or modify a covered work except as expressly\par +provided under this License. Any attempt otherwise to propagate or\par +modify it is void, and will automatically terminate your rights under\par +this License (including any patent licenses granted under the third\par +paragraph of section 11).\par +\par + However, if you cease all violation of this License, then your\par +license from a particular copyright holder is reinstated (a)\par +provisionally, unless and until the copyright holder explicitly and\par +finally terminates your license, and (b) permanently, if the copyright\par +holder fails to notify you of the violation by some reasonable means\par +prior to 60 days after the cessation.\par +\par + Moreover, your license from a particular copyright holder is\par +reinstated permanently if the copyright holder notifies you of the\par +violation by some reasonable means, this is the first time you have\par +received notice of violation of this License (for any work) from that\par +copyright holder, and you cure the violation prior to 30 days after\par +your receipt of the notice.\par +\par + Termination of your rights under this section does not terminate the\par +licenses of parties who have received copies or rights from you under\par +this License. If your rights have been terminated and not permanently\par +reinstated, you do not qualify to receive new licenses for the same\par +material under section 10.\par +\par + 9. Acceptance Not Required for Having Copies.\par +\par + You are not required to accept this License in order to receive or\par +run a copy of the Program. Ancillary propagation of a covered work\par +occurring solely as a consequence of using peer-to-peer transmission\par +to receive a copy likewise does not require acceptance. However,\par +nothing other than this License grants you permission to propagate or\par +modify any covered work. These actions infringe copyright if you do\par +not accept this License. Therefore, by modifying or propagating a\par +covered work, you indicate your acceptance of this License to do so.\par +\par + 10. Automatic Licensing of Downstream Recipients.\par +\par + Each time you convey a covered work, the recipient automatically\par +receives a license from the original licensors, to run, modify and\par +propagate that work, subject to this License. You are not responsible\par +for enforcing compliance by third parties with this License.\par +\par + An "entity transaction" is a transaction transferring control of an\par +organization, or substantially all assets of one, or subdividing an\par +organization, or merging organizations. If propagation of a covered\par +work results from an entity transaction, each party to that\par +transaction who receives a copy of the work also receives whatever\par +licenses to the work the party's predecessor in interest had or could\par +give under the previous paragraph, plus a right to possession of the\par +Corresponding Source of the work from the predecessor in interest, if\par +the predecessor has it or can get it with reasonable efforts.\par +\par + You may not impose any further restrictions on the exercise of the\par +rights granted or affirmed under this License. For example, you may\par +not impose a license fee, royalty, or other charge for exercise of\par +rights granted under this License, and you may not initiate litigation\par +(including a cross-claim or counterclaim in a lawsuit) alleging that\par +any patent claim is infringed by making, using, selling, offering for\par +sale, or importing the Program or any portion of it.\par +\par + 11. Patents.\par +\par + A "contributor" is a copyright holder who authorizes use under this\par +License of the Program or a work on which the Program is based. The\par +work thus licensed is called the contributor's "contributor version".\par +\par + A contributor's "essential patent claims" are all patent claims\par +owned or controlled by the contributor, whether already acquired or\par +hereafter acquired, that would be infringed by some manner, permitted\par +by this License, of making, using, or selling its contributor version,\par +but do not include claims that would be infringed only as a\par +consequence of further modification of the contributor version. For\par +purposes of this definition, "control" includes the right to grant\par +patent sublicenses in a manner consistent with the requirements of\par +this License.\par +\par + Each contributor grants you a non-exclusive, worldwide, royalty-free\par +patent license under the contributor's essential patent claims, to\par +make, use, sell, offer for sale, import and otherwise run, modify and\par +propagate the contents of its contributor version.\par +\par + In the following three paragraphs, a "patent license" is any express\par +agreement or commitment, however denominated, not to enforce a patent\par +(such as an express permission to practice a patent or covenant not to\par +sue for patent infringement). To "grant" such a patent license to a\par +party means to make such an agreement or commitment not to enforce a\par +patent against the party.\par +\par + If you convey a covered work, knowingly relying on a patent license,\par +and the Corresponding Source of the work is not available for anyone\par +to copy, free of charge and under the terms of this License, through a\par +publicly available network server or other readily accessible means,\par +then you must either (1) cause the Corresponding Source to be so\par +available, or (2) arrange to deprive yourself of the benefit of the\par +patent license for this particular work, or (3) arrange, in a manner\par +consistent with the requirements of this License, to extend the patent\par +license to downstream recipients. "Knowingly relying" means you have\par +actual knowledge that, but for the patent license, your conveying the\par +covered work in a country, or your recipient's use of the covered work\par +in a country, would infringe one or more identifiable patents in that\par +country that you have reason to believe are valid.\par +\par + If, pursuant to or in connection with a single transaction or\par +arrangement, you convey, or propagate by procuring conveyance of, a\par +covered work, and grant a patent license to some of the parties\par +receiving the covered work authorizing them to use, propagate, modify\par +or convey a specific copy of the covered work, then the patent license\par +you grant is automatically extended to all recipients of the covered\par +work and works based on it.\par +\par + A patent license is "discriminatory" if it does not include within\par +the scope of its coverage, prohibits the exercise of, or is\par +conditioned on the non-exercise of one or more of the rights that are\par +specifically granted under this License. You may not convey a covered\par +work if you are a party to an arrangement with a third party that is\par +in the business of distributing software, under which you make payment\par +to the third party based on the extent of your activity of conveying\par +the work, and under which the third party grants, to any of the\par +parties who would receive the covered work from you, a discriminatory\par +patent license (a) in connection with copies of the covered work\par +conveyed by you (or copies made from those copies), or (b) primarily\par +for and in connection with specific products or compilations that\par +contain the covered work, unless you entered into that arrangement,\par +or that patent license was granted, prior to 28 March 2007.\par +\par + Nothing in this License shall be construed as excluding or limiting\par +any implied license or other defenses to infringement that may\par +otherwise be available to you under applicable patent law.\par +\par + 12. No Surrender of Others' Freedom.\par +\par + If conditions are imposed on you (whether by court order, agreement or\par +otherwise) that contradict the conditions of this License, they do not\par +excuse you from the conditions of this License. If you cannot convey a\par +covered work so as to satisfy simultaneously your obligations under this\par +License and any other pertinent obligations, then as a consequence you may\par +not convey it at all. For example, if you agree to terms that obligate you\par +to collect a royalty for further conveying from those to whom you convey\par +the Program, the only way you could satisfy both those terms and this\par +License would be to refrain entirely from conveying the Program.\par +\par + 13. Remote Network Interaction; Use with the GNU General Public License.\par +\par + Notwithstanding any other provision of this License, if you modify the\par +Program, your modified version must prominently offer all users\par +interacting with it remotely through a computer network (if your version\par +supports such interaction) an opportunity to receive the Corresponding\par +Source of your version by providing access to the Corresponding Source\par +from a network server at no charge, through some standard or customary\par +means of facilitating copying of software. This Corresponding Source\par +shall include the Corresponding Source for any work covered by version 3\par +of the GNU General Public License that is incorporated pursuant to the\par +following paragraph.\par +\par + Notwithstanding any other provision of this License, you have\par +permission to link or combine any covered work with a work licensed\par +under version 3 of the GNU General Public License into a single\par +combined work, and to convey the resulting work. The terms of this\par +License will continue to apply to the part which is the covered work,\par +but the work with which it is combined will remain governed by version\par +3 of the GNU General Public License.\par +\par + 14. Revised Versions of this License.\par +\par + The Free Software Foundation may publish revised and/or new versions of\par +the GNU Affero General Public License from time to time. Such new versions\par +will be similar in spirit to the present version, but may differ in detail to\par +address new problems or concerns.\par +\par + Each version is given a distinguishing version number. If the\par +Program specifies that a certain numbered version of the GNU Affero General\par +Public License "or any later version" applies to it, you have the\par +option of following the terms and conditions either of that numbered\par +version or of any later version published by the Free Software\par +Foundation. If the Program does not specify a version number of the\par +GNU Affero General Public License, you may choose any version ever published\par +by the Free Software Foundation.\par +\par + If the Program specifies that a proxy can decide which future\par +versions of the GNU Affero General Public License can be used, that proxy's\par +public statement of acceptance of a version permanently authorizes you\par +to choose that version for the Program.\par +\par + Later license versions may give you additional or different\par +permissions. However, no additional obligations are imposed on any\par +author or copyright holder as a result of your choosing to follow a\par +later version.\par +\par + 15. Disclaimer of Warranty.\par +\par + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\par +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\par +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\par +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\par +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\par +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\par +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\par +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\par +\par + 16. Limitation of Liability.\par +\par + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\par +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\par +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\par +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\par +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\par +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\par +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\par +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\par +SUCH DAMAGES.\par +\par + 17. Interpretation of Sections 15 and 16.\par +\par + If the disclaimer of warranty and limitation of liability provided\par +above cannot be given local legal effect according to their terms,\par +reviewing courts shall apply local law that most closely approximates\par +an absolute waiver of all civil liability in connection with the\par +Program, unless a warranty or assumption of liability accompanies a\par +copy of the Program in return for a fee.\par +\par + END OF TERMS AND CONDITIONS\par +\par + How to Apply These Terms to Your New Programs\par +\par + If you develop a new program, and you want it to be of the greatest\par +possible use to the public, the best way to achieve this is to make it\par +free software which everyone can redistribute and change under these terms.\par +\par + To do so, attach the following notices to the program. It is safest\par +to attach them to the start of each source file to most effectively\par +state the exclusion of warranty; and each file should have at least\par +the "copyright" line and a pointer to where the full notice is found.\par +\par + \par + Copyright (C) \par +\par + This program is free software: you can redistribute it and/or modify\par + it under the terms of the GNU Affero General Public License as published by\par + the Free Software Foundation, either version 3 of the License, or\par + (at your option) any later version.\par +\par + This program is distributed in the hope that it will be useful,\par + but WITHOUT ANY WARRANTY; without even the implied warranty of\par + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\par + GNU Affero General Public License for more details.\par +\par + You should have received a copy of the GNU Affero General Public License\par + along with this program. If not, see <{{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{https://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs22 >.\par +\par +Also add information on how to contact you by electronic and paper mail.\par +\par + If your software can interact with users remotely through a computer\par +network, you should also make sure that it provides a way for users to\par +get its source. For example, if your program is a web application, its\par +interface could display a "Source" link that leads users to an archive\par +of the code. There are many ways you could offer source, and different\par +solutions will be better for different programs; see section 13 for the\par +specific requirements.\par +\par + You should also get your employer (if you work as a programmer) or school,\par +if any, to sign a "copyright disclaimer" for the program, if necessary.\par +For more information on this, and how to apply and follow the GNU AGPL, see\par +<{{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/"}}{\fldrslt{https://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs22 >.\par +\par +} + \ No newline at end of file diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/grafana-enterprise.rtf b/pkg/build/daggerbuild/scripts/packaging/windows/grafana-enterprise.rtf new file mode 100644 index 00000000000..2f88547d474 --- /dev/null +++ b/pkg/build/daggerbuild/scripts/packaging/windows/grafana-enterprise.rtf @@ -0,0 +1,1502 @@ +{\rtf1\ansi\ansicpg1252\uc0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deff0\adeff0{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f2\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}{\f3\fnil\fcharset0 Lemon;}{\f4\fnil\fcharset0 Helvetica Neue +;}{\f5\fnil\fcharset0 Georgia;}}{\colortbl;\red0\green0\blue0;\red102\green102\blue102;}{\stylesheet{\s0\snext0\sqformat\spriority0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1 Normal;}{\s1\sbasedon0\snext0\styrsid15694742 + +\sqformat\spriority0\keep\keepn\fi0\sb480\sa120\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs48\ltrch\b\i0\fs48\f0\strike0\ulnone\cf1 heading 1;}{\s2\sbasedon0\snext0\styrsid15694742\sqformat\spriority0 +\keep\keepn\fi0\sb360\sa80\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs36\ltrch\b\i0\fs36\f0\strike0\ulnone\cf1 heading 2;}{\s3\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb280\sa80 +\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs28\ltrch\b\i0\fs28\f0\strike0\ulnone\cf1 heading 3;}{\s4\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb240\sa40\aspalpha\aspnum +\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs24\ltrch\b\i0\fs24\f0\strike0\ulnone\cf1 heading 4;}{\s5\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb220\sa40\aspalpha\aspnum\adjustright\widctlpar +\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs22\ltrch\b\i0\fs22\f0\strike0\ulnone\cf1 heading 5;}{\s6\sbasedon0\snext0\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb200\sa40\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0 +\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs20\ltrch\b\i0\fs20\f0\strike0\ulnone\cf1 heading 6;}{\*\cs10\additive\ssemihidden\spriority0 Default Paragraph Font;}{\s15\sbasedon0\snext15\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb480\sa120 +\aspalpha\aspnum\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab\ai0\af0\afs72\ltrch\b\i0\fs72\f0\strike0\ulnone\cf1 Title;}{\s16\sbasedon0\snext16\styrsid15694742\sqformat\spriority0\keep\keepn\fi0\sb360\sa80\aspalpha\aspnum + +\adjustright\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai\af5\afs48\ltrch\b0\i\fs48\loch\af5\dbch\af5\hich\f5\strike0\ulnone\cf2 Subtitle;}}{\*\rsidtbl\rsid10976062}{\*\generator Aspose.Words for Java 13.12.0.0;}{\info\version1\edmins0\nofpages1\nofwords0\nofchars0\nofcharsws0}{\mmathPr\mbrkBin0\mbrkBinSub0\mdefJc1\mdispDef1\minterSp0\mintLim0\mintraSp0\mlMargin0\mmathFont0\mnaryLim1\mpostSp0\mpreSp0\mrMargin0\msmallFrac0\mwrapIndent1440\mwrapRight0} +\deflang1033\deflangfe2052\adeflang1025\jexpand\showxmlerrors1\validatexml1{\*\wgrffmtfilter 013f}\viewkind1\viewscale100\fet0\ftnbj\aenddoc\ftnrstcont\aftnrstcont\ftnnar\aftnnrlc\widowctrl\nospaceforul\nolnhtadjtbl\alntblind\lyttblrtgr\dntblnsbdb\noxlattoyen +\wrppunct\nobrkwrptbl\expshrtn\snaptogridincell\asianbrkrule\htmautsp\noultrlspc\useltbaln\splytwnine\ftnlytwnine\lytcalctblwd\allowfieldendsel\lnbrkrule\nouicompat\nofeaturethrottle1\formshade\nojkernpunct\dghspace180\dgvspace180\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1 +\dgmargin\pgbrdrhead\pgbrdrfoot\sectd\sectlinegrid360\pgwsxn12240\pghsxn15840\marglsxn720\margrsxn720\margtsxn1440\margbsxn1440\guttersxn0\headery708\footery708\colsx708\ltrsect{\header\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw +\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1\par}}{\footer\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha +\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1\par}}\pard +\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl +\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par} +\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PLEASE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 READ}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CAREFULLY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 "), }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WHICH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 CONSTITUTES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LEGALLY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BINDING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GOVERNS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 ALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOUR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WHICH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCLUDED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (\u8220 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 \u8221 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 + +\dbch\af3\hich\f3\strike0\ulnone\cf1 THAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PROVIDED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OBJECT}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CODE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FORMAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INSTALLING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 USING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GOVERNED}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FREE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 VERSION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ENTERPRISE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 ARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ASSENTING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 IF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NOT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NOT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 INSTALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 GOVERNED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IF}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 INSTALLING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ON}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BEHALF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LEGAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ENTITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 REPRESENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 WARRANT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 HAVE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ACTUAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AUTHORITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ON}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BEHALF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ENTITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar +\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Posted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Date}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 : }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Jan}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 10, 2020}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 + +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entered}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 into}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 between}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Inc}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 (\u8220 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ") }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 legal}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 behalf}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whom}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 acting}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ").}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OBJECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CODE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 END}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESTRICTIONS} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIRD}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 PARTY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OPEN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOURCE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl +\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par} +\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 End}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 User}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conditions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Section}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 hereby}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grants}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 AT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CHARGE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 so}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 long}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 you}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provision}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 free}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 features}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 functions}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Enterprise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 + +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Reservation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Rights}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ; }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Restrictions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 As}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 between}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 licensors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 own}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 title}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 interest}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 expressly}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 set}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 forth}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Sections}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 + +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 no}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 granted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 under}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 implication}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 estoppel}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 agree}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 : (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 i}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reverse}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 engineer}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 decompile}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 decrypt}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 disassemble}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reduce}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 portion}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 thereof}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 only}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 extent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 restriction}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 prohibited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 , (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ii}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 expressly}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 permitted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Section}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 1.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 above}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transfer}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sell}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 rent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 lease}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 distribute}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sublicense}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 loan}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transfer}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whole}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 part}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ; (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 iii}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 providing}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 time}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 sharing}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 services}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 service}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 service}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 bureau}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 services}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 part}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 an}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 application}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 services}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 provider}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 service}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 offering}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 collectively}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , "}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ") }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 obtaining}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 access}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 features}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 functions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 primary}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reason}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 substantial}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 motivation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 users}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 access}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 /}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ("}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Prohibited} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "); (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 iv}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 circumvent}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limitations}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 format}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 imposed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 preserved}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Key}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 v}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 alter}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 remove}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Marks}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Notices}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 If}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 question}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 whether}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 specific}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 constitutes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Prohibited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SaaS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Offering}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 interested}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 obtaining}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 + +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 '}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 s}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 permission}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 engage}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 distribution}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 please}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contact}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sales}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 @}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grafana}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 com}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.3 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 libraries}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 components}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 utilities} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 collectively}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "), }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 identified}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 website}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 designated}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Notwithstanding} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 anything}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contrary}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 herein}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 conditions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 extent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 required}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 licensor} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 restrict}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 rights}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 granted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 hereunder}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 additional}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 rights}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ). }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 To}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 extent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 condition}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conflicts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 govern}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 respect}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 only}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 also}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 separately}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provide} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 you}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 certain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 licensed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 governed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 open}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1 +\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TERMINATION}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 automatically}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terminate}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whether}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 receive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 notice}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 from}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 if}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provisions}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Post}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Upon}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reason}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 promptly}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 cease}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 format}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 For}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 avoidance}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 doubt}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 affect}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 either}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 formats}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 made}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 available}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 under}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Apache}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Version}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.0.}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 + +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 2.3 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Survival}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Sections}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1.2, 2.2. 2.3, 3 } +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 4 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 survive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 termination}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 expiration}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 3. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DISCLAIMER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANTIES}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LIMITATION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LIABILITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 + +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 3.1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Disclaimer}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Warranties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAXIMUM}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 EXTENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERMITTED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 UNDER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 APPLICABLE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LAW}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PROVIDED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AS}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITHOUT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 WARRANTY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 KIND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ITS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSORS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAKE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANTIES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 WHETHER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EXPRESSED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IMPLIED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 STATUTORY}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 REGARDING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 RELATING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LAB}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MAXIMUM}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EXTENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERMITTED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 UNDER}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 APPLICABLE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LAW}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ITS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSORS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SPECIFICALLY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DISCLAIM}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 ALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IMPLIED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANTIES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MERCHANTABILITY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FITNESS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PARTICULAR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PURPOSE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NON}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INFRINGEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESPECT}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 AND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESPECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOREGOING}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FURTHER}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DOES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NOT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WARRANT}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 RESULTS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THAT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WILL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 ERROR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FREE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 UNINTERRUPTED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard +\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 3.2 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Limitation}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Liability}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IN}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EVENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 SHALL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ITS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LICENSORS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 LIABLE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 YOU}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIRD}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PARTY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DIRECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INDIRECT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DAMAGES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCLUDING} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITHOUT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LIMITATION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LOSS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PROFITS}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LOSS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BUSINESS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INTERRUPTION}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 LOSS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DATA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 COST}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SUBSTITUTE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GOODS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SERVICES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FOR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SPECIAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCIDENTAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONSEQUENTIAL}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DAMAGES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ANY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 KIND}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONNECTION}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WITH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ARISING}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OUT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INABILITY}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 SOFTWARE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERFORMANCE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 FAILURE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TO}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 PERFORM}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THIS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AGREEMENT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 WHETHER} + +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ALLEGED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 AS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BREACH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 CONTRACT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OR}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 TORTIOUS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 CONDUCT}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 INCLUDING} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 NEGLIGENCE}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 EVEN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 IF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 GRAFANA}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 LABS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 HAS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 BEEN}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ADVISED}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 THE}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 POSSIBILITY}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 OF}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 SUCH}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DAMAGES}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar +\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 4. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 MISCELLANEOUS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 completely}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 exclusively}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 states}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entire}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 agreement}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 regarding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 matter}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 herein}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 it}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 supersedes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 govern}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 prior}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 proposals}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 agreements}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 communications}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 between}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 oral}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 written}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 regarding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 subject}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 matter}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modified}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 from}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 time}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 time}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modifications}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 effective}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 upon}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Posted}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Date}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 set}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 forth}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 top}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modified}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 If}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provision}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 hereof}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 held}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 unenforceable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 will}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 continue}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 said}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provision}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 interpreted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 reflect}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 original}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 intent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contractual}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 obligation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 arising} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 out}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 it}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 governed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 exclusively} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 New}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 York}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 This}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 governed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1980 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 UN}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Convention}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contracts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 International}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Sale}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Goods}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 All}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 disputes}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 arising}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 out}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 existence}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 validity}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 resolved}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 courts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 jurisdiction}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 New}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 York}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 City}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 USA}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 except}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 mandatory}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provides}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 courts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 another}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 location}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 United}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 States}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 jurisdiction}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 parties}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 hereby}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 irrevocably}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 waive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 claims}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 defenses}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 either}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 might}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 otherwise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 action}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 proceeding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 courts}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 based}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 upon}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 alleged}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 lack}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 personal}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 jurisdiction}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 improper}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 venue}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 forum}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conveniens}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 similar}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 claim}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 defense}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 A}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 threatened}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 breach}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Section}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 cause}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 irreparable}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 harm}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 damages}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provide}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 adequate}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 relief}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 therefore}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entitled}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 seek}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 injunctive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 relief}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 being}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 required}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 post}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 bond}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 assign}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 operation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 law}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 merger}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 acquisition}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ), }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 whole}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 part}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 third}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 prior}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 written}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 consent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 withheld}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 granted}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 its}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sole}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 absolute}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 discretion} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 assignment}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 violation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 preceding}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sentence}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 void}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 . }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Notices}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 may}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 also}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 legal}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 @}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 com}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb +\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard +\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5. }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 DEFINITIONS}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par} +\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 The}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 following}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 have}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 meanings}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ascribed}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 :}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0 +\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.1 "} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliate}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 respect}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 controls}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 controlled}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 which}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 under}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 common}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 control}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 party}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 "}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 control}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ownership}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 at}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 least}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 fifty}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 percent}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (50%) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 outstanding}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 voting} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shares}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 contractual}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 establish}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 policy}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 manage}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 operations}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 entity}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0 + +\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0 +\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.2 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 commercially}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 free}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 version}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Enterprise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Enterprise}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 + +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 5.3 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 exclusive}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transferable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 fully}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 paid}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 up}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 royalty}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 free}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 license}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 without}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 grant}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 authorize}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sublicenses}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 solely}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 internal}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 business}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 operations} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 i}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 install}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 applicable}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Features}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Functions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ii}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 permit}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contractors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliates}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 set}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 forth}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 (}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 i}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 ) }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 above}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 provided}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contractors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 must}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 solely}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 benefit}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 /}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 benefit}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Your}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliates}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 You}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 shall}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 be}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 responsible}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 acts}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 omissions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 such}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Contractors}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Affiliates}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 in}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 connection}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 with}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 their}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 use}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 are}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 contrary}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 terms}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conditions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 this}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Agreement}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 + +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 5.4 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 Key}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 sequence}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 bytes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 JSON}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 blob}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 that}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 used}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 enable}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 certain}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 features}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 functions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum +\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 + +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.5 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Marks}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 Notices}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 all}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 trademarks}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 trade}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 names}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 logos}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 notices}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 present}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 on}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Documentation}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 as}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 originally}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 + +\hich\f3\strike0\ulnone\cf1 provided}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 by}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Grafana}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Labs}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1 + +\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.6 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Non}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 -}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 production}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Environment}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means} +{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 an}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 environment}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 development}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 + +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 testing}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 quality}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 assurance}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 where}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 is}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 used}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 production}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 purposes}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.7 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 any}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 form}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 resulting}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 from}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 mechanical}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 transformation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 + +\dbch\af3\hich\f3\strike0\ulnone\cf1 or}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 translation}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 form}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 compiled}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 object}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 generated}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 documentation}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 conversions}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 other}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 media}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 types}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0 +\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0 +\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.8 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Code}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 preferred}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 form}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 of}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 computer}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 for}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 making}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 modifications}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 including}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 but}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 not}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 limited}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 software}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 code}{ +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 documentation}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 source}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 , }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 configuration}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 files}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 .}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24 +\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\insrsid10976062\strike0\ulnone\cf1\par}\pard\plain\itap0\s0\ilvl0\fi0\sb0\sa0\aspalpha\aspnum\adjustright\brdrt\brdrl\brdrb\brdrr\brdrbtw\brdrbar +\widctlpar\ltrpar\li0\lin0\ri0\rin0\ql\faauto\sl240\slmult1\rtlch\ab0\ai0\af0\afs24\ltrch\b0\i0\fs24\f0\strike0\ulnone\cf1{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 5.9 "}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3 +\dbch\af3\hich\f3\strike0\ulnone\cf1 Subscription}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 " }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 means}{\rtlch\ab0\ai0\af3\afs14 + +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 right}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 receive}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14 +\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Support}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Services}{ + +\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 and}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 + +\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 a}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0 +\ulnone\cf1 License}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 to}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3 +\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 the}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14 +\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Commercial}{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 }{\rtlch\ab0\ai0\af3\afs14\ltrch\b0\i0\fs14\loch\af3\dbch\af3\hich\f3\strike0\ulnone\cf1 Software}{\rtlch\ab0\ai0\af4\afs22 +\ltrch\b0\i0\fs22\loch\af4\dbch\af4\hich\f4\insrsid10976062\strike0\ulnone\cf1\par}{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef0{\lsdlockedexcept\lsdqformat1 Normal;\lsdqformat1 heading 1;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 2;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 3 +;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 4;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 5;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 6;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 7;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 8 +;\lsdsemihidden1\lsdunhideused1\lsdqformat1 heading 9;\lsdsemihidden1\lsdunhideused1\lsdqformat1 caption;\lsdqformat1 Title;\lsdqformat1 Subtitle;\lsdqformat1 Strong;\lsdqformat1 Emphasis;\lsdsemihidden1\lsdpriority99 Placeholder Text;\lsdqformat1\lsdpriority1 No Spacing +;\lsdpriority60 Light Shading;\lsdpriority61 Light List;\lsdpriority62 Light Grid;\lsdpriority63 Medium Shading 1;\lsdpriority64 Medium Shading 2;\lsdpriority65 Medium List 1;\lsdpriority66 Medium List 2;\lsdpriority67 Medium Grid 1;\lsdpriority68 Medium Grid 2 +;\lsdpriority69 Medium Grid 3;\lsdpriority70 Dark List;\lsdpriority71 Colorful Shading;\lsdpriority72 Colorful List;\lsdpriority73 Colorful Grid;\lsdpriority60 Light Shading Accent 1;\lsdpriority61 Light List Accent 1;\lsdpriority62 Light Grid Accent 1;\lsdpriority63 Medium Shading 1 Accent 1 +;\lsdpriority64 Medium Shading 2 Accent 1;\lsdpriority65 Medium List 1 Accent 1;\lsdsemihidden1\lsdpriority99 Revision;\lsdqformat1\lsdpriority34 List Paragraph;\lsdqformat1\lsdpriority29 Quote;\lsdqformat1\lsdpriority30 Intense Quote;\lsdpriority66 Medium List 2 Accent 1 +;\lsdpriority67 Medium Grid 1 Accent 1;\lsdpriority68 Medium Grid 2 Accent 1;\lsdpriority69 Medium Grid 3 Accent 1;\lsdpriority70 Dark List Accent 1;\lsdpriority71 Colorful Shading Accent 1;\lsdpriority72 Colorful List Accent 1;\lsdpriority73 Colorful Grid Accent 1 +;\lsdpriority60 Light Shading Accent 2;\lsdpriority61 Light List Accent 2;\lsdpriority62 Light Grid Accent 2;\lsdpriority63 Medium Shading 1 Accent 2;\lsdpriority64 Medium Shading 2 Accent 2;\lsdpriority65 Medium List 1 Accent 2;\lsdpriority66 Medium List 2 Accent 2 +;\lsdpriority67 Medium Grid 1 Accent 2;\lsdpriority68 Medium Grid 2 Accent 2;\lsdpriority69 Medium Grid 3 Accent 2;\lsdpriority70 Dark List Accent 2;\lsdpriority71 Colorful Shading Accent 2;\lsdpriority72 Colorful List Accent 2;\lsdpriority73 Colorful Grid Accent 2 +;\lsdpriority60 Light Shading Accent 3;\lsdpriority61 Light List Accent 3;\lsdpriority62 Light Grid Accent 3;\lsdpriority63 Medium Shading 1 Accent 3;\lsdpriority64 Medium Shading 2 Accent 3;\lsdpriority65 Medium List 1 Accent 3;\lsdpriority66 Medium List 2 Accent 3 +;\lsdpriority67 Medium Grid 1 Accent 3;\lsdpriority68 Medium Grid 2 Accent 3;\lsdpriority69 Medium Grid 3 Accent 3;\lsdpriority70 Dark List Accent 3;\lsdpriority71 Colorful Shading Accent 3;\lsdpriority72 Colorful List Accent 3;\lsdpriority73 Colorful Grid Accent 3 +;\lsdpriority60 Light Shading Accent 4;\lsdpriority61 Light List Accent 4;\lsdpriority62 Light Grid Accent 4;\lsdpriority63 Medium Shading 1 Accent 4;\lsdpriority64 Medium Shading 2 Accent 4;\lsdpriority65 Medium List 1 Accent 4;\lsdpriority66 Medium List 2 Accent 4 +;\lsdpriority67 Medium Grid 1 Accent 4;\lsdpriority68 Medium Grid 2 Accent 4;\lsdpriority69 Medium Grid 3 Accent 4;\lsdpriority70 Dark List Accent 4;\lsdpriority71 Colorful Shading Accent 4;\lsdpriority72 Colorful List Accent 4;\lsdpriority73 Colorful Grid Accent 4 +;\lsdpriority60 Light Shading Accent 5;\lsdpriority61 Light List Accent 5;\lsdpriority62 Light Grid Accent 5;\lsdpriority63 Medium Shading 1 Accent 5;\lsdpriority64 Medium Shading 2 Accent 5;\lsdpriority65 Medium List 1 Accent 5;\lsdpriority66 Medium List 2 Accent 5 +;\lsdpriority67 Medium Grid 1 Accent 5;\lsdpriority68 Medium Grid 2 Accent 5;\lsdpriority69 Medium Grid 3 Accent 5;\lsdpriority70 Dark List Accent 5;\lsdpriority71 Colorful Shading Accent 5;\lsdpriority72 Colorful List Accent 5;\lsdpriority73 Colorful Grid Accent 5 + +;\lsdpriority60 Light Shading Accent 6;\lsdpriority61 Light List Accent 6;\lsdpriority62 Light Grid Accent 6;\lsdpriority63 Medium Shading 1 Accent 6;\lsdpriority64 Medium Shading 2 Accent 6;\lsdpriority65 Medium List 1 Accent 6;\lsdpriority66 Medium List 2 Accent 6 +;\lsdpriority67 Medium Grid 1 Accent 6;\lsdpriority68 Medium Grid 2 Accent 6;\lsdpriority69 Medium Grid 3 Accent 6;\lsdpriority70 Dark List Accent 6;\lsdpriority71 Colorful Shading Accent 6;\lsdpriority72 Colorful List Accent 6;\lsdpriority73 Colorful Grid Accent 6 +;\lsdqformat1\lsdpriority19 Subtle Emphasis;\lsdqformat1\lsdpriority21 Intense Emphasis;\lsdqformat1\lsdpriority31 Subtle Reference;\lsdqformat1\lsdpriority32 Intense Reference;\lsdqformat1\lsdpriority33 Book Title;\lsdsemihidden1\lsdunhideused1\lsdpriority37 Bibliography +;\lsdsemihidden1\lsdunhideused1\lsdqformat1\lsdpriority39 TOC Heading;}}} diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/grafana-svc.xml b/pkg/build/daggerbuild/scripts/packaging/windows/grafana-svc.xml new file mode 100755 index 00000000000..98e9589a7da --- /dev/null +++ b/pkg/build/daggerbuild/scripts/packaging/windows/grafana-svc.xml @@ -0,0 +1,9 @@ + + Grafana + Grafana Server + This service runs Grafana + %BASE%\bin\grafana.exe + server --homepath="%BASE%" + + + diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/grafana.nsis b/pkg/build/daggerbuild/scripts/packaging/windows/grafana.nsis new file mode 100644 index 00000000000..dae306c7ffb --- /dev/null +++ b/pkg/build/daggerbuild/scripts/packaging/windows/grafana.nsis @@ -0,0 +1,139 @@ +Unicode true + +!define HELPURL "https://github.com/grafana/grafana" +!define ABOUTURL "https://grafana.com/grafana/" + +RequestExecutionLevel admin + +InstallDir $PROGRAMFILES64\GrafanaLabs\Grafana + +Outfile "grafana-setup.exe" +Name "${APPNAME}" +!if ${APPNAME} == "GrafanaOSS" + !define CONFLICT_APP "GrafanaEnterprise" + !define CONFLICT_APP_NAME "Grafana Enterprise" +!else + !define CONFLICT_APP "GrafanaOSS" + !define CONFLICT_APP_NAME "Grafana OSS" +!endif + +# Branding / theming +SetFont Arial 10 +AddBrandingImage left 100u + +!define MUI_PAGE_HEADER_TEXT "Install ${APPNAME}" +!define MUI_UNCONFIRMPAGE_TEXT_TOP "Warning: Uninstalling Grafana" + +# Modern UI2 +!include MUI2.nsh + +# Installer pages +!insertmacro MUI_PAGE_LICENSE "${LICENSE}" +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES + +# Uninstaller pages +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +!insertmacro MUI_LANGUAGE "English" + +Function .onInit + ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${CONFLICT_APP}" "DisplayName" + IfErrors NoConflictPresent ConflictPresent + ConflictPresent: + Pop $0 + MessageBox MB_OK "${CONFLICT_APP_NAME} is already installed. Please uninstall it before continuing." + Abort + NoConflictPresent: + Pop $0 +FunctionEnd + +; The directory page allows the user to set the install directory +; Page directory + +Section + nsExec::ExecToLog 'sc stop "Grafana"' + Pop $0 + + SetOutPath $INSTDIR + WriteUninstaller "$INSTDIR\uninstall.exe" + CreateShortcut "$SMPROGRAMS\Uninstall Grafana.lnk" "$INSTDIR\uninstall.exe" + + # Install the Grafana program files + File grafana-svc.exe + File grafana-svc.xml + File grafana/VERSION + File grafana/LICENSE + File grafana/README.md + File grafana/NOTICE.md + File winimg/grafana_icon.ico + File /r grafana/bin + File /r grafana/conf + File /r grafana/public + + # Add registry keys for "Add or Remove Programs" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$\"$INSTDIR\grafana_icon.ico$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "Publisher" "$\"https://grafana.com$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "HelpLink" "$\"${HELPURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" + + # There is no option for modifying or repairing the install + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1 + + # Stop and uninstall the Grafana service if one already exists + nsExec::ExecToLog '$INSTDIR\grafana-svc.exe stop' + Pop $0 + + nsExec::ExecToLog '$INSTDIR\grafana-svc.exe uninstall' + Pop $0 + + # Install the Grafana service + nsExec::ExecToLog '$INSTDIR\grafana-svc.exe install' + Pop $0 + + # Start the Grafana service + nsExec::ExecToLog '$INSTDIR\grafana-svc.exe start' + Pop $0 +SectionEnd + +; Page instfiles + +Section Uninstall + DetailPrint "Uninstalling Grafana" + # Remove the shortcuts + delete "$SMPROGRAMS\Uninstall Grafana.lnk" + # Stop and uninstall the Grafana service if one already exists + nsExec::ExecToLog '$INSTDIR\grafana-svc.exe stop' + Pop $0 + + nsExec::ExecToLog '$INSTDIR\grafana-svc.exe uninstall' + Pop $0 + + # Install the Grafana program files + DELETE $INSTDIR\grafana-svc.exe + DELETE $INSTDIR\grafana-svc.xml + DELETE $INSTDIR\grafana\VERSION + DELETE $INSTDIR\LICENSE + DELETE $INSTDIR\README.md + DELETE $INSTDIR\NOTICE.md + DELETE $INSTDIR\grafana_icon.ico + RMDIR /r $INSTDIR\bin + RMDIR /r $INSTDIR\public + RMDIR /r $INSTDIR\plugins-bundled + # We are intentionally not removing the "conf" or "data" directories. + + # Always remove the uninstaller as the last step + delete $INSTDIR\uninstall.exe + + # Remove the $INSTDIR; this command will not succeed if the $INSTDIR is not empty. + # This is a good thing, as we want to loosely preserve the grafana.db and logs generated from previous installs. + # In the future we should consider giving the user the option to delete the grafana.db and logs in the uninstaller. + RMDIR $INSTDIR + + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" +SectionEnd diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_dialog_background.bmp b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_dialog_background.bmp new file mode 100755 index 00000000000..1975e7a492e Binary files /dev/null and b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_dialog_background.bmp differ diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_dialog_background.png b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_dialog_background.png new file mode 100755 index 00000000000..ab262097128 Binary files /dev/null and b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_dialog_background.png differ diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_icon.ico b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_icon.ico new file mode 100755 index 00000000000..6f13cb3210a Binary files /dev/null and b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_icon.ico differ diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner.bmp b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner.bmp new file mode 100755 index 00000000000..b4faabb92de Binary files /dev/null and b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner.bmp differ diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner.png b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner.png new file mode 100755 index 00000000000..905d54414f2 Binary files /dev/null and b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner.png differ diff --git a/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner_white.bmp b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner_white.bmp new file mode 100755 index 00000000000..c72380151d2 Binary files /dev/null and b/pkg/build/daggerbuild/scripts/packaging/windows/winimg/grafana_top_banner_white.bmp differ diff --git a/pkg/build/daggerbuild/stringutil/random.go b/pkg/build/daggerbuild/stringutil/random.go new file mode 100644 index 00000000000..a8ef2f86996 --- /dev/null +++ b/pkg/build/daggerbuild/stringutil/random.go @@ -0,0 +1,17 @@ +package stringutil + +import ( + "math/rand" + "time" +) + +var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func RandomString(n int) string { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + b := make([]rune, n) + for i := range b { + b[i] = letters[r.Intn(len(letters))] + } + return string(b) +} diff --git a/pkg/build/daggerbuild/targz/build.go b/pkg/build/daggerbuild/targz/build.go new file mode 100644 index 00000000000..abc61a7b068 --- /dev/null +++ b/pkg/build/daggerbuild/targz/build.go @@ -0,0 +1,61 @@ +package targz + +import ( + "path" + + "dagger.io/dagger" +) + +func NewMappedDir(path string, directory *dagger.Directory) MappedDirectory { + return MappedDirectory{path: path, directory: directory} +} + +type MappedDirectory struct { + path string + directory *dagger.Directory +} + +type MappedFile struct { + path string + file *dagger.File +} + +func NewMappedFile(path string, file *dagger.File) MappedFile { + return MappedFile{path: path, file: file} +} + +type Opts struct { + // Root is the root folder that holds all of the packaged data. + // It is common for targz packages to have a root folder. + // This should equal something like `grafana-9.4.1`. + Root string + + // A map of directory paths relative to the root, like 'bin', 'public', 'npm-artifacts' + // to dagger directories. + Directories []MappedDirectory + Files []MappedFile +} + +func Build(packager *dagger.Container, opts *Opts) *dagger.File { + root := opts.Root + + packager = packager. + WithWorkdir("/src") + + paths := []string{} + for _, v := range opts.Files { + path := path.Join(root, v.path) + packager = packager.WithMountedFile(path, v.file) + paths = append(paths, path) + } + + for _, v := range opts.Directories { + path := path.Join(root, v.path) + packager = packager.WithMountedDirectory(path, v.directory) + paths = append(paths, path) + } + + packager = packager.WithExec(append([]string{"tar", "-czf", "/package.tar.gz"}, paths...)) + + return packager.File("/package.tar.gz") +} diff --git a/pkg/build/daggerbuild/versions/opts.go b/pkg/build/daggerbuild/versions/opts.go new file mode 100644 index 00000000000..00de9ea2d8b --- /dev/null +++ b/pkg/build/daggerbuild/versions/opts.go @@ -0,0 +1,102 @@ +package versions + +import ( + "github.com/Masterminds/semver" +) + +type Nullable[T any] struct { + Value T + IsSet bool +} + +func NewNullable[T any](val T) Nullable[T] { + return Nullable[T]{ + Value: val, + IsSet: true, + } +} + +// Options holds the general options for each version that may be different. +type Options struct { + Constraint Nullable[string] + // CombinedExecutable was introduced in Grafana 9.4; it combined the `grafana-server` and `grafana-cli` commands into one `grafana` executable. + CombinedExecutable Nullable[bool] + // DebPreRM defines the 'prerm' script in the debian installer, introduced by this PR: https://github.com/grafana/grafana/pull/59580 in v9.5.0. Versions before v9.5.0 do not have the 'prerm' script in the grafana package. + DebPreRM Nullable[bool] + + // Automcplete (in packaging/autocomplete) was added in Grafana 9.4.0, so we should not try to include this folder in the package before then. + Autocomplete Nullable[bool] +} + +func MergeNullables[T any](values ...Nullable[T]) Nullable[T] { + val := values[0] + for _, v := range values { + if v.IsSet { + val = v + } + } + + return val +} + +func Merge(from, to Options) Options { + return Options{ + Constraint: from.Constraint, + CombinedExecutable: MergeNullables(from.CombinedExecutable, to.CombinedExecutable), + DebPreRM: MergeNullables(from.DebPreRM, to.DebPreRM), + Autocomplete: MergeNullables(from.Autocomplete, to.Autocomplete), + } +} + +// LatestOptions are the options that apply to the latest version of Grafana +var LatestOptions = Options{ + Autocomplete: NewNullable(true), + CombinedExecutable: NewNullable(true), + DebPreRM: NewNullable(true), +} + +// OptionsList is a list of semver filters and corresponding options. +// If multiple constraints match the given semver, then they are merged in the order they appear, where later entries override earlier ones. +// These options should only exist if they are contrary to the LatestOptions, as the applicable options will be merged with it. In the event of any conflicts, the options in this list will override those in the LatestOptions. +var OptionsList = []Options{ + { + Constraint: NewNullable("< 9.5.0-0"), + DebPreRM: NewNullable(false), + }, + { + Constraint: NewNullable("< 9.3.7-0"), + CombinedExecutable: NewNullable(false), + }, + { + Constraint: NewNullable("< 9.4.0-0"), // The -0 includes prereleases. Without it, prereleases are ignored from comparison. I don't really know why??? but it is what it is. + Autocomplete: NewNullable(false), + }, + { + Constraint: NewNullable(">= 9.2.11-0, < 9.3.0-0"), // The combined executable change was backported to 9.2.x at v9.2.11 + CombinedExecutable: NewNullable(true), + }, +} + +// OptionsFor returns the options found for a given version. If no versions that matched were found, then the result of "LatestOptions" is returned. +func OptionsFor(version string) Options { + opts := LatestOptions + smversion, err := semver.NewVersion(version) + if err != nil { + return opts + } + + for _, v := range OptionsList { + c, err := semver.NewConstraint(v.Constraint.Value) + if err != nil { + continue + } + if !c.Check(smversion) { + continue + } + + // This version matches the semver, override all options set in 'opts' with those set in 'v' + opts = Merge(opts, v) + } + + return opts +} diff --git a/pkg/build/daggerbuild/versions/opts_test.go b/pkg/build/daggerbuild/versions/opts_test.go new file mode 100644 index 00000000000..93244f8ad0e --- /dev/null +++ b/pkg/build/daggerbuild/versions/opts_test.go @@ -0,0 +1,86 @@ +package versions_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/daggerbuild/versions" +) + +func TestOptsFor(t *testing.T) { + t.Run("v9.3.0 should not have combined executables", func(t *testing.T) { + opts := versions.OptionsFor("v9.3.0") + + if opts.CombinedExecutable.IsSet != true { + t.Errorf("CombinedExecutable should be set for v9.3.0") + } + if opts.CombinedExecutable.Value != false { + t.Errorf("CombinedExecutable should be false for v9.3.0") + } + }) + t.Run("v9.3.0 should not have packaging/autocomplete", func(t *testing.T) { + opts := versions.OptionsFor("9.3.0") + + if opts.Autocomplete.IsSet != true { + t.Errorf("Autocomplete should be set for v9.3.0") + } + if opts.Autocomplete.Value != false { + t.Errorf("Autocomplete should be false for v9.3.0") + } + }) + t.Run("v9.3.0-beta.1 should not have packaging/autocomplete", func(t *testing.T) { + opts := versions.OptionsFor("v9.3.0-beta.1") + + if opts.Autocomplete.IsSet != true { + t.Errorf("Autocomplete should be set for v9.3.0-beta.1") + } + if opts.Autocomplete.Value != false { + t.Errorf("Autocomplete should be false for v9.3.0-beta.1") + } + }) + t.Run("v10.0.1 should have packaging/autocomplete", func(t *testing.T) { + opts := versions.OptionsFor("v10.0.1") + + if opts.Autocomplete.IsSet != true { + t.Errorf("Autocomplete should be set for v10.0.1") + } + if opts.Autocomplete.Value != true { + t.Errorf("Autocomplete should be true for v10.0.1") + } + }) +} + +func TestMerge(t *testing.T) { + opts1 := versions.Options{ + Constraint: versions.NewNullable("^1.2.3"), + DebPreRM: versions.NewNullable(true), + } + + opts2 := versions.Options{ + Constraint: versions.NewNullable("^3.2.1"), + CombinedExecutable: versions.NewNullable(false), + } + + opts3 := versions.Options{ + Constraint: versions.NewNullable("^5.0.0"), + } + + merged := versions.Merge(opts1, opts2) + merged = versions.Merge(merged, opts3) + t.Run("It should keep the first constraint", func(t *testing.T) { + if merged.Constraint.Value != "^1.2.3" { + t.Fatalf(`merged.Constraint.Value != "^1.2.3", it is '%s'`, merged.Constraint.Value) + } + }) + + t.Run("It should use the last set 'CombinedExecutable'", func(t *testing.T) { + if merged.CombinedExecutable.Value != false { + t.Fatalf(`merged.Constraint.Value != false it is %t`, merged.CombinedExecutable.Value) + } + }) + + t.Run("It should use the last set 'DebPreRM'", func(t *testing.T) { + if merged.DebPreRM.Value != true { + t.Fatalf(`merged.DebPreRM.Value != true, it is %t`, merged.DebPreRM.Value) + } + }) +} diff --git a/pkg/build/daggerbuild/zip/builder.go b/pkg/build/daggerbuild/zip/builder.go new file mode 100644 index 00000000000..2391f2611e8 --- /dev/null +++ b/pkg/build/daggerbuild/zip/builder.go @@ -0,0 +1,15 @@ +package zip + +import "dagger.io/dagger" + +func Builder(d *dagger.Client) *dagger.Container { + return d.Container().From("alpine"). + WithExec([]string{"apk", "add", "--update", "zip", "tar"}) +} + +func Build(c *dagger.Container, targz *dagger.File) *dagger.File { + return c.WithFile("/src/grafana.tar.gz", targz). + WithExec([]string{"/bin/sh", "-c", "tar xzf /src/grafana.tar.gz"}). + WithExec([]string{"/bin/sh", "-c", "zip /src/grafana.zip $(tar tf /src/grafana.tar.gz)"}). + File("/src/grafana.zip") +} diff --git a/pkg/build/go.mod b/pkg/build/go.mod index fcc75b4b48a..f7782b13cec 100644 --- a/pkg/build/go.mod +++ b/pkg/build/go.mod @@ -22,14 +22,13 @@ require ( github.com/urfave/cli v1.22.16 // @grafana/grafana-backend-group github.com/urfave/cli/v2 v2.27.6 // @grafana/grafana-backend-group go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect; @grafana/plugins-platform-backend - go.opentelemetry.io/otel v1.35.0 // indirect; @grafana/grafana-backend-group + go.opentelemetry.io/otel v1.35.0 // @grafana/grafana-backend-group go.opentelemetry.io/otel/sdk v1.35.0 // indirect; @grafana/grafana-backend-group - go.opentelemetry.io/otel/trace v1.35.0 // indirect; @grafana/grafana-backend-group + go.opentelemetry.io/otel/trace v1.35.0 // @grafana/grafana-backend-group golang.org/x/crypto v0.38.0 // indirect; @grafana/grafana-backend-group - golang.org/x/mod v0.24.0 // @grafana/grafana-backend-group golang.org/x/net v0.40.0 // indirect; @grafana/oss-big-tent @grafana/partner-datasources golang.org/x/oauth2 v0.29.0 // @grafana/identity-access-team - golang.org/x/sync v0.14.0 // indirect; @grafana/alerting-backend + golang.org/x/sync v0.14.0 // @grafana/alerting-backend golang.org/x/text v0.25.0 // indirect; @grafana/grafana-backend-group golang.org/x/time v0.11.0 // indirect; @grafana/grafana-backend-group google.golang.org/api v0.223.0 // @grafana/grafana-backend-group @@ -73,25 +72,27 @@ require ( go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect golang.org/x/sys v0.33.0 // indirect google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect; @grafana/grafana-backend-group - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) require ( - dagger.io/dagger v0.17.2 + dagger.io/dagger v0.18.8 + github.com/Masterminds/semver v1.5.0 github.com/google/go-github/v70 v70.0.0 + github.com/quasilyte/go-ruleguard/dsl v0.3.22 ) require ( cel.dev/expr v0.23.1 // indirect cloud.google.com/go/monitoring v1.23.0 // indirect - github.com/99designs/gqlgen v0.17.70 // indirect + github.com/99designs/gqlgen v0.17.73 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.26.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect - github.com/Khan/genqlient v0.8.0 // indirect + github.com/Khan/genqlient v0.8.1 // indirect github.com/adrg/xdg v0.5.3 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -110,7 +111,7 @@ require ( github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sosodev/duration v1.3.1 // indirect github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect - github.com/vektah/gqlparser/v2 v2.5.23 // indirect + github.com/vektah/gqlparser/v2 v2.5.27 // indirect github.com/zeebo/errs v1.4.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect diff --git a/pkg/build/go.sum b/pkg/build/go.sum index 4b297f89121..69f82631a4b 100644 --- a/pkg/build/go.sum +++ b/pkg/build/go.sum @@ -21,11 +21,11 @@ cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6Q cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY= cloud.google.com/go/trace v1.11.3 h1:c+I4YFjxRQjvAhRmSsmjpASUKq88chOX854ied0K/pE= cloud.google.com/go/trace v1.11.3/go.mod h1:pt7zCYiDSQjC9Y2oqCsh9jF4GStB/hmjrYLsxRR27q8= -dagger.io/dagger v0.17.2 h1:/kspNWXEYvYy/MD6wu1LwYiQeZjp4Hv+53t4qIoi8SE= -dagger.io/dagger v0.17.2/go.mod h1:WkSnr5u632S+QhCOYAcgzEaeEB8kUfLarnJOpBym2hY= +dagger.io/dagger v0.18.8 h1:k3+DvD93Fy5SKijuPqFGvnQIBdJQJdfZtrGp4rqU1Xg= +dagger.io/dagger v0.18.8/go.mod h1:FWhniTblKFaUK6emdtL229v9GUOgC5rqIWIzABIdJIc= github.com/99designs/basicauth-go v0.0.0-20160802081356-2a93ba0f464d/go.mod h1:3cARGAK9CfW3HoxCy1a0G4TKrdiKke8ftOMEOHyySYs= -github.com/99designs/gqlgen v0.17.70 h1:xgLIgQuG+Q2L/AE9cW595CT7xCWCe/bpPIFGSfsGSGs= -github.com/99designs/gqlgen v0.17.70/go.mod h1:fvCiqQAu2VLhKXez2xFvLmE47QgAPf/KTPN5XQ4rsHQ= +github.com/99designs/gqlgen v0.17.73 h1:A3Ki+rHWqKbAOlg5fxiZBnz6OjW3nwupDHEG15gEsrg= +github.com/99designs/gqlgen v0.17.73/go.mod h1:2RyGWjy2k7W9jxrs8MOQthXGkD3L3oGr0jXW3Pu8lGg= github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= @@ -40,8 +40,10 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0 github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= -github.com/Khan/genqlient v0.8.0 h1:Hd1a+E1CQHYbMEKakIkvBH3zW0PWEeiX6Hp1i2kP2WE= -github.com/Khan/genqlient v0.8.0/go.mod h1:hn70SpYjWteRGvxTwo0kfaqg4wxvndECGkfa1fdDdYI= +github.com/Khan/genqlient v0.8.1 h1:wtOCc8N9rNynRLXN3k3CnfzheCUNKBcvXmVv5zt6WCs= +github.com/Khan/genqlient v0.8.1/go.mod h1:R2G6DzjBvCbhjsEajfRjbWdVglSH/73kSivC9TLWVjU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -216,6 +218,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -247,8 +251,8 @@ github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/vektah/gqlparser/v2 v2.5.23 h1:PurJ9wpgEVB7tty1seRUwkIDa/QH5RzkzraiKIjKLfA= -github.com/vektah/gqlparser/v2 v2.5.23/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= +github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s= +github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -311,8 +315,6 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -373,10 +375,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/pkg/promlib/go.mod b/pkg/promlib/go.mod index 0c2ae146dff..5f0f30fa286 100644 --- a/pkg/promlib/go.mod +++ b/pkg/promlib/go.mod @@ -121,8 +121,8 @@ require ( golang.org/x/tools v0.33.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/api v0.223.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/grpc v1.72.1 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect diff --git a/pkg/promlib/go.sum b/pkg/promlib/go.sum index b753a9bccab..5543a8e7150 100644 --- a/pkg/promlib/go.sum +++ b/pkg/promlib/go.sum @@ -405,10 +405,10 @@ gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= google.golang.org/api v0.223.0 h1:JUTaWEriXmEy5AhvdMgksGGPEFsYfUKaPEYXd4c3Wvc= google.golang.org/api v0.223.0/go.mod h1:C+RS7Z+dDwds2b+zoAk5hN/eSfsiCn0UDrYof/M4d2M= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/pkg/storage/unified/apistore/go.mod b/pkg/storage/unified/apistore/go.mod index 817420aa72d..a3f3af347ab 100644 --- a/pkg/storage/unified/apistore/go.mod +++ b/pkg/storage/unified/apistore/go.mod @@ -401,8 +401,8 @@ require ( gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/api v0.223.0 // indirect google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/pkg/storage/unified/apistore/go.sum b/pkg/storage/unified/apistore/go.sum index bc9f083c8c9..44209fd8c36 100644 --- a/pkg/storage/unified/apistore/go.sum +++ b/pkg/storage/unified/apistore/go.sum @@ -2572,10 +2572,8 @@ google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOl google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s= google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 h1:h6p3mQqrmT1XkHVTfzLdNz1u7IhINeZkz67/xTbOuWs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= diff --git a/scripts/drone/dagger.star b/scripts/drone/dagger.star new file mode 100644 index 00000000000..3f02f7282bb --- /dev/null +++ b/scripts/drone/dagger.star @@ -0,0 +1,9 @@ +""" +Utilities / functions for working with dagger pipelines +""" + +def with_dagger_install(commands = [], dagger_version = ""): + return [ + "wget -qO- https://github.com/dagger/dagger/releases/download/{}/dagger_{}_linux_amd64.tar.gz | tar zx -C /bin".format(dagger_version, dagger_version), + "apk add docker", + ] + commands diff --git a/scripts/drone/rgm.star b/scripts/drone/rgm.star index 3f8ac0ad65c..a8c7d3e48ee 100644 --- a/scripts/drone/rgm.star +++ b/scripts/drone/rgm.star @@ -1,9 +1,11 @@ """ -rgm uses 'github.com/grafana/grafana-build' to build Grafana on the following events: -* A merge to main -* A tag that begins with a 'v' +'rgm' pipelines are pipelines that use dagger (located in 'pkg/build/daggerbuild') """ +load( + "scripts/drone/dagger.star", + "with_dagger_install", +) load( "scripts/drone/events/release.star", "verify_release_pipeline", @@ -33,7 +35,7 @@ load( ) load( "scripts/drone/variables.star", - "golang_version", + "dagger_version", ) load( "scripts/drone/vault.star", @@ -132,19 +134,18 @@ def rgm_run(name, script): Drone step. """ env = { - "GO_VERSION": golang_version, "ALPINE_BASE": images["alpine"], "UBUNTU_BASE": images["ubuntu"], } rgm_run_step = { "name": name, - "image": "grafana/grafana-build:main", + "image": images["go"], "pull": "always", - "commands": [ + "commands": with_dagger_install([ "export GRAFANA_DIR=$$(pwd)", "export GITHUB_TOKEN=$(cat /github-app/token)", - "cd /src && ./scripts/{}".format(script), - ], + "./pkg/build/daggerbuild/scripts/{}".format(script), + ], dagger_version), "environment": rgm_env_secrets(env), # The docker socket is a requirement for running dagger programs # In the future we should find a way to use dagger without mounting the docker socket. @@ -328,7 +329,6 @@ def rgm_promotion_pipeline(): } env = { - "GO_VERSION": golang_version, "ALPINE_BASE": images["alpine"], "UBUNTU_BASE": images["ubuntu"], } @@ -342,18 +342,17 @@ def rgm_promotion_pipeline(): # * UPLOAD_TO = Google Cloud Storage URL to upload the built artifacts to. (ex: gs://some-bucket/path) build_step = { "name": "rgm-build", - "image": "grafana/grafana-build:main", + "image": images["go"], "pull": "always", - "commands": [ + "commands": with_dagger_install([ "export GITHUB_TOKEN=$(cat /github-app/token)", - "dagger run --silent /src/grafana-build artifacts " + + "dagger run --silent ./pkg/build/cmd artifacts " + "-a $${ARTIFACTS} " + "--grafana-ref=$${GRAFANA_REF} " + "--enterprise-ref=$${ENTERPRISE_REF} " + "--grafana-repo=$${GRAFANA_REPO} " + - "--version=$${VERSION} " + - "--go-version={}".format(golang_version), - ], + "--version=$${VERSION}", + ], dagger_version), "environment": rgm_env_secrets(env), # The docker socket is a requirement for running dagger programs # In the future we should find a way to use dagger without mounting the docker socket. diff --git a/scripts/drone/steps/rgm.star b/scripts/drone/steps/rgm.star index 68dd2a082e5..899411817a0 100644 --- a/scripts/drone/steps/rgm.star +++ b/scripts/drone/steps/rgm.star @@ -3,13 +3,17 @@ Individual steps that use 'grafana-build' to replace existing individual steps. These aren't used in releases. """ +load( + "scripts/drone/dagger.star", + "with_dagger_install", +) load( "scripts/drone/utils/images.star", "images", ) load( "scripts/drone/variables.star", - "golang_version", + "dagger_version", ) load( "scripts/drone/vault.star", @@ -18,7 +22,7 @@ load( ) def artifacts_cmd(artifacts = []): - cmd = "/src/grafana-build artifacts " + cmd = "go run ./pkg/build/cmd artifacts " for artifact in artifacts: cmd += "-a {} ".format(artifact) @@ -40,18 +44,17 @@ def rgm_artifacts_step( return { "name": name, - "image": "grafana/grafana-build:main", + "image": images["go"], "pull": "always", "depends_on": depends_on, "environment": { "_EXPERIMENTAL_DAGGER_CLOUD_TOKEN": from_secret(rgm_dagger_token), }, - "commands": [ + "commands": with_dagger_install([ "docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version", "docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'", "docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all", cmd + - "--go-version={} ".format(golang_version) + "--yarn-cache=$$YARN_CACHE_FOLDER " + "--build-id=$$DRONE_BUILD_NUMBER " + "--ubuntu-base={} ".format(ubuntu) + @@ -61,7 +64,7 @@ def rgm_artifacts_step( "--verify='{}' ".format(verify) + "--grafana-dir=$$PWD > {}".format(file), "find ./dist -name '*docker*.tar.gz' -type f | xargs -n1 docker load -i", - ], + ], dagger_version), "volumes": [{"name": "docker", "path": "/var/run/docker.sock"}], } @@ -74,16 +77,16 @@ def rgm_build_backend_step(artifacts = ["backend:grafana:linux/amd64", "backend: def rgm_build_docker_step(ubuntu, alpine, depends_on = ["yarn-install"], file = "docker.txt", tag_format = "{{ .version }}-{{ .arch }}", ubuntu_tag_format = "{{ .version }}-ubuntu-{{ .arch }}"): return { "name": "rgm-build-docker", - "image": "grafana/grafana-build:main", + "image": images["go"], "pull": "always", "environment": { "_EXPERIMENTAL_DAGGER_CLOUD_TOKEN": from_secret(rgm_dagger_token), }, - "commands": [ + "commands": with_dagger_install([ "docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version", "docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'", "docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all", - "/src/grafana-build artifacts " + + "go run ./pkg/build/cmd artifacts " + "-a docker:grafana:linux/amd64 " + "-a docker:grafana:linux/amd64:ubuntu " + "-a docker:grafana:linux/arm64 " + @@ -92,14 +95,13 @@ def rgm_build_docker_step(ubuntu, alpine, depends_on = ["yarn-install"], file = "-a docker:grafana:linux/arm/v7:ubuntu " + "--yarn-cache=$$YARN_CACHE_FOLDER " + "--build-id=$$DRONE_BUILD_NUMBER " + - "--go-version={} ".format(golang_version) + "--ubuntu-base={} ".format(ubuntu) + "--alpine-base={} ".format(alpine) + "--tag-format='{}' ".format(tag_format) + "--grafana-dir=$$PWD " + "--ubuntu-tag-format='{}' > {}".format(ubuntu_tag_format, file), "find ./dist -name '*docker*.tar.gz' -type f | xargs -n1 docker load -i", - ], + ], dagger_version), "volumes": [{"name": "docker", "path": "/var/run/docker.sock"}], "depends_on": depends_on, } diff --git a/scripts/drone/variables.star b/scripts/drone/variables.star index 315d5e002f5..d0ed5fbd63e 100644 --- a/scripts/drone/variables.star +++ b/scripts/drone/variables.star @@ -7,3 +7,4 @@ golang_version = "1.24.4" # nodejs_version should match what's in ".nvmrc", but without the v prefix. nodejs_version = "22.11.0" +dagger_version = "v0.18.8"