From ee8de424d7919991282d8a7333dd5faeb969b068 Mon Sep 17 00:00:00 2001 From: Justin Kolberg Date: Thu, 31 Oct 2024 12:14:57 -0700 Subject: [PATCH] chore(ci): pkg trigger & release workflow updates Packaging is now only triggered from Dev & PR builds. The only input sent when triggering packaging is now the Workflow Run ID of the workflow run that packaging should pull its artifacts from. The version of otelcol-sumo & otelcol-config is now determined using a combination of the otelcol_version in `otelcolbuilder/.otelcol-builder.yaml` and git tags. Releases are no longer triggered by the creation of a tag. A release can now be triggered via the new 'Publish release' workflow. The new release workflow requires the ID of a workflow run that contains the artifacts to be released. The Git SHA used to build the otelcol-sumo binary is now included in the version of the --version flag. Signed-off-by: Justin Kolberg --- .changelog/1693.changed.txt | 1 + .github/workflows/dev_builds.yml | 53 --- .github/workflows/pull_requests.yml | 26 +- .github/workflows/release-packaging.yml | 13 - .../{release_builds.yml => releases.yml} | 214 ++++----- .../workflows/workflow-trigger-packaging.yml | 37 +- ci/get_version.sh | 134 +++--- ci/get_version_from_binary.sh | 95 ++++ otelcolbuilder/Makefile | 2 +- .../msi/SumoLogic.wixext/SumoLogic.wixext.sln | 50 --- .../SumoLogic.wixext/Config.cs | 62 --- .../SumoLogic.wixext/ConfigUpdater.cs | 168 ------- .../SumoLogic.wixext/CustomAction.config | 18 - .../SumoLogic.wixext/CustomAction.cs | 138 ------ .../SumoLogic.wixext/Exceptions.cs | 42 -- .../SumoLogic.wixext/Logger.cs | 30 -- .../SumoLogic.wixext/SumoLogic.wixext.csproj | 19 - .../SumoLogicTests/ConfigTests.cs | 90 ---- .../SumoLogicTests/ConfigUpdaterTests.cs | 410 ------------------ .../SumoLogicTests/Properties/AssemblyInfo.cs | 20 - .../SumoLogicTests/SumoLogicTests.csproj | 105 ----- .../SumoLogicTests/TestData/empty.yaml | 0 .../SumoLogicTests/TestData/invalid.yaml | 1 - .../TestData/no-indentation.yaml | 11 - .../TestData/with-extensions-block.yaml | 104 ----- .../TestData/without-extensions-block.yaml | 85 ---- .../SumoLogicTests/packages.config | 6 - packaging/msi/wix/assets/LICENSE.rtf | 236 ---------- .../msi/wix/assets/banner_background.bmp | Bin 114432 -> 0 bytes packaging/msi/wix/assets/common.yaml | 3 - .../msi/wix/assets/dialog_background.bmp | Bin 615320 -> 0 bytes packaging/msi/wix/assets/project.ico | Bin 270398 -> 0 bytes packaging/msi/wix/components.wxs | 104 ----- packaging/msi/wix/folders.wxs | 28 -- packaging/msi/wix/otelcol-sumo.wixproj | 68 --- packaging/msi/wix/package.en-us.wxl | 29 -- packaging/msi/wix/package.wxs | 151 ------- packaging/msi/wix/ui/appdata-dir-dlg.wxs | 28 -- packaging/msi/wix/ui/otelcol-sumo.wxs | 60 --- packaging/msi/wix/variables.wxi | 14 - 40 files changed, 243 insertions(+), 2412 deletions(-) create mode 100644 .changelog/1693.changed.txt delete mode 100644 .github/workflows/release-packaging.yml rename .github/workflows/{release_builds.yml => releases.yml} (70%) create mode 100755 ci/get_version_from_binary.sh delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext.sln delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Config.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/ConfigUpdater.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.config delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Exceptions.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Logger.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogic.wixext/SumoLogic.wixext.csproj delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigTests.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigUpdaterTests.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/Properties/AssemblyInfo.cs delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/SumoLogicTests.csproj delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/empty.yaml delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/invalid.yaml delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/no-indentation.yaml delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/with-extensions-block.yaml delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/without-extensions-block.yaml delete mode 100644 packaging/msi/SumoLogic.wixext/SumoLogicTests/packages.config delete mode 100644 packaging/msi/wix/assets/LICENSE.rtf delete mode 100644 packaging/msi/wix/assets/banner_background.bmp delete mode 100644 packaging/msi/wix/assets/common.yaml delete mode 100644 packaging/msi/wix/assets/dialog_background.bmp delete mode 100644 packaging/msi/wix/assets/project.ico delete mode 100644 packaging/msi/wix/components.wxs delete mode 100644 packaging/msi/wix/folders.wxs delete mode 100644 packaging/msi/wix/otelcol-sumo.wixproj delete mode 100644 packaging/msi/wix/package.en-us.wxl delete mode 100644 packaging/msi/wix/package.wxs delete mode 100644 packaging/msi/wix/ui/appdata-dir-dlg.wxs delete mode 100644 packaging/msi/wix/ui/otelcol-sumo.wxs delete mode 100644 packaging/msi/wix/variables.wxi diff --git a/.changelog/1693.changed.txt b/.changelog/1693.changed.txt new file mode 100644 index 0000000000..9ebbb534a1 --- /dev/null +++ b/.changelog/1693.changed.txt @@ -0,0 +1 @@ +chore(ci): remove MSIs from this repo \ No newline at end of file diff --git a/.github/workflows/dev_builds.yml b/.github/workflows/dev_builds.yml index 78a1b71af9..2f8c7cdb78 100644 --- a/.github/workflows/dev_builds.yml +++ b/.github/workflows/dev_builds.yml @@ -451,57 +451,6 @@ jobs: REPO_URL=sumologic/sumologic-otel-collector-dev \ BUILD_TYPE_SUFFIX="-ubi" - package-msi: - name: Package MSI - runs-on: windows-2019 - needs: - - build - strategy: - matrix: - include: - - arch_os: windows_amd64 - platform: x64 - fips: false - - arch_os: windows_amd64 - platform: x64 - fips: true - steps: - - uses: actions/checkout@v4 - - - name: Fetch current branch - run: ./ci/fetch_current_branch.sh - - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v2 - - - name: Fetch binary artifact for ${{ matrix.arch_os }} - uses: actions/download-artifact@v4 - with: - name: otelcol-sumo${{ matrix.fips && '-fips' || '' }}-${{ matrix.arch_os }}.exe - path: ./otelcolbuilder/cmd - - - name: Rename fips binary artifact for ${{ matrix.arch_os }} - if: matrix.fips - working-directory: ./otelcolbuilder/cmd - run: mv otelcol-sumo-fips-${{ matrix.arch_os }}.exe otelcol-sumo-${{ matrix.arch_os }}.exe - - - name: Set OVERRIDE_BUILD_NUMBER - run: echo "OVERRIDE_BUILD_VERSION=$GITHUB_RUN_NUMBER" >> $GITHUB_ENV - - - name: Set PRODUCT_VERSION - run: echo "PRODUCT_VERSION=$(./ci/get_version.sh productversion)" >> $GITHUB_ENV - - - name: Build MSI for ${{ matrix.arch_os }} - working-directory: ./packaging/msi/wix - run: msbuild.exe -p:Configuration=Release -p:Platform=${{ matrix.platform }} -p:ProductVersion=$PRODUCT_VERSION -p:FIPSEnabled=${{ matrix.fips }} -Restore - - - name: Store MSI as action artifact for ${{ matrix.arch_os }} - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.arch_os }}${{ matrix.fips && '_fips' || '' }}_msi - path: ./packaging/msi/wix/bin/${{ matrix.platform }}/en-US/*.msi - if-no-files-found: error - install-script: name: Store install script runs-on: ubuntu-latest @@ -530,10 +479,8 @@ jobs: - build - build-otelcol-config - lint - - package-msi - push-docker-manifest uses: ./.github/workflows/workflow-trigger-packaging.yml secrets: inherit with: workflow_id: ${{ github.run_id }} - create_release: false diff --git a/.github/workflows/pull_requests.yml b/.github/workflows/pull_requests.yml index 267e24bd4b..54be4830ab 100644 --- a/.github/workflows/pull_requests.yml +++ b/.github/workflows/pull_requests.yml @@ -175,30 +175,6 @@ jobs: save-cache: true boringcrypto: ${{ matrix.boringcrypto == true }} - test-wixext: - name: Test (SumoLogic.wixext) - runs-on: windows-2019 - steps: - - uses: actions/checkout@v4 - - - name: Fetch current branch - run: ./ci/fetch_current_branch.sh - - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v2 - - - name: Restore NuGet packages - working-directory: ./packaging/msi/SumoLogic.wixext/SumoLogicTests - run: nuget.exe restore -PackagesDirectory ../packages - - - name: Build unit tests - working-directory: ./packaging/msi/SumoLogic.wixext/SumoLogicTests - run: msbuild.exe -p:Configuration=Release -p:Platform=AnyCPU -Restore - - - name: Run unit tests - working-directory: ./packaging/msi/SumoLogic.wixext/SumoLogicTests/bin/Release - run: dotnet test -v:n ./SumoLogicTests.dll - lint: name: Lint (golangci-lint) runs-on: ubuntu-20.04 @@ -404,4 +380,4 @@ jobs: - name: Test built image run: make test-built-image - # ToDo: build windows FIPS image + # TODO: build windows FIPS image diff --git a/.github/workflows/release-packaging.yml b/.github/workflows/release-packaging.yml deleted file mode 100644 index 5377726504..0000000000 --- a/.github/workflows/release-packaging.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Trigger packaging for release - -on: - release: - types: [published] - -jobs: - trigger-packaging: - name: Trigger Packaging for release ${{ github.event.release.name }} - uses: ./.github/workflows/workflow-trigger-packaging.yml - secrets: inherit - with: - create_release: true diff --git a/.github/workflows/release_builds.yml b/.github/workflows/releases.yml similarity index 70% rename from .github/workflows/release_builds.yml rename to .github/workflows/releases.yml index 006162b0bd..515a979c58 100644 --- a/.github/workflows/release_builds.yml +++ b/.github/workflows/releases.yml @@ -1,88 +1,85 @@ -name: Releases +name: 'Publish release' + +run-name: > + ${{ format('Publish Release for Workflow: {0}', inputs.workflow_id) }} on: - push: - tags: - - "v[0-9]+.[0-9]+.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+" - - - "v[0-9]+.[0-9]+.[0-9]+-sumo-[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-sumo-[0-9]+-alpha.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-sumo-[0-9]+-beta.[0-9]+" - - "v[0-9]+.[0-9]+.[0-9]+-sumo-[0-9]+-rc.[0-9]+" + workflow_dispatch: + inputs: + workflow_id: + description: | + Workflow Run ID from this repository to fetch artifacts from for this + release. + required: true + type: string defaults: run: shell: bash -env: - GO_VERSION: "1.22.6" - jobs: get-version: name: Get application version for this revision runs-on: ubuntu-latest outputs: + sha: ${{ steps.get-sha.outputs.git-sha }} + otc-version: ${{ steps.get-version.outputs.otc-version }} + sumo-version: ${{ steps.get-version.outputs.sumo-version }} version: ${{ steps.get-version.outputs.version }} steps: - uses: actions/checkout@v4 + + - name: Outuput Workflow ID + run: echo ::notice title=Workflow ID::${{ inputs.workflow_id }} + + - name: Output Workflow URL + run: | + repo_url="https://github.com/SumoLogic/sumologic-otel-collector" + url="${repo_url}/actions/runs/${{ inputs.workflow_id }}" + echo ::notice title=Workflow URL::${url} + + - name: Download otelcol-sumo artifact from workflow + uses: actions/download-artifact@v4 with: - fetch-depth: 0 - - name: Get version + name: otelcol-sumo-linux_amd64 + path: artifacts/ + merge-multiple: true + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ inputs.workflow_id }} + + - name: Determine version from artifact id: get-version run: | - echo "version=$(echo ${GITHUB_REF#refs/tags/v})" > $GITHUB_OUTPUT - - name: Print version - run: echo ::notice title=Version::${{ steps.get-version.outputs.version }} - - build: - name: Build - uses: ./.github/workflows/workflow-build.yml - needs: [get-version] - strategy: - matrix: - include: - - arch_os: linux_amd64 - runs-on: ubuntu-20.04 - - arch_os: linux_amd64 - runs-on: ubuntu-20.04 - fips: true - - arch_os: linux_arm64 - runs-on: ubuntu-20.04 - - arch_os: linux_arm64 - runs-on: ubuntu-20.04 - fips: true - - arch_os: darwin_amd64 - runs-on: macos-15 - - arch_os: darwin_arm64 - runs-on: macos-15 - - arch_os: windows_amd64 - runs-on: windows-2022 - - arch_os: windows_amd64 - runs-on: windows-2022 - fips: true - with: - arch_os: ${{ matrix.arch_os }} - runs-on: ${{ matrix.runs-on }} - fips: ${{ matrix.fips == true }} - sumo_component_gomod_version: "v${{ needs.get-version.outputs.version }}" - secrets: - apple_developer_certificate_p12_base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} - apple_developer_certificate_password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} - app_store_connect_password: ${{ secrets.AC_PASSWORD }} - microsoft_certificate: ${{ secrets.MICROSOFT_CERTIFICATE }} - microsoft_certificate_password: ${{ secrets.MICROSOFT_CERTIFICATE_PASSWORD }} - microsoft_certificate_hash: ${{ secrets.MICROSOFT_CERTHASH }} - microsoft_certificate_name: ${{ secrets.MICROSOFT_CERTNAME }} - microsoft_description: ${{ secrets.MICROSOFT_DESCRIPTION }} + artifact="artifacts/otelcol-sumo-linux_amd64" + chmod +x "${artifact}" + script="ci/get_version_from_binary.sh" + core="$("$script" core "${artifact}")" + sumo="$("$script" sumo "${artifact}")" + echo "otc-version=$core" >> $GITHUB_OUTPUT + echo "sumo-version=$sumo" >> $GITHUB_OUTPUT + echo "version=${core}-sumo-${sumo}" >> $GITHUB_OUTPUT + + - name: Output Version + run: | + echo ::notice title=Version::${{ steps.get-version.outputs.version }} + + - name: Determine Git SHA of workflow + id: get-sha + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + workflow="${{ inputs.workflow_id }}" + sha="$(gh run view ${workflow} --json headSha -t '{{.headSha}}')" + echo "git-sha=$sha" >> $GITHUB_OUTPUT + + - name: Output Git SHA + run: | + echo ::notice title=Git SHA::${{ steps.get-sha.outputs.git-sha }} build-container-images: name: Build container runs-on: ubuntu-20.04 needs: - - build - get-version strategy: matrix: @@ -112,17 +109,13 @@ jobs: --username ${{ secrets.DOCKERHUB_LOGIN }} \ --password ${{ secrets.DOCKERHUB_PASSWORD }} - - name: Download binary action artifact from build phase + - name: Download platform otelcol-sumo artifacts from workflow uses: actions/download-artifact@v4 with: - name: otelcol-sumo-${{matrix.arch_os}} - path: artifacts/ - - - name: Download binary action artifact from build phase (FIPS) - uses: actions/download-artifact@v4 - with: - name: otelcol-sumo-fips-${{matrix.arch_os}} + pattern: otelcol-sumo-*-${{ matrix.arch_os }} path: artifacts/ + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ inputs.workflow_id }} - name: Build and push FIPS image to Open Source ECR run: | @@ -196,7 +189,6 @@ jobs: needs: # Require darwin build to succeed to prevent pushing container images # when darwin build fails. - - build - build-container-images - get-version steps: @@ -282,64 +274,6 @@ jobs: REPO_URL=sumologic/sumologic-otel-collector \ BUILD_TYPE_SUFFIX="-ubi" - package-msi: - name: Package MSI - runs-on: windows-2019 - needs: - - build - strategy: - matrix: - include: - - arch_os: windows_amd64 - platform: x64 - fips: false - - arch_os: windows_amd64 - platform: x64 - fips: true - steps: - - uses: actions/checkout@v4 - - - name: Fetch current branch - run: ./ci/fetch_current_branch.sh - - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v2 - - - name: Fetch binary artifact for ${{ matrix.arch_os }} ${{ matrix.fips && '(FIPS)' || '' }} - uses: actions/download-artifact@v4 - with: - name: otelcol-sumo${{ matrix.fips && '-fips' || '' }}-windows_amd64.exe - path: ./otelcolbuilder/cmd - - - name: Rename FIPS binary artifact for ${{ matrix.arch_os }} - if: matrix.fips - working-directory: ./otelcolbuilder/cmd - run: mv otelcol-sumo${{ matrix.fips && '-fips' || '' }}-windows_amd64.exe otelcol-sumo-${{ matrix.arch_os }}.exe - - - name: Set PRODUCT_VERSION - run: echo "PRODUCT_VERSION=$(./ci/get_version.sh productversion)" >> $GITHUB_ENV - - - name: Build MSI for ${{ matrix.arch_os }} - working-directory: ./packaging/msi/wix - run: msbuild.exe -p:Configuration=Release -p:Platform=${{ matrix.platform }} -p:ProductVersion=$PRODUCT_VERSION -p:FIPSEnabled=${{ matrix.fips }} -Restore - - - name: Sign MSI - uses: skymatic/code-sign-action@v3 - with: - certificate: "${{ secrets.MICROSOFT_CERTIFICATE }}" - password: "${{ secrets.MICROSOFT_CERTIFICATE_PASSWORD }}" - certificatesha1: "${{ secrets.MICROSOFT_CERTHASH }}" - certificatename: "${{ secrets.MICROSOFT_CERTNAME }}" - description: "${{ secrets.MICROSOFT_DESCRIPTION }}" - folder: ./packaging/msi/wix/bin/${{ matrix.platform }}/en-US - - - name: Store MSI as action artifact for ${{ matrix.arch_os }} - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.arch_os }}${{ matrix.fips && '_fips' || '' }}_msi - path: ./packaging/msi/wix/bin/${{ matrix.platform }}/en-US/*.msi - if-no-files-found: error - # Store the install script from the packaging repository as a release artifact. # Originally, this script was stored in this repository, and the official download url pointed # to the most recent release here. The script has since been moved to the packaging repository. @@ -411,32 +345,42 @@ jobs: name: Create Github release runs-on: ubuntu-20.04 needs: - - build + - get-version - build-container-images - push-docker-manifest - - package-msi - - get-version steps: - - name: Download all binaries stored as artifact + - name: Download all artifacts from workflow uses: actions/download-artifact@v4 with: path: artifacts/ merge-multiple: true + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ inputs.workflow_id }} + - name: Add version to binary names working-directory: artifacts/ run: | + version="${{ needs.get-version.outputs.version }}" find . -type f -name 'otelcol-sumo*' \ - | grep -v '\.msi' \ | sed 's/^\.\///' \ | while read -r file; do - new_name=$(echo "$file" | sed 's/otelcol-sumo/otelcol-sumo-${{ needs.get-version.outputs.version }}/g') + new_name=$(echo "$file" | sed "s/otelcol-sumo/otelcol-sumo-${version}/g") + mv "$file" "$new_name" + done + find . -type f -name 'otelcol-config*' \ + | sed 's/^\.\///' \ + | while read -r file; do + new_name=$(echo "$file" | sed "s/otelcol-config/otelcol-config-${version}/g") mv "$file" "$new_name" done + - uses: ncipollo/release-action@v1 with: token: ${{ secrets.GITHUB_TOKEN }} draft: true prerelease: false + commit: ${{ needs.get-sha.outputs.git-sha }} + tag: v${{ needs.get-version.outputs.version }} allowUpdates: true omitBodyDuringUpdate: true diff --git a/.github/workflows/workflow-trigger-packaging.yml b/.github/workflows/workflow-trigger-packaging.yml index e2e2fd2665..4a50172918 100644 --- a/.github/workflows/workflow-trigger-packaging.yml +++ b/.github/workflows/workflow-trigger-packaging.yml @@ -3,14 +3,10 @@ name: Trigger Packaging on: workflow_call: inputs: - create_release: - description: The packaging workflow will create a draft release in the packaging repository. - required: true - type: boolean workflow_id: - description: ID of the workflow to fetch artifacts from. If empty, artifacts will be fetched from the latest release. + description: ID of the Collector workflow that Packaging will fetch artifacts from. type: string - required: false + required: true defaults: run: @@ -30,20 +26,6 @@ jobs: fetch-depth: 0 filter: 'tree:0' - - name: Determine version core - id: version-core - run: > - ./ci/get_version.sh core > /tmp/version_core && - cat /tmp/version_core && - echo version=$(cat /tmp/version_core) >> $GITHUB_OUTPUT - - - name: Determine sumo version - id: sumo-version - run: > - ./ci/get_version.sh sumo > /tmp/sumo_version && - cat /tmp/sumo_version && - echo version=$(cat /tmp/sumo_version) >> $GITHUB_OUTPUT - # TODO: output the workflow url - name: Trigger packaging workflow id: trigger-packaging-workflow @@ -52,12 +34,9 @@ jobs: REPO: SumoLogic/sumologic-otel-collector-packaging WORKFLOW: build_packages.yml run: | - gh workflow run --repo ${REPO} ${WORKFLOW} --json << EOF + gh workflow run --repo ${REPO} ${WORKFLOW} --ref use-binary-version --json << EOF { - "workflow_id": "${{ inputs.workflow_id }}", - "otc_version": "${{ steps.version-core.outputs.version }}", - "otc_sumo_version": "${{ steps.sumo-version.outputs.version }}", - "release": "${{ inputs.create_release }}" + "workflow_id": "${{ inputs.workflow_id }}" } EOF @@ -65,9 +44,5 @@ jobs: # packaging workflow has completed. - name: Packaging Workflow URL run: echo ::notice title=Packaging Workflow URL::https://github.com/SumoLogic/sumologic-otel-collector-packaging/actions/workflows/build_packages.yml - - name: Workflow ID - run: echo ::notice title=Workflow ID::${{ inputs.workflow_id }} - - name: OTC Version - run: echo ::notice title=OTC Version::${{ steps.version-core.outputs.version }} - - name: OTC Sumo Version - run: echo ::notice title=OTC Sumo Version::${{ steps.sumo-version.outputs.version }} + - name: Collector Workflow ID + run: echo ::notice title=Collector Workflow ID::${{ inputs.workflow_id }} diff --git a/ci/get_version.sh b/ci/get_version.sh index 318e56a18a..3ae74f1833 100755 --- a/ci/get_version.sh +++ b/ci/get_version.sh @@ -3,27 +3,24 @@ declare -i major_version declare -i minor_version declare -i patch_version -declare build_version -declare build_windows_version -declare ot_channel -declare -i ot_channel_version -declare sumo_channel -declare -i sumo_channel_version +declare -i sumo_version usage() { cat <&2 + exit 1 fi - version_regex="^v([0-9]+).([0-9]+).([0-9]+)((-(alpha|beta|rc|sumo)[-.]([0-9]+))(-(alpha|beta|rc).([0-9])+)?)?$" + version_regex="^([0-9]+).([0-9]+).([0-9]+)$" - if [[ $version_tag =~ $version_regex ]]; then + if [[ $version =~ $version_regex ]]; then major_version="${BASH_REMATCH[1]}" minor_version="${BASH_REMATCH[2]}" patch_version="${BASH_REMATCH[3]}" - ot_channel="${BASH_REMATCH[6]}" - ot_channel_version="${BASH_REMATCH[7]}" - sumo_channel="${BASH_REMATCH[9]}" - sumo_channel_version="${BASH_REMATCH[10]}" else - echo "Error: Tag does not match required version regex: ${version_tag}" >&2 + echo "Error: otc version does not match required version regex: ${version}" >&2 exit 1 fi +} - if [[ $ot_channel == "sumo" ]]; then - if [[ $sumo_channel != "" ]]; then - build_version="${ot_channel_version}-${sumo_channel}.${sumo_channel_version}" - build_windows_version="${ot_channel_version}" - else - build_version="${ot_channel_version}" - build_windows_version="${ot_channel_version}" - fi - elif [[ $ot_channel != "" ]]; then - build_version="${ot_channel_version}" - build_windows_version="${ot_channel_version}" - fi +parse_sumo_version() { + tags=() + for tag in $(git tag -l "v$(version_core)-sumo-*"); do + tags+=( "${tag}" ) + done - if [[ $OVERRIDE_BUILD_VERSION != "" ]]; then - number_regex='^[0-9]+$' - if ! [[ $OVERRIDE_BUILD_VERSION =~ $number_regex ]]; then - echo "Error: OVERRIDE_BUILD_VERSION is not a number" >&2 - exit 1 + for tag in "${tags[@]}"; do + tag_regex="^v[0-9]+.[0-9]+.[0-9]+-sumo-([0-9])+$" + if [[ $tag =~ $tag_regex ]]; then + sumo_version="${BASH_REMATCH[1]}" fi - build_version="${OVERRIDE_BUILD_VERSION}" - build_windows_version="${OVERRIDE_BUILD_VERSION}" + done + + if [[ -z "${sumo_version}" ]]; then + # No matching tags were found. Sumo version is 0. + sumo_version="0" + else + # Matching tags found. Increment sumo_version by 1. + (( sumo_version++ )) fi } # Validate version information using the Windows ProductVersion requirements. validate() { if [[ -z "${major_version}" ]]; then - echo "Major version cannot be empty" + echo "Major version cannot be empty" >&2 exit 1 fi if [[ $major_version -lt 0 ]]; then - echo "Major version cannot be less than 0" + echo "Major version cannot be less than 0" >&2 exit 1 fi if [[ $major_version -gt 255 ]]; then - echo "Major version cannot be greater than 255" + echo "Major version cannot be greater than 255" >&2 exit 1 fi if [[ -z "${minor_version}" ]]; then - echo "Minor version cannot be empty" + echo "Minor version cannot be empty" >&2 exit 1 fi if [[ $minor_version -lt 0 ]]; then - echo "Minor version cannot be less than 0" + echo "Minor version cannot be less than 0" >&2 exit 1 fi if [[ $minor_version -gt 255 ]]; then - echo "Minor version cannot be greater than 255" + echo "Minor version cannot be greater than 255" >&2 exit 1 fi - # Patch version is also known as the build version on Windows + # Patch version (known as the build version on Windows) if [[ -z "${patch_version}" ]]; then - echo "Patch version cannot be empty" + echo "Patch version cannot be empty" >&2 exit 1 fi if [[ $patch_version -lt 0 ]]; then - echo "Patch version cannot be less than 0" + echo "Patch version cannot be less than 0" >&2 exit 1 fi if [[ $patch_version -gt 65535 ]]; then - echo "Patch version cannot be greater than 65,535" - exit 1 - fi - - # Build version is also known as the internal version on Windows - if [[ -z "${build_version}" ]]; then - echo "Build version cannot be empty" - exit 1 - fi - - # Build version is also known as the internal version on Windows - if [[ -z "${build_windows_version}" ]]; then - echo "Windows Build version cannot be empty" + echo "Patch version cannot be greater than 65,535" >&2 exit 1 fi - if [[ $ot_channel_version -lt 0 ]]; then - echo "Build version cannot be less than 0" - exit 1 - fi - - if [[ $ot_channel_version -gt 65535 ]]; then - echo "Build version cannot be greater than 65,535" + # Sumo version (known as the internal version on Windows) + if [[ -z "${sumo_version}" ]]; then + echo "Sumo version cannot be empty" >&2 exit 1 fi } @@ -177,24 +156,31 @@ version_core() { # Prints the sumo version. (e.g. the X in A.B.C-sumo-X) sumo_version() { - echo "${build_version}" + echo "${sumo_version}" +} + +# Prints the full version. (e.g. A.B.C-sumo-X) +full_version() { + echo "$(version_core)-sumo-$(sumo_version)" } # Convert the version to a Windows ProductVersion. # # https://learn.microsoft.com/en-us/windows/win32/msi/productversion -# MAJOR.MINOR.PATCH.BUILD -> MAJOR.MINOR.BUILD.INTERNAL +# MAJOR.MINOR.PATCH.SUMO -> MAJOR.MINOR.BUILD.INTERNAL windows_product_version() { - echo "${major_version}.${minor_version}.${patch_version}.${build_windows_version}" + echo "${major_version}.${minor_version}.${patch_version}.${sumo_version}" } parse_params "$@" -parse_version_tag +parse_core_version +parse_sumo_version validate case "$1" in core) version_core ;; sumo) sumo_version ;; + full) full_version ;; productversion) windows_product_version ;; *) bad_usage "Unknown argument: ${1}" ;; esac diff --git a/ci/get_version_from_binary.sh b/ci/get_version_from_binary.sh new file mode 100755 index 0000000000..6a3c96f17a --- /dev/null +++ b/ci/get_version_from_binary.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +declare -i major_version +declare -i minor_version +declare -i patch_version +declare -i sumo_version + +usage() { + cat <&2 + exit 1 + fi +} + +# Prints the semver version core. (e.g. A.B.C) +version_core() { + echo "${major_version}.${minor_version}.${patch_version}" +} + +# Prints the sumo version. (e.g. the X in A.B.C-sumo-X) +version_sumo() { + echo "${sumo_version}" +} + +# Convert the version to a Windows ProductVersion. +# +# https://learn.microsoft.com/en-us/windows/win32/msi/productversion +# MAJOR.MINOR.PATCH.SUMO -> MAJOR.MINOR.BUILD.INTERNAL +windows_product_version() { + echo "${major_version}.${minor_version}.${patch_version}.${sumo_version}" +} + +parse_params "$@" +parse_version "$2" + +case "$1" in + core) version_core ;; + sumo) version_sumo ;; + productversion) windows_product_version ;; + *) bad_usage "Unknown argument: ${1}" ;; +esac diff --git a/otelcolbuilder/Makefile b/otelcolbuilder/Makefile index 5b36318408..d7237687ed 100644 --- a/otelcolbuilder/Makefile +++ b/otelcolbuilder/Makefile @@ -86,7 +86,7 @@ install-builder: .PHONY: _builder _builder: - $(eval VERSION ?= $(shell git describe --tags --abbrev=5 --match "v[0-9]*")) + $(eval VERSION ?= $(shell ./ci/get_version.sh full | xargs)-$(shell git rev-parse HEAD | xargs)) # Need to specify go path because otherwise opentelemetry-collector-builder # uses /usr/bin/go which on Github Actions is using preinstalled 1.15.12 by default. CGO_ENABLED=$(CGO_ENABLED) $(BUILDER_BIN_NAME) \ diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext.sln b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext.sln deleted file mode 100644 index 9d259d8089..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext.sln +++ /dev/null @@ -1,50 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.33027.164 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SumoLogic.wixext", "SumoLogic.wixext\SumoLogic.wixext.csproj", "{C2671341-19D5-4CD6-84A3-F7207DE74E30}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SumoLogicTests", "SumoLogicTests\SumoLogicTests.csproj", "{C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Debug|Any CPU.ActiveCfg = Debug|x86 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Debug|x64.ActiveCfg = Debug|x64 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Debug|x64.Build.0 = Debug|x64 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Debug|x86.ActiveCfg = Debug|x86 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Debug|x86.Build.0 = Debug|x86 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Release|Any CPU.Build.0 = Release|Any CPU - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Release|x64.ActiveCfg = Release|x64 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Release|x64.Build.0 = Release|x64 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Release|x86.ActiveCfg = Release|x64 - {C2671341-19D5-4CD6-84A3-F7207DE74E30}.Release|x86.Build.0 = Release|x64 - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Debug|x64.ActiveCfg = Debug|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Debug|x64.Build.0 = Debug|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Debug|x86.ActiveCfg = Debug|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Debug|x86.Build.0 = Debug|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Release|Any CPU.Build.0 = Release|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Release|x64.ActiveCfg = Release|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Release|x64.Build.0 = Release|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Release|x86.ActiveCfg = Release|Any CPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {AF3C92B2-597B-4A89-A66F-9B4FBD962809} - EndGlobalSection -EndGlobal diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Config.cs b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Config.cs deleted file mode 100644 index d9ec4e9b5d..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Config.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace SumoLogic.wixext -{ - public class Config - { - public string InstallationToken { get; set; } - public Dictionary CollectorFields { get; set; } - public bool RemotelyManaged { get; set; } - public bool Ephemeral { get; set; } - public string OpAmpFolder { get; set; } - public string Api { get; set; } - - public Config() { - this.CollectorFields = new Dictionary(); - } - - public void SetCollectorFieldsFromTags(string tags) - { - if (tags.Length == 0) { return; } - - var tagsRx = new Regex(@"([^=,]+)=([^\0]+?)(?=,[^,]+=|$)", RegexOptions.Compiled); - var matches = tagsRx.Matches(tags); - - if (matches.Count == 0) - { - throw new TagsSyntaxException("tags were provided with invalid syntax"); - } - if (matches.Count > 10) - { - throw new TagsLimitExceededException("the limit of 10 tags was exceeded"); - } - - foreach (Match match in matches) - { - if (match.Groups.Count != 3) - { - Console.WriteLine("Groups: {0}", match.Groups.Count); - var msg = string.Format("invalid syntax for tag: {0}", match.Value); - throw new TagSyntaxException(msg); - } - var key = match.Groups[1].Value.Trim(); - var value = match.Groups[2].Value.Trim(); - - if (key.Length > 255) - { - var msg = string.Format("tag key exceeds maximum length of 255: {0}", key); - throw new TagKeyLengthExceededException(msg); - } - if (value.Length > 200) - { - var msg = string.Format("tag value exceeds maximum length of 200: {0}", value); - throw new TagValueLengthExceededException(msg); - } - - this.CollectorFields.Add(key, value); - } - } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/ConfigUpdater.cs b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/ConfigUpdater.cs deleted file mode 100644 index 3f32026f86..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/ConfigUpdater.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using YamlDotNet.RepresentationModel; -using YamlDotNet.Serialization; - -namespace SumoLogic.wixext -{ - public class ConfigUpdater - { - public YamlDocument Document { get; set; } - - public ConfigUpdater(StreamReader streamReader) { - try - { - var ys = new YamlStream(); - ys.Load(streamReader); - if (ys.Documents.Count == 0) - { - throw new EmptyConfigException("config file is empty"); - } - this.Document = ys.Documents[0]; - } - finally - { - streamReader.Dispose(); - } - } - - public void Update(Config config) - { - if (config.RemotelyManaged && string.IsNullOrEmpty(config.OpAmpFolder)) - { - throw new MissingConfigurationException("OpAmpFolder"); - } - - YamlMappingNode root = (YamlMappingNode)this.Document.RootNode; - - EnsureMapKey(root, "extensions"); - YamlMappingNode extensions = (YamlMappingNode)root.Children["extensions"]; - - EnsureMapKey(extensions, "sumologic"); - YamlMappingNode sumologic = (YamlMappingNode)extensions.Children["sumologic"]; - - if (config.InstallationToken != "") - { - EnsureScalarKey(sumologic, "installation_token"); - sumologic.Children["installation_token"] = config.InstallationToken; - } - - if (config.CollectorFields.Count > 0) - { - EnsureMapKey(sumologic, "collector_fields"); - YamlMappingNode collectorFields = (YamlMappingNode)sumologic.Children["collector_fields"]; - - foreach (KeyValuePair field in config.CollectorFields) - { - EnsureScalarKey(collectorFields, field.Key); - collectorFields.Children[field.Key] = field.Value; - } - } - - if (config.RemotelyManaged) - { - EnsureMapKey(extensions, "opamp"); - YamlMappingNode opamp = (YamlMappingNode)extensions.Children["opamp"]; - EnsureScalarKey(opamp, "remote_configuration_directory"); - opamp.Children["remote_configuration_directory"] = config.OpAmpFolder; - - // Add OpAmp extension to service section - EnsureMapKey(root, "service"); - YamlMappingNode service = (YamlMappingNode)root.Children["service"]; - EnsureSequenceKey(service, "extensions"); - YamlSequenceNode serviceExtensions = (YamlSequenceNode)service.Children["extensions"]; - if (!serviceExtensions.Children.Contains("opamp")) - { - serviceExtensions.Children.Add("opamp"); - } - } - - if (config.Ephemeral) - { - EnsureScalarKey(sumologic, "ephemeral"); - sumologic.Children["ephemeral"] = "true"; - } - - if (!string.IsNullOrEmpty(config.Api)) - { - EnsureScalarKey(sumologic, "api_base_url"); - sumologic.Children["api_base_url"] = config.Api; - } - - // Make sure the sumologic processor node is a map node, otherwise an empty string - // is generated as the value instead of an empty node. - if (root.Children.ContainsKey("processors")) - { - EnsureMapKey(root, "processors"); - YamlMappingNode processors = (YamlMappingNode)root.Children["processors"]; - if (processors.Children.ContainsKey("sumologic")) - { - EnsureMapKey(processors, "sumologic"); - } - } - } - - public void Save(StreamWriter streamWriter) - { - try - { - var serializer = new Serializer(); - serializer.Serialize(streamWriter, this.Document.RootNode); - } - finally - { - streamWriter.Flush(); - } - } - - private void EnsureMapKey(YamlMappingNode node, string key) - { - if (node.Children.ContainsKey(key)) - { - if (node.Children[key].NodeType == YamlNodeType.Mapping) { - return; - } - - // TODO: is this how we want to handle incorrect node types? - // YamlNode is wrong type, remove it - node.Children.Remove(key); - } - // Add empty YamlMappingNode to key - node.Children.Add(key, new YamlMappingNode()); - } - - private void EnsureScalarKey(YamlMappingNode node, string key) - { - if (node.Children.ContainsKey(key)) - { - if (node.Children[key].NodeType == YamlNodeType.Scalar) - { - return; - } - - // TODO: is this how we want to handle incorrect node types? - // YamlNode is wrong type, remove it - node.Children.Remove(key); - } - // Add empty YamlScalarNode to key - node.Children.Add(key, new YamlScalarNode()); - } - - private void EnsureSequenceKey(YamlMappingNode node, string key) - { - if (node.Children.ContainsKey(key)) - { - if (node.Children[key].NodeType == YamlNodeType.Sequence) - { - return; - } - - // TODO: is this how we want to handle incorrect node types? - // YamlNode is wrong type, remove it - node.Children.Remove(key); - } - // Add empty YamlScalarNode to key - node.Children.Add(key, new YamlSequenceNode()); - } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.config b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.config deleted file mode 100644 index 19bffa211e..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.cs b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.cs deleted file mode 100644 index af566b9e81..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/CustomAction.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.IO; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using WixToolset.Dtf.WindowsInstaller; - -namespace SumoLogic.wixext -{ - public class CustomActions - { - // WiX error codes - private const short ecMissingCustomActionData = 9001; - private const short ecConfigError = 9002; - - // WiX property names - private const string pCommonConfigPath = "CommonConfigPath"; - private const string pSumoLogicConfigPath = "SumoLogicConfigPath"; - private const string pInstallationToken = "InstallationToken"; - private const string pInstallToken = "InstallToken"; - private const string pTags = "Tags"; - private const string pApi = "Api"; - private const string pRemotelyManaged = "RemotelyManaged"; - private const string pEphemeral = "Ephemeral"; - private const string pConfigFolder = "ConfigFolder"; - private const string pOpAmpFolder = "OpAmpFolder"; - private const string pConfigFragmentsFolder = "ConfigFragmentsFolder"; - - // WiX features - private const string fRemotelyManaged = "REMOTELYMANAGED"; - - [CustomAction] - public static ActionResult UpdateConfig(Session session) - { - Logger logger = new Logger("UpdateConfig", session); - logger.Log("Begin"); - - // Validate presence of required WiX properties - if (!session.CustomActionData.ContainsKey(pCommonConfigPath)) - { - ShowErrorMessage(session, ecMissingCustomActionData, pCommonConfigPath); - return ActionResult.Failure; - } - if (!session.CustomActionData.ContainsKey(pInstallToken) && !session.CustomActionData.ContainsKey(pInstallationToken)) - { - ShowErrorMessage(session, ecMissingCustomActionData, pInstallationToken); - return ActionResult.Failure; - } - if (!session.CustomActionData.ContainsKey(pTags)) - { - ShowErrorMessage(session, ecMissingCustomActionData, pTags); - return ActionResult.Failure; - } - - var commonConfigPath = session.CustomActionData[pCommonConfigPath]; - var sumoLogicConfigPath = session.CustomActionData[pSumoLogicConfigPath]; - var tags = session.CustomActionData[pTags]; - - var installationToken = ""; - if (session.CustomActionData.ContainsKey(pInstallationToken) && session.CustomActionData[pInstallationToken] != "") - { - installationToken = session.CustomActionData[pInstallationToken]; - } - else if (session.CustomActionData.ContainsKey(pInstallToken)) - { - installationToken = session.CustomActionData[pInstallToken]; - } - - var remotelyManaged = (session.CustomActionData.ContainsKey(pRemotelyManaged) && session.CustomActionData[pRemotelyManaged] == "true"); - var ephemeral = (session.CustomActionData.ContainsKey(pEphemeral) && session.CustomActionData[pEphemeral] == "true"); - var opAmpFolder = session.CustomActionData[pOpAmpFolder]; - var api = session.CustomActionData[pApi]; - - if (remotelyManaged && string.IsNullOrEmpty(opAmpFolder)) - { - ShowErrorMessage(session, ecMissingCustomActionData, pOpAmpFolder); - return ActionResult.Failure; - } - - // Load config from disk and replace values - Config config = new Config { InstallationToken = installationToken, RemotelyManaged = remotelyManaged, Ephemeral = ephemeral, - OpAmpFolder = opAmpFolder, Api = api }; - config.SetCollectorFieldsFromTags(tags); - - var configFile = remotelyManaged ? sumoLogicConfigPath : commonConfigPath; - try - { - ConfigUpdater configUpdater = new ConfigUpdater(new StreamReader(configFile)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(configFile)); - } - catch (Exception e) - { - ShowErrorMessage(session, ecConfigError, e.Message); - return ActionResult.Failure; - } - - logger.Log("End"); - - return ActionResult.Success; - } - - [CustomAction] - public static ActionResult PopulateServiceArguments(Session session) - { - try - { - var configFolder = session.GetTargetPath(pConfigFolder); - var configFragmentsFolder = session.GetTargetPath(pConfigFragmentsFolder); - var remotelyManaged = session.Features.Contains(fRemotelyManaged) && session.Features[fRemotelyManaged].RequestState == InstallState.Local; - - if (remotelyManaged) - { - session["SERVICEARGUMENTS"] = " --remote-config \"opamp:" + configFolder + "sumologic.yaml\""; - } - else - { - session["SERVICEARGUMENTS"] = " --config \"" + configFolder + "sumologic.yaml\" --config \"glob:" + configFragmentsFolder + "*.yaml\""; - } - } - catch (Exception e) - { - ShowErrorMessage(session, ecConfigError, e.Message + e.StackTrace); - return ActionResult.Failure; - } - - return ActionResult.Success; - } - - private static void ShowErrorMessage(Session session, short errCode, string key) - { - Record record = new Record(3); - record.SetInteger(1, errCode); - record.SetString(2, key); - session.Message(InstallMessage.Error | (InstallMessage)MessageIcon.Error, record); - record.Close(); - } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Exceptions.cs b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Exceptions.cs deleted file mode 100644 index 3c8519ad44..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Exceptions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace SumoLogic.wixext -{ - public class EmptyConfigException : Exception - { - public EmptyConfigException(string message) { } - } - - public class TagsSyntaxException : Exception - { - public TagsSyntaxException(string message) { } - } - - public class TagSyntaxException : Exception - { - public TagSyntaxException(string message) { } - } - - public class TagsLimitExceededException : Exception - { - public TagsLimitExceededException(string message) { } - } - - public class TagKeyLengthExceededException : Exception - { - public TagKeyLengthExceededException(string message) { } - } - - public class TagValueLengthExceededException : Exception - { - public TagValueLengthExceededException(string message) { } - } - - public class MissingConfigurationException : Exception - { - public MissingConfigurationException(string message) { } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Logger.cs b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Logger.cs deleted file mode 100644 index 5d507392fb..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/Logger.cs +++ /dev/null @@ -1,30 +0,0 @@ -using WixToolset.Dtf.WindowsInstaller; - -namespace SumoLogic.wixext -{ - class Logger - { - private string actionName; - private Session session; - - public Logger(string actionName, Session session) - { - this.actionName = actionName; - this.session = session; - } - - public void Log(string msg) - { - this.session.Log(this.Format(msg)); - } - public void Log(string format, params object[] args) - { - this.session.Log(this.Format(format), args); - } - - private string Format(string msg) - { - return string.Format("{0}: {1}", this.actionName, msg); - } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/SumoLogic.wixext.csproj b/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/SumoLogic.wixext.csproj deleted file mode 100644 index f6ec09218f..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogic.wixext/SumoLogic.wixext.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - net35 - x64;x86;AnyCPU - - - - - - - - - - - - - - - diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigTests.cs b/packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigTests.cs deleted file mode 100644 index 4953c3e2f8..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigTests.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SumoLogic.wixext; -using System; -using System.Linq; - -namespace SumoLogicTests -{ - [TestClass] - public class ConfigTests - { - private static readonly Random random = new Random(); - - public static string RandomString(int length) - { - const string chars = "abcdefghijklmnopqrstuvwxyz"; - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[random.Next(s.Length)]).ToArray()); - } - - [TestMethod] - public void TestSetCollectorFieldsFromTags_Valid() - { - var tags = @"foo=bar,baz=kaz , xaz=yaz"; - - var config = new Config(); - config.SetCollectorFieldsFromTags(tags); - - Assert.AreEqual(config.CollectorFields.Keys.Count, 3); - - Assert.IsTrue(config.CollectorFields.ContainsKey("foo")); - Assert.IsTrue(config.CollectorFields.ContainsKey("baz")); - Assert.IsTrue(config.CollectorFields.ContainsKey("xaz")); - - Assert.AreEqual("bar", config.CollectorFields["foo"]); - Assert.AreEqual("kaz", config.CollectorFields["baz"]); - Assert.AreEqual("yaz", config.CollectorFields["xaz"]); - } - - [TestMethod] - public void TestSetCollectorFieldsFromTags_Empty() - { - var tags = @""; - - var config = new Config(); - config.SetCollectorFieldsFromTags(tags); - - Assert.AreEqual(config.CollectorFields.Keys.Count, 0); - } - - [TestMethod] - [ExpectedException(typeof(TagsSyntaxException), "Invalid tags syntax did not throw a TagsSyntaxException.")] - public void TestSetCollectorFieldsFromTags_NoMatches() - { - var tags = @"key"; - - var config = new Config(); - config.SetCollectorFieldsFromTags(tags); - } - - [TestMethod] - [ExpectedException(typeof(TagsLimitExceededException), "Tag count exceeding 10 did not throw a TagsLimitExceededException.")] - public void TestSetCollectorFieldsFromTags_LimitExceeded() - { - var tags = @"a=b,c=d,e=f,g=h,i=j,k=l,m=n,o=p,q=r,s=t,u=v"; - - var config = new Config(); - config.SetCollectorFieldsFromTags(tags); - } - - [TestMethod] - [ExpectedException(typeof(TagKeyLengthExceededException), "Tag key exceeding 255 characters did not throw a TagKeyLengthExceededException.")] - public void TestSetCollectorFieldsFromTags_KeyLengthExceeded() - { - var tags = string.Format("{0}=value", RandomString(256)); - - var config = new Config(); - config.SetCollectorFieldsFromTags(tags); - } - - [TestMethod] - [ExpectedException(typeof(TagValueLengthExceededException), "Tag value exceeding 200 characters did not throw a TagValueLengthExceededException.")] - public void TestSetCollectorFieldsFromTags_ValueLengthExceeded() - { - var tags = string.Format("key={0}", RandomString(201)); - - var config = new Config(); - config.SetCollectorFieldsFromTags(tags); - } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigUpdaterTests.cs b/packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigUpdaterTests.cs deleted file mode 100644 index f812e4bab9..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/ConfigUpdaterTests.cs +++ /dev/null @@ -1,410 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SumoLogic.wixext; -using System; -using System.IO; -using YamlDotNet.RepresentationModel; - -namespace SumoLogicTests -{ - [TestClass] - public class ConfigUpdaterTests - { - readonly string testDataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestData"); - - public void InstallationTokenAssertions(Config config, StreamReader sr) - { - YamlStream ys = new YamlStream(); - ys.Load(sr); - YamlMappingNode root = (YamlMappingNode)ys.Documents[0].RootNode; - - Assert.IsTrue(root.Children.ContainsKey("extensions")); - Assert.AreEqual(YamlNodeType.Mapping, root.Children["extensions"].NodeType); - var extensions = (YamlMappingNode)root.Children["extensions"]; - - Assert.IsTrue(extensions.Children.ContainsKey("sumologic")); - Assert.AreEqual(YamlNodeType.Mapping, extensions.Children["sumologic"].NodeType); - var sumologic = (YamlMappingNode)extensions.Children["sumologic"]; - - Assert.IsTrue(sumologic.Children.ContainsKey("installation_token")); - Assert.AreEqual(YamlNodeType.Scalar, sumologic.Children["installation_token"].NodeType); - Assert.AreEqual(config.InstallationToken, sumologic.Children["installation_token"].ToString()); - - if (config.Ephemeral) - { - Assert.IsTrue(sumologic.Children.ContainsKey("ephemeral")); - Assert.AreEqual(YamlNodeType.Scalar, sumologic.Children["ephemeral"].NodeType); - Assert.AreEqual("true", sumologic.Children["ephemeral"].ToString()); - } - else - { - Assert.IsFalse(sumologic.Children.ContainsKey("ephemeral")); - } - - Assert.IsTrue(sumologic.Children.ContainsKey("collector_fields")); - Assert.AreEqual(YamlNodeType.Mapping, sumologic.Children["collector_fields"].NodeType); - var collectorFields = (YamlMappingNode)sumologic.Children["collector_fields"]; - - Assert.IsTrue(collectorFields.Children.ContainsKey("foo")); - Assert.IsTrue(collectorFields.Children.ContainsKey("baz")); - Assert.IsTrue(collectorFields.Children.ContainsKey("xaz")); - Assert.AreEqual(YamlNodeType.Scalar, collectorFields.Children["foo"].NodeType); - Assert.AreEqual(YamlNodeType.Scalar, collectorFields.Children["baz"].NodeType); - Assert.AreEqual(YamlNodeType.Scalar, collectorFields.Children["xaz"].NodeType); - Assert.AreEqual("bar", collectorFields.Children["foo"]); - Assert.AreEqual("kaz", collectorFields.Children["baz"]); - Assert.AreEqual("yaz", collectorFields.Children["xaz"]); - } - - public void OpAmpAssertions(Config config, StreamReader sr) - { - YamlStream ys = new YamlStream(); - ys.Load(sr); - YamlMappingNode root = (YamlMappingNode)ys.Documents[0].RootNode; - - Assert.IsTrue(root.Children.ContainsKey("extensions")); - Assert.AreEqual(YamlNodeType.Mapping, root.Children["extensions"].NodeType); - var extensions = (YamlMappingNode)root.Children["extensions"]; - - if (config.RemotelyManaged) - { - Assert.IsTrue(extensions.Children.ContainsKey("opamp")); - Assert.AreEqual(YamlNodeType.Mapping, extensions.Children["opamp"].NodeType); - var opamp = (YamlMappingNode)extensions.Children["opamp"]; - - Assert.IsTrue(opamp.Children.ContainsKey("remote_configuration_directory")); - Assert.AreEqual(YamlNodeType.Scalar, opamp.Children["remote_configuration_directory"].NodeType); - Assert.AreEqual(config.OpAmpFolder, opamp.Children["remote_configuration_directory"].ToString()); - } - else - { - Assert.IsFalse(extensions.Children.ContainsKey("opamp")); - } - - Assert.IsTrue(root.Children.ContainsKey("service")); - Assert.AreEqual(YamlNodeType.Mapping, root.Children["service"].NodeType); - var service = (YamlMappingNode)root.Children["service"]; - - Assert.IsTrue(service.Children.ContainsKey("extensions")); - Assert.AreEqual(YamlNodeType.Sequence, service.Children["extensions"].NodeType); - var serviceExtensions = (YamlSequenceNode)service.Children["extensions"]; - if (config.RemotelyManaged) - { - Assert.IsTrue(serviceExtensions.Children.Contains("opamp")); - } - else - { - Assert.IsFalse(serviceExtensions.Children.Contains("opamp")); - } - } - - public void EphemeralAssertions(Config config, StreamReader sr) - { - YamlStream ys = new YamlStream(); - ys.Load(sr); - YamlMappingNode root = (YamlMappingNode)ys.Documents[0].RootNode; - - Assert.IsTrue(root.Children.ContainsKey("extensions")); - Assert.AreEqual(YamlNodeType.Mapping, root.Children["extensions"].NodeType); - var extensions = (YamlMappingNode)root.Children["extensions"]; - - Assert.IsTrue(extensions.Children.ContainsKey("sumologic")); - Assert.AreEqual(YamlNodeType.Mapping, extensions.Children["sumologic"].NodeType); - var sumologic = (YamlMappingNode)extensions.Children["sumologic"]; - - if (config.Ephemeral) - { - Assert.IsTrue(sumologic.Children.ContainsKey("ephemeral")); - Assert.AreEqual(YamlNodeType.Scalar, sumologic.Children["ephemeral"].NodeType); - Assert.AreEqual("true", sumologic.Children["ephemeral"].ToString()); - } - else - { - if (sumologic.Children.ContainsKey("ephemeral")) - { - Assert.AreEqual(YamlNodeType.Scalar, sumologic.Children["ephemeral"].NodeType); - Assert.AreEqual("false", sumologic.Children["ephemeral"].ToString()); - } - } - } - - public void ApiAssertions(Config config, StreamReader sr) - { - YamlStream ys = new YamlStream(); - ys.Load(sr); - YamlMappingNode root = (YamlMappingNode)ys.Documents[0].RootNode; - - Assert.IsTrue(root.Children.ContainsKey("extensions")); - Assert.AreEqual(YamlNodeType.Mapping, root.Children["extensions"].NodeType); - var extensions = (YamlMappingNode)root.Children["extensions"]; - - Assert.IsTrue(extensions.Children.ContainsKey("sumologic")); - Assert.AreEqual(YamlNodeType.Mapping, extensions.Children["sumologic"].NodeType); - var sumologic = (YamlMappingNode)extensions.Children["sumologic"]; - - Assert.IsTrue(sumologic.Children.ContainsKey("api_base_url")); - Assert.AreEqual(YamlNodeType.Scalar, sumologic.Children["api_base_url"].NodeType); - var apiBaseUrl = (YamlScalarNode)sumologic.Children["api_base_url"]; - Assert.AreEqual(config.Api, apiBaseUrl.ToString()); - } - - [TestMethod] - public void TestUpdate_WithExtensionsBlock() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = true }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - InstallationTokenAssertions(config, sr); - } - } - - [TestMethod] - public void TestUpdate_WithoutExtensionsBlock() - { - var filePath = Path.Combine(testDataPath, "without-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = false }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - InstallationTokenAssertions(config, sr); - } - } - - [TestMethod] - public void TestUpdate_NoIndentation() - { - var filePath = Path.Combine(testDataPath, "no-indentation.yaml"); - var config = new Config { InstallationToken = "foobar" }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - InstallationTokenAssertions(config, sr); - } - } - - [TestMethod] - [ExpectedException(typeof(EmptyConfigException), "Loading an empty config did not throw an EmptyConfigException.")] - public void TestUpdate_Empty() - { - var filePath = Path.Combine(testDataPath, "empty.yaml"); - var config = new Config { InstallationToken = "foobar" }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - } - } - - [TestMethod] - [ExpectedException(typeof(YamlDotNet.Core.SyntaxErrorException), "Loading an invalid config did not throw a YamlDotNet.Core.SyntaxErrorException.")] - public void TestUpdate_Invalid() - { - var filePath = Path.Combine(testDataPath, "invalid.yaml"); - var config = new Config { InstallationToken = "foobar" }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - } - } - - [TestMethod] - public void TestUpdate_OpAmp() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = true, RemotelyManaged = true, OpAmpFolder = "/opamp" }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - OpAmpAssertions(config, sr); - } - } - - [TestMethod] - [ExpectedException(typeof(MissingConfigurationException), "OpAmpFolder")] - public void TestUpdate_OpAmpNoFolder() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = true, RemotelyManaged = true }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - } - } - - [TestMethod] - public void TestUpdate_NoOpAmpWithFolder() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = true, RemotelyManaged = false, OpAmpFolder = "/opamp" }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - OpAmpAssertions(config, sr); - } - } - - [TestMethod] - public void TestUpdate_Ephemeral() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = true }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - EphemeralAssertions(config, sr); - } - } - - [TestMethod] - public void TestUpdate_NotEphemeral() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Ephemeral = false }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - EphemeralAssertions(config, sr); - } - } - - [TestMethod] - public void TestUpdate_Api() - { - var filePath = Path.Combine(testDataPath, "with-extensions-block.yaml"); - var config = new Config { InstallationToken = "foobar", Api = "http://apiurl.local" }; - config.SetCollectorFieldsFromTags(@"foo=bar,baz=kaz,xaz=yaz"); - - using (MemoryStream ms = new MemoryStream()) - { - var configUpdater = new ConfigUpdater(new StreamReader(filePath)); - configUpdater.Update(config); - configUpdater.Save(new StreamWriter(ms)); - - ms.Seek(0, SeekOrigin.Begin); - - StreamReader sr = new StreamReader(ms); - while (!sr.EndOfStream) - { - Console.WriteLine(sr.ReadLine()); - } - - ms.Seek(0, SeekOrigin.Begin); - - ApiAssertions(config, sr); - } - } - } -} diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/Properties/AssemblyInfo.cs b/packaging/msi/SumoLogic.wixext/SumoLogicTests/Properties/AssemblyInfo.cs deleted file mode 100644 index 08b3c70bcb..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SumoLogicTests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SumoLogicTests")] -[assembly: AssemblyCopyright("Copyright © 2022")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("c2b5b3eb-dbd0-4bd2-a90e-d4f2f1a615bc")] - -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/SumoLogicTests.csproj b/packaging/msi/SumoLogic.wixext/SumoLogicTests/SumoLogicTests.csproj deleted file mode 100644 index f83f8d9f4e..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/SumoLogicTests.csproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - Debug - AnyCPU - {C2B5B3EB-DBD0-4BD2-A90E-D4F2F1A615BC} - Library - Properties - SumoLogicTests - SumoLogicTests - v4.5.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - - - 15.0 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - MinimumRecommendedRules.ruleset - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - MinimumRecommendedRules.ruleset - false - AnyCPU - - - - ..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - - - ..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - - - - - ..\packages\YamlDotNet.12.0.2\lib\net45\YamlDotNet.dll - - - - - - - - - - {c2671341-19d5-4cd6-84a3-f7207de74e30} - SumoLogic.wixext - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/empty.yaml b/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/empty.yaml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/invalid.yaml b/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/invalid.yaml deleted file mode 100644 index bf1ee551ce..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/invalid.yaml +++ /dev/null @@ -1 +0,0 @@ -"invalid-yaml: foobar diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/no-indentation.yaml b/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/no-indentation.yaml deleted file mode 100644 index d01f538872..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/no-indentation.yaml +++ /dev/null @@ -1,11 +0,0 @@ -## This file is generated automatically and shouldn't be changed -## All modifications should be put as separate files in conf.d subdirectory -extensions: - -receivers: - -exporters: - -processors: - -service: diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/with-extensions-block.yaml b/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/with-extensions-block.yaml deleted file mode 100644 index 67581a6b61..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/with-extensions-block.yaml +++ /dev/null @@ -1,104 +0,0 @@ -## This file is generated automatically and shouldn't be changed -## All modifications should be put as separate files in conf.d subdirectory -extensions: - ## Configuration for Sumo Logic Extension - ## Manages registration, heartbeats and authentication to Sumo Logic - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/sumologicextension - sumologic: - installation_token: ${SUMOLOGIC_INSTALLATION_TOKEN} - collector_credentials_directory: ${PROGRAMDATA}\Sumo Logic\otelcol-sumo\data\credentials - - ## Configuration for Health Check Extension - ## Health Check extension enables an HTTP url that can be probed to check the status of the OpenTelemetry Collector - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/healthcheckextension - health_check: - - ## Configuration for File Storage Extension - ## The File Storage extension can persist state to the local file system - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/storage/filestorage - file_storage: - directory: ${PROGRAMDATA}\Sumo Logic\otelcol-sumo\data\file_storage - -receivers: - ## Configuration for OTLP Receiver - ## Receives data via gRPC or HTTP using OTLP format. - ## ref: https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver - otlp: - protocols: - grpc: - endpoint: localhost:4317 - http: - endpoint: localhost:4318 - -exporters: - ## Configuration for Sumo Logic Exporter - ## This exporter supports sending logs, metrics and traces data to Sumo Logic. - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/v0.103.0/exporter/sumologicexporter - sumologic: - sending_queue: - enabled: true - storage: file_storage - -processors: - ## Configuration for Memory Limiter Processor - ## The memory_limiter processor is used to prevent out of memory situations on the collector. - ## ref: https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/memorylimiterprocessor - memory_limiter: - ## check_interval is the time between measurements of memory usage for the - ## purposes of avoiding going over the limits. Defaults to zero, so no - ## checks will be performed. Values below 1 second are not recommended since - ## it can result in unnecessary CPU consumption. - check_interval: 5s - ## Maximum amount of memory, in %, targeted to be allocated by the process heap. - limit_percentage: 75 - ## Spike limit (calculated from available memory). Must be less than limit_percentage. - spike_limit_percentage: 20 - - ## Configuration for Batch Processor - ## The batch processor accepts records and places them into batches grouped by node and resource - ## ref: https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor - batch: - ## Number of records after which a batch will be sent regardless of time - send_batch_size: 1_024 - ## Time duration after which a batch will be sent regardless of size - timeout: 1s - - ## Configuration for Sumo Logic Schema Processor - ## The Sumo Logic Schema processor modifies the metadata on logs, metrics and traces sent to Sumo Logic - ## so that the Sumo Logic apps can make full use of the ingested data. - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/sumologicprocessor - sumologic: - -service: - extensions: - - sumologic - - health_check - - file_storage - pipelines: - metrics/default: - receivers: - - otlp - processors: - - memory_limiter - - batch - - sumologic - exporters: - - sumologic - logs/default: - receivers: - - otlp - processors: - - memory_limiter - - batch - - sumologic - exporters: - - sumologic - traces/default: - receivers: - - otlp - processors: - - memory_limiter - - batch - - sumologic - exporters: - - sumologic diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/without-extensions-block.yaml b/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/without-extensions-block.yaml deleted file mode 100644 index f1b0ea41d6..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/TestData/without-extensions-block.yaml +++ /dev/null @@ -1,85 +0,0 @@ -## This file is generated automatically and shouldn't be changed -## All modifications should be put as separate files in conf.d subdirectory -receivers: - ## Configuration for OTLP Receiver - ## Receives data via gRPC or HTTP using OTLP format. - ## ref: https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver - otlp: - protocols: - grpc: - endpoint: localhost:4317 - http: - endpoint: localhost:4318 - -exporters: - ## Configuration for Sumo Logic Exporter - ## This exporter supports sending logs, metrics and traces data to Sumo Logic. - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/v0.103.0/exporter/sumologicexporter - sumologic: - sending_queue: - enabled: true - storage: file_storage - -processors: - ## Configuration for Memory Limiter Processor - ## The memory_limiter processor is used to prevent out of memory situations on the collector. - ## ref: https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/memorylimiterprocessor - memory_limiter: - ## check_interval is the time between measurements of memory usage for the - ## purposes of avoiding going over the limits. Defaults to zero, so no - ## checks will be performed. Values below 1 second are not recommended since - ## it can result in unnecessary CPU consumption. - check_interval: 5s - ## Maximum amount of memory, in %, targeted to be allocated by the process heap. - limit_percentage: 75 - ## Spike limit (calculated from available memory). Must be less than limit_percentage. - spike_limit_percentage: 20 - - ## Configuration for Batch Processor - ## The batch processor accepts records and places them into batches grouped by node and resource - ## ref: https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor - batch: - ## Number of records after which a batch will be sent regardless of time - send_batch_size: 1_024 - ## Time duration after which a batch will be sent regardless of size - timeout: 1s - - ## Configuration for Sumo Logic Schema Processor - ## The Sumo Logic Schema processor modifies the metadata on logs, metrics and traces sent to Sumo Logic - ## so that the Sumo Logic apps can make full use of the ingested data. - ## ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/sumologicprocessor - sumologic: - -service: - extensions: - - sumologic - - health_check - - file_storage - pipelines: - metrics/default: - receivers: - - otlp - processors: - - memory_limiter - - batch - - sumologic - exporters: - - sumologic - logs/default: - receivers: - - otlp - processors: - - memory_limiter - - batch - - sumologic - exporters: - - sumologic - traces/default: - receivers: - - otlp - processors: - - memory_limiter - - batch - - sumologic - exporters: - - sumologic diff --git a/packaging/msi/SumoLogic.wixext/SumoLogicTests/packages.config b/packaging/msi/SumoLogic.wixext/SumoLogicTests/packages.config deleted file mode 100644 index 673ede4a7d..0000000000 --- a/packaging/msi/SumoLogic.wixext/SumoLogicTests/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packaging/msi/wix/assets/LICENSE.rtf b/packaging/msi/wix/assets/LICENSE.rtf deleted file mode 100644 index 0184c5c42a..0000000000 --- a/packaging/msi/wix/assets/LICENSE.rtf +++ /dev/null @@ -1,236 +0,0 @@ -{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Courier New;}} -{\*\generator Riched20 10.0.22000}\viewkind4\uc1 -\pard\f0\fs22\lang1033 Copyright 2021 Sumo Logic Inc.\par -\par - -\pard\qc Apache License\par -Version 2.0, January 2004\par -http://www.apache.org/licenses/\par - -\pard\par - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\par -\par - 1. Definitions.\par -\par - "License" shall mean the terms and conditions for use, reproduction,\par - and distribution as defined by Sections 1 through 9 of this document.\par -\par - "Licensor" shall mean the copyright owner or entity authorized by\par - the copyright owner that is granting the License.\par -\par - "Legal Entity" shall mean the union of the acting entity and all\par - other entities that control, are controlled by, or are under common\par - control with that entity. For the purposes of this definition,\par - "control" means (i) the power, direct or indirect, to cause the\par - direction or management of such entity, whether by contract or\par - otherwise, or (ii) ownership of fifty percent (50%) or more of the\par - outstanding shares, or (iii) beneficial ownership of such entity.\par -\par - "You" (or "Your") shall mean an individual or Legal Entity\par - exercising permissions granted by this License.\par -\par - "Source" form shall mean the preferred form for making modifications,\par - including but not limited to software source code, documentation\par - source, and configuration files.\par -\par - "Object" form shall mean any form resulting from mechanical\par - transformation or translation of a Source form, including but\par - not limited to compiled object code, generated documentation,\par - and conversions to other media types.\par -\par - "Work" shall mean the work of authorship, whether in Source or\par - Object form, made available under the License, as indicated by a\par - copyright notice that is included in or attached to the work\par - (an example is provided in the Appendix below).\par -\par - "Derivative Works" shall mean any work, whether in Source or Object\par - form, that is based on (or derived from) the Work and for which the\par - editorial revisions, annotations, elaborations, or other modifications\par - represent, as a whole, an original work of authorship. For the purposes\par - of this License, Derivative Works shall not include works that remain\par - separable from, or merely link (or bind by name) to the interfaces of,\par - the Work and Derivative Works thereof.\par -\par - "Contribution" shall mean any work of authorship, including\par - the original version of the Work and any modifications or additions\par - to that Work or Derivative Works thereof, that is intentionally\par - submitted to Licensor for inclusion in the Work by the copyright owner\par - or by an individual or Legal Entity authorized to submit on behalf of\par - the copyright owner. For the purposes of this definition, "submitted"\par - means any form of electronic, verbal, or written communication sent\par - to the Licensor or its representatives, including but not limited to\par - communication on electronic mailing lists, source code control systems,\par - and issue tracking systems that are managed by, or on behalf of, the\par - Licensor for the purpose of discussing and improving the Work, but\par - excluding communication that is conspicuously marked or otherwise\par - designated in writing by the copyright owner as "Not a Contribution."\par -\par - "Contributor" shall mean Licensor and any individual or Legal Entity\par - on behalf of whom a Contribution has been received by Licensor and\par - subsequently incorporated within the Work.\par -\par - 2. Grant of Copyright License. Subject to the terms and conditions of\par - this License, each Contributor hereby grants to You a perpetual,\par - worldwide, non-exclusive, no-charge, royalty-free, irrevocable\par - copyright license to reproduce, prepare Derivative Works of,\par - publicly display, publicly perform, sublicense, and distribute the\par - Work and such Derivative Works in Source or Object form.\par -\par - 3. Grant of Patent License. Subject to the terms and conditions of\par - this License, each Contributor hereby grants to You a perpetual,\par - worldwide, non-exclusive, no-charge, royalty-free, irrevocable\par - (except as stated in this section) patent license to make, have made,\par - use, offer to sell, sell, import, and otherwise transfer the Work,\par - where such license applies only to those patent claims licensable\par - by such Contributor that are necessarily infringed by their\par - Contribution(s) alone or by combination of their Contribution(s)\par - with the Work to which such Contribution(s) was submitted. If You\par - institute patent litigation against any entity (including a\par - cross-claim or counterclaim in a lawsuit) alleging that the Work\par - or a Contribution incorporated within the Work constitutes direct\par - or contributory patent infringement, then any patent licenses\par - granted to You under this License for that Work shall terminate\par - as of the date such litigation is filed.\par -\par - 4. Redistribution. You may reproduce and distribute copies of the\par - Work or Derivative Works thereof in any medium, with or without\par - modifications, and in Source or Object form, provided that You\par - meet the following conditions:\par -\par - (a) You must give any other recipients of the Work or\par - Derivative Works a copy of this License; and\par -\par - (b) You must cause any modified files to carry prominent notices\par - stating that You changed the files; and\par -\par - (c) You must retain, in the Source form of any Derivative Works\par - that You distribute, all copyright, patent, trademark, and\par - attribution notices from the Source form of the Work,\par - excluding those notices that do not pertain to any part of\par - the Derivative Works; and\par -\par - (d) If the Work includes a "NOTICE" text file as part of its\par - distribution, then any Derivative Works that You distribute must\par - include a readable copy of the attribution notices contained\par - within such NOTICE file, excluding those notices that do not\par - pertain to any part of the Derivative Works, in at least one\par - of the following places: within a NOTICE text file distributed\par - as part of the Derivative Works; within the Source form or\par - documentation, if provided along with the Derivative Works; or,\par - within a display generated by the Derivative Works, if and\par - wherever such third-party notices normally appear. The contents\par - of the NOTICE file are for informational purposes only and\par - do not modify the License. You may add Your own attribution\par - notices within Derivative Works that You distribute, alongside\par - or as an addendum to the NOTICE text from the Work, provided\par - that such additional attribution notices cannot be construed\par - as modifying the License.\par -\par - You may add Your own copyright statement to Your modifications and\par - may provide additional or different license terms and conditions\par - for use, reproduction, or distribution of Your modifications, or\par - for any such Derivative Works as a whole, provided Your use,\par - reproduction, and distribution of the Work otherwise complies with\par - the conditions stated in this License.\par -\par - 5. Submission of Contributions. Unless You explicitly state otherwise,\par - any Contribution intentionally submitted for inclusion in the Work\par - by You to the Licensor shall be under the terms and conditions of\par - this License, without any additional terms or conditions.\par - Notwithstanding the above, nothing herein shall supersede or modify\par - the terms of any separate license agreement you may have executed\par - with Licensor regarding such Contributions.\par -\par - 6. Trademarks. This License does not grant permission to use the trade\par - names, trademarks, service marks, or product names of the Licensor,\par - except as required for reasonable and customary use in describing the\par - origin of the Work and reproducing the content of the NOTICE file.\par -\par - 7. Disclaimer of Warranty. Unless required by applicable law or\par - agreed to in writing, Licensor provides the Work (and each\par - Contributor provides its Contributions) on an "AS IS" BASIS,\par - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\par - implied, including, without limitation, any warranties or conditions\par - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\par - PARTICULAR PURPOSE. You are solely responsible for determining the\par - appropriateness of using or redistributing the Work and assume any\par - risks associated with Your exercise of permissions under this License.\par -\par - 8. Limitation of Liability. In no event and under no legal theory,\par - whether in tort (including negligence), contract, or otherwise,\par - unless required by applicable law (such as deliberate and grossly\par - negligent acts) or agreed to in writing, shall any Contributor be\par - liable to You for damages, including any direct, indirect, special,\par - incidental, or consequential damages of any character arising as a\par - result of this License or out of the use or inability to use the\par - Work (including but not limited to damages for loss of goodwill,\par - work stoppage, computer failure or malfunction, or any and all\par - other commercial damages or losses), even if such Contributor\par - has been advised of the possibility of such damages.\par -\par - 9. Accepting Warranty or Additional Liability. While redistributing\par - the Work or Derivative Works thereof, You may choose to offer,\par - and charge a fee for, acceptance of support, warranty, indemnity,\par - or other liability obligations and/or rights consistent with this\par - License. However, in accepting such obligations, You may act only\par - on Your own behalf and on Your sole responsibility, not on behalf\par - of any other Contributor, and only if You agree to indemnify,\par - defend, and hold each Contributor harmless for any liability\par - incurred by, or claims asserted against, such Contributor by reason\par - of your accepting any such warranty or additional liability.\par -\par - END OF TERMS AND CONDITIONS\par -\par - APPENDIX: How to apply the Apache License to your work.\par -\par - To apply the Apache License to your work, attach the following\par - boilerplate notice, with the fields enclosed by brackets "[]"\par - replaced with your own identifying information. (Don't include\par - the brackets!) The text should be enclosed in the appropriate\par - comment syntax for the file format. We also recommend that a\par - file or class name and description of purpose be included on the\par - same "printed page" as the copyright notice for easier\par - identification within third-party archives.\par -\par - Copyright 2021 Sumo Logic Inc.\par -\par - Licensed under the Apache License, Version 2.0 (the "License");\par - you may not use this file except in compliance with the License.\par - You may obtain a copy of the License at\par -\par - http://www.apache.org/licenses/LICENSE-2.0\par -\par - Unless required by applicable law or agreed to in writing, software\par - distributed under the License is distributed on an "AS IS" BASIS,\par - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\par - See the License for the specific language governing permissions and\par - limitations under the License.\par -\par -Contains code from https://github.com/SumoLogic/telegraf/blob/master/LICENSE\par -under the MIT license in the following directory:\par -https://github.com/SumoLogic/sumologic-otel-collector/tree/main/pkg/receiver/telegrafreceiver\par -\par -The MIT License (MIT)\par -\par -Copyright (c) 2015-2020 InfluxData Inc.\par -\par -Permission is hereby granted, free of charge, to any person obtaining a copy\par -of this software and associated documentation files (the "Software"), to deal\par -in the Software without restriction, including without limitation the rights\par -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\par -copies of the Software, and to permit persons to whom the Software is\par -furnished to do so, subject to the following conditions:\par -\par -The above copyright notice and this permission notice shall be included in all\par -copies or substantial portions of the Software.\par -\par -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\par -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\par -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\par -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\par -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\par -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\par -SOFTWARE.\par -\par -} - diff --git a/packaging/msi/wix/assets/banner_background.bmp b/packaging/msi/wix/assets/banner_background.bmp deleted file mode 100644 index 8ea0a1292a4c8a30eb39db444f8cc4c8d29b35e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114432 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/msi/wix/folders.wxs b/packaging/msi/wix/folders.wxs deleted file mode 100644 index 35d209252b..0000000000 --- a/packaging/msi/wix/folders.wxs +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/msi/wix/otelcol-sumo.wixproj b/packaging/msi/wix/otelcol-sumo.wixproj deleted file mode 100644 index e538f9fb35..0000000000 --- a/packaging/msi/wix/otelcol-sumo.wixproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - 1.0.0.0 - 25ec8859-fe5e-4110-a6e4-915b6ed83072 - 33D8E84A-1581-41DC-AF17-E48459B895C5 - en-US - none - $([System.IO.Path]::GetFullPath('..\..\..')) - false - - - - ICE61 - - - - bin\$(Platform)\ - obj\$(Platform)\ - - - - otelcol-sumo_$(ProductVersion)_en-US.$(Platform) - - - - otelcol-sumo_$(ProductVersion)_en-US.$(Platform)-fips - - - - $(DefineConstants);ProductVersion=$(ProductVersion) - $(DefineConstants);UpgradeCode=$(UpgradeCode) - - - - - - - - - - - SumoLogic - - - - - - - - - - - - - - - true - - - - - - - - - - diff --git a/packaging/msi/wix/package.en-us.wxl b/packaging/msi/wix/package.en-us.wxl deleted file mode 100644 index b677409a10..0000000000 --- a/packaging/msi/wix/package.en-us.wxl +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/msi/wix/package.wxs b/packaging/msi/wix/package.wxs deleted file mode 100644 index 4903853990..0000000000 --- a/packaging/msi/wix/package.wxs +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/msi/wix/ui/appdata-dir-dlg.wxs b/packaging/msi/wix/ui/appdata-dir-dlg.wxs deleted file mode 100644 index 5736fc8de1..0000000000 --- a/packaging/msi/wix/ui/appdata-dir-dlg.wxs +++ /dev/null @@ -1,28 +0,0 @@ - - - - -

- - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/msi/wix/ui/otelcol-sumo.wxs b/packaging/msi/wix/ui/otelcol-sumo.wxs deleted file mode 100644 index 73765b66af..0000000000 --- a/packaging/msi/wix/ui/otelcol-sumo.wxs +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packaging/msi/wix/variables.wxi b/packaging/msi/wix/variables.wxi deleted file mode 100644 index 2b6c3ba33f..0000000000 --- a/packaging/msi/wix/variables.wxi +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - -