├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ ├── PublishToMarketPlace.yml │ ├── PublishToOpenVsx.yml │ ├── art.yaml │ ├── main.yml │ └── test_matrix.yml ├── .gitignore ├── .markdownlint.yml ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README_docs ├── fast.md ├── images │ ├── as3SchemaInYaml.PNG │ ├── as3_snippet_9.9.2020.gif │ ├── f5-demo-1_4.27.2020.gif │ ├── f5-demo-hostMgmt_5.7.2020.gif │ ├── f5-demo-postAS3_5.7.2020.gif │ ├── vscode-f5-fast_as3TenantTree_5.15.2020.PNG │ ├── vscode-f5-fast_mainView_5.15.2020.PNG │ ├── vscode-fast_demo_01.png │ ├── vscodeDebugConsole_5.20.2020.PNG │ └── vscode_statusBar_colors.PNG ├── rawApiCalls.md ├── research.md ├── rpmMgmt.md ├── schemaValidation.md ├── tcl.md ├── tools.md └── vsc-extension-quickstart.md ├── cache └── atcVersions.json ├── diagRules └── tmosXcRules.json ├── docs ├── .nojekyll ├── README.md ├── _coverpage.md ├── _navbar.md ├── _sidebar.md ├── as3.md ├── assets │ ├── main.css │ └── main.js ├── atc_rpm_mgmt.md ├── config_explorer.md ├── device_importing.md ├── do_ts.md ├── fast.md ├── general.md ├── generic_rest_calls.md ├── index.html ├── media │ ├── AS3_2_FAST_YAML_02.09.2021.gif │ ├── AS3_deployed_2_FAST_YAML_02.09.2021.gif │ ├── FAST_as3JSON_to_mst_6.22.2020.PNG │ ├── FAST_deleteApp_6.23.2020.gif │ ├── FAST_deployApp_6.23.2020.gif │ ├── FAST_mst_ADC_Declaration_6.23.2020.PNG │ ├── FAST_mst_template_params_6.23.2020.PNG │ ├── FAST_tempSet_upload_6.23.2020.gif │ ├── FAST_view_6.23.2020.PNG │ ├── OUTPUT_logging_9.9.2020.PNG │ ├── addDeviceConnect_11.04.2020.gif │ ├── appMove_tclMerge_11.04.2020.gif │ ├── as3GetPostDeleteTask_5.18.2020.gif │ ├── as3SchemaInYaml.PNG │ ├── as3SnippetDemo_11.04.2020.gif │ ├── as3_snippet_9.9.2020.gif │ ├── base64_11.04.2020.gif │ ├── configExplerSearching_3.7.2021.gif │ ├── configExplore_clear_11.04.2020.PNG │ ├── connectDisPassCache_5.18.2020.gif │ ├── deviceMgmt_5.18.2020.gif │ ├── exploreUCS_11.04.2020.gif │ ├── exploreUCS_multiSelect_11.04.2020.gif │ ├── f5.png │ ├── f5_24x24.svg │ ├── f5_white_24x24.svg │ ├── fastTemplatePreview_11.04.2020.gif │ ├── favicon.png │ ├── getModifyDO_5.18.2020.gif │ ├── getModifyTS_5.18.2020.gif │ ├── github.svg │ ├── hostsView_labelsConfig.gif │ ├── injectSchema_existingBroken_v2.8.0_10.30.2020.gif │ ├── injectSchema_existing_v2.8.0_10.30.2020.gif │ ├── injectSchema_v2.8.0_10.30.2020.gif │ ├── installTsRpm_11.04.2020.gif │ ├── installWithinCode_11.04.2020.gif │ ├── json_yaml_coverter_11.04.2020.gif │ ├── onConnect_11.05.2020.gif │ ├── remoteCMD_5.18.2020.gif │ ├── tcl_createModifyDelete_iApp_8.21.2020.gif │ ├── tcl_createModifyDelete_rule_8.21.2020.gif │ ├── tcl_setting_8.21.2020.PNG │ ├── unInstallRPM_11.04.2020.gif │ ├── uploadFastTemplates_11.04.2020.gif │ ├── vscode_extensions_icon.PNG │ ├── xcApps.PNG │ ├── xcDiagRules.PNG │ └── xcGettingStarted.PNG ├── schemaRefVariables.md ├── schema_validation.md ├── tcl.md ├── utilities.md └── xcDiagnostics.md ├── images ├── BIG-IQ-sticker_transparent.png ├── addDeviceConnect_11.04.2020.gif ├── as3SnippetDemo_11.04.2020.gif ├── big-iq-centralized-mngmnt.svg ├── bigiq1.svg ├── bigiq_text.svg ├── f5.png ├── f5_24x24.svg ├── f5_open.svg ├── f5_open_dark.svg ├── f5_open_light.svg ├── f5_white_24x24.svg ├── greenCheck.svg ├── greenDot.svg ├── greyLine.svg ├── installWithinCode_11.04.2020.gif ├── next12-cm.svg ├── next12.svg ├── orangeDot.svg ├── redDot.svg ├── swagger.svg ├── vscode_extensions_icon.PNG └── yellowDot.svg ├── language-configuration.json ├── package-lock.json ├── package.json ├── snippets ├── fastYamlSnippets.json └── snippets.json ├── src ├── as3Core.ts ├── bigiqCore.ts ├── cfCore.ts ├── cfgExploreCore.ts ├── changeVersion.ts ├── codeLens.ts ├── deviceImport.ts ├── devicesCore.ts ├── doCore.ts ├── editorViews │ ├── editorView.ts │ └── fastWebView.ts ├── extLoader.ts ├── extension.ts ├── extensionVariables.ts ├── f5Client.ts ├── fastCore.ts ├── hovers.ts ├── logger.ts ├── models.ts ├── proxy_issue#88.md ├── rpmCore.ts ├── tclCore.ts ├── telemetry.ts ├── test │ ├── runTest.ts │ ├── suite │ │ ├── deviceImport.tests.ts │ │ ├── deviceMgmt.test.ts │ │ ├── extension.test.ts │ │ ├── index.ts │ │ └── rawAPI.test.ts │ └── testingProceedure.md ├── tmosXcDiag.ts ├── tokenTimer.ts ├── treeViewsProviders │ ├── as3TreeProvider.ts │ ├── bigipTreeProvider.ts │ ├── bigiqTreeProvider.ts │ ├── cfgTreeProvider.ts │ ├── fastTreeProvider.ts │ ├── githubDecExamples.ts │ ├── hostsTreeProvider.ts │ └── tclTreeProvider.ts ├── utils │ ├── f5FastApi.ts │ ├── f5FastUtils.ts │ ├── rpmMgmt.ts │ └── utils.ts └── x509.ts ├── styles └── webView.css ├── tcl.tmGrammars.json └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | *.http 2 | 3 | 4 | { 5 | "ignorePatterns": ["*.http", "**/vendor/*.js"], 6 | "rules": { 7 | //... 8 | } 9 | } -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "plugins": [ 9 | "@typescript-eslint" 10 | ], 11 | "rules": { 12 | "@typescript-eslint/semi": "warn", 13 | "curly": "warn", 14 | "eqeqeq": "warn", 15 | "no-throw-literal": "warn", 16 | "semi": "off" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/PublishToMarketPlace.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow that is manually triggered 2 | 3 | name: Publish to Marketplace 4 | 5 | # on: 6 | # release: 7 | # # Only use the types keyword to narrow down the activity types that will trigger your workflow. 8 | # # types: [published] 9 | # types: [published, created, edited] 10 | 11 | # curl -sL https://api.github.com/repos/f5devcentral/vscode-f5/releases/latest | jq .assets[0].browser_download_url 12 | # "https://github.com/f5devcentral/vscode-f5/releases/download/v2.3.0/vscode-f5-fast-2.3.0.vsix" 13 | 14 | # single line command to download latest release 15 | # curl -sL https://api.github.com/repos/f5devcentral/vscode-f5/releases/latest | jq .assets[0].browser_download_url | xargs wget 16 | 17 | 18 | on: 19 | workflow_dispatch: 20 | 21 | jobs: 22 | Build_Publish: 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | - uses: actions/checkout@v2 27 | - uses: actions/setup-node@v1 28 | with: 29 | node-version: 12 30 | 31 | - name: npm install everything 32 | run: npm install 33 | 34 | # - name: Publish to Open VSX Registry 35 | # id: publishToOpenVSX 36 | # uses: HaaLeo/publish-vscode-extension@v0 37 | # with: 38 | # pat: ${{ secrets.OPEN_VSX_TOKEN }} 39 | # # extensionFile: ${{ steps.get_release_name.outputs.name }} 40 | # # packagePath: '' 41 | # # dryRun: true 42 | 43 | # - name: display open vsx output 44 | # run: 45 | # echo ${{ steps.publishToOpenVSX.outputs.vsixPath }} 46 | # echo ${{ steps.get_release_name.outputs.name }} 47 | 48 | - name: Publish to Visual Studio Marketplace 49 | uses: HaaLeo/publish-vscode-extension@v0 50 | with: 51 | pat: ${{ secrets.MARKETPLACE_PUBLISH_KEY }} 52 | registryUrl: https://marketplace.visualstudio.com 53 | # extensionFile: ${{ steps.publishToOpenVSX.outputs.vsixPath }} 54 | # extensionFile: ${{ steps.get_release_name.outputs.name }} 55 | # packagePath: '' 56 | # dryRun: true 57 | -------------------------------------------------------------------------------- /.github/workflows/PublishToOpenVsx.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow that is manually triggered 2 | 3 | name: Publish to OpenVSX 4 | 5 | # on: 6 | # release: 7 | # # Only use the types keyword to narrow down the activity types that will trigger your workflow. 8 | # # types: [published] 9 | # types: [published, created, edited] 10 | 11 | # curl -sL https://api.github.com/repos/f5devcentral/vscode-f5/releases/latest | jq .assets[0].browser_download_url 12 | # "https://github.com/f5devcentral/vscode-f5/releases/download/v2.3.0/vscode-f5-fast-2.3.0.vsix" 13 | 14 | # single line command to download latest release 15 | # curl -sL https://api.github.com/repos/f5devcentral/vscode-f5/releases/latest | jq .assets[0].browser_download_url | xargs wget 16 | 17 | 18 | on: 19 | workflow_dispatch: 20 | 21 | jobs: 22 | Build_Publish: 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | - uses: actions/checkout@v2 27 | - uses: actions/setup-node@v1 28 | with: 29 | node-version: 12 30 | 31 | # - name: get latest release name 32 | # id: get_release_name 33 | # run: echo ::set-output name=name::$(curl -sL https://api.github.com/repos/f5devcentral/vscode-f5/releases/latest | jq .assets[0].name) 34 | # # outputs: 35 | # # releaseName: 36 | # # description: 'full name of the release' 37 | 38 | # - name: display release name from output 39 | # # run: echo ${{ outputs.releaseName.value }} 40 | # run: echo ${{ steps.get_release_name.outputs.name }} 41 | 42 | # - name: download latest release 43 | # run: "curl -sL https://api.github.com/repos/f5devcentral/vscode-f5/releases/latest | jq .assets[0].browser_download_url | xargs wget" 44 | # shell: bash 45 | 46 | # - name: list directory 47 | # run: ls -la 48 | # shell: bash 49 | 50 | - name: npm install everything 51 | run: npm install 52 | 53 | - name: Publish to Open VSX Registry 54 | id: publishToOpenVSX 55 | uses: HaaLeo/publish-vscode-extension@v0 56 | with: 57 | pat: ${{ secrets.OPEN_VSX_TOKEN }} 58 | # extensionFile: ${{ steps.get_release_name.outputs.name }} 59 | # packagePath: '' 60 | # dryRun: true 61 | 62 | # - name: display open vsx output 63 | # run: 64 | # echo ${{ steps.publishToOpenVSX.outputs.vsixPath }} 65 | # echo ${{ steps.get_release_name.outputs.name }} 66 | 67 | # - name: Publish to Visual Studio Marketplace 68 | # uses: HaaLeo/publish-vscode-extension@v0 69 | # with: 70 | # pat: ${{ secrets.MARKETPLACE_PUBLISH_KEY }} 71 | # registryUrl: https://marketplace.visualstudio.com 72 | # extensionFile: ${{ steps.publishToOpenVSX.outputs.vsixPath }} 73 | # # extensionFile: ${{ steps.get_release_name.outputs.name }} 74 | # packagePath: '' 75 | # # dryRun: true 76 | -------------------------------------------------------------------------------- /.github/workflows/art.yaml: -------------------------------------------------------------------------------- 1 | name: "art" 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | env: 7 | NODE_VERSION: 14.x 8 | 9 | jobs: 10 | 11 | 12 | 13 | package-release-publish: 14 | runs-on: ubuntu-latest 15 | environment: publishing 16 | name: Package-Release-Publish 17 | steps: 18 | 19 | - name: Checkout code 20 | uses: actions/checkout@v2 21 | 22 | - name: setup node.js ${{ env.NODE_VERSION }} 23 | uses: actions/setup-node@v2 24 | with: 25 | node-version: ${{ env.NODE_VERSION }} 26 | 27 | - name: install node deps 28 | run: npm ci 29 | 30 | - name: capture latest release notes 31 | run: | 32 | echo "RELEASE_NOTE<> $GITHUB_ENV 33 | echo "$(node src/scripts/changelog.js)" >> $GITHUB_ENV 34 | echo "" >> $GITHUB_ENV 35 | echo "See [CHANGE LOG](https://github.com/f5devcentral/vscode-f5/blob/main/README.md) for full details and history." >> $GITHUB_ENV 36 | echo "" >> $GITHUB_ENV 37 | echo 'EOF' >> $GITHUB_ENV 38 | # run: node src/scripts/changelog.js >> releaseNote.txt 39 | 40 | - name: display release notes 41 | run: echo "${{ env.RELEASE_NOTE }}" 42 | 43 | # - name: append release note reference 44 | # run: echo "See [CHANGE LOG](https://github.com/f5devcentral/vscode-f5/blob/main/README.md) for full details." >> releaseNote.txt 45 | 46 | # - name: package extension 47 | # run: vsce package 48 | 49 | # - name: get extension path 50 | # run: echo "VSIX_PATH=$(find . -maxdepth 1 -type f -iname "*.vsix" | head -1)" >> $GITHUB_ENV 51 | 52 | # - name: get extension name 53 | # run: echo "VSIX_NAME=$(basename $(find . -maxdepth 1 -type f -iname "*.vsix" | head -1))" >> $GITHUB_ENV 54 | 55 | - name: get extension version 56 | run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV 57 | 58 | 59 | 60 | # - name: create upload artifacts 61 | # uses: actions/upload-artifact@v2 62 | # with: 63 | # path: ${{ env.VSIX_PATH }} 64 | # name: ${{ env.VSIX_NAME }} 65 | 66 | # - name: create github release 67 | # env: 68 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 69 | # NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 70 | # run: npm -g install @semantic-release/git semantic-release && semantic-release 71 | 72 | - name: create github release 73 | uses: actions/create-release@v1 74 | id: create_release 75 | env: 76 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 77 | with: 78 | tag_name: v${{ env.PACKAGE_VERSION }} 79 | release_name: 'my rel' 80 | body: ${{env.RELEASE_NOTE}} 81 | draft: false 82 | prerelease: false 83 | 84 | # - name: upload releases 85 | # uses: actions/upload-release-asset@v1 86 | # env: 87 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 88 | # PUBLISH_TOKEN: ${{ secrets.MARKETPLACE_PUBLISH_KEY }} 89 | # with: 90 | # upload_url: ${{ steps.create_release.outputs.upload_url }} 91 | # asset_path: ${{ env.VSIX_PATH }} 92 | # asset_name: ${{ env.VSIX_NAME }} 93 | # asset_content_type: application/zip 94 | 95 | # - name: publish to marketplace 96 | # run: vsce publish -i ${{ env.VSIX_PATH }} -p ${{ secrets.MARKETPLACE_PUBLISH_KEY }} 97 | 98 | # - name: publish to open-vsix 99 | # run: ovsx publish ${{ env.VSIX_PATH }} -p ${{ secrets.OPEN_VSX_TOKEN }} 100 | 101 | 102 | 103 | # good example of action workflow for publishing an extension 104 | # https://github.com/politie/omt-odt-language/pull/30/files#diff-87db21a973eed4fef5f32b267aa60fcee5cbdf03c67fafdc2a9b553bb0b15f34 105 | 106 | # vsce source for understanding switches 107 | # https://github.com/microsoft/vscode-vsce/tree/main/src 108 | 109 | # ovsx source 110 | # https://github.com/eclipse/openvsx 111 | 112 | # another ci/cd example 113 | # https://dev.to/shaimendel/vs-code-extension-building-auto-ci-cd-with-github-actions-2dmf 114 | # https://github.com/shaimendel/vscode-plugin-cicd-github-actions/blob/master/.github/workflows/ci.yaml -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: "Main" 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | env: 8 | NODE_VERSION: 22 9 | 10 | jobs: 11 | 12 | test: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [macos-latest, windows-latest, ubuntu-latest] 17 | name: Test on ${{ matrix.os }} 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ env.NODE_VERSION }} 23 | 24 | - run: npm install 25 | - run: xvfb-run -a npm test 26 | if: runner.os == 'Linux' 27 | - run: npm test 28 | if: runner.os != 'Linux' 29 | 30 | package-release-publish: 31 | runs-on: ubuntu-latest 32 | permissions: 33 | contents: write 34 | environment: publishing 35 | needs: test 36 | name: Package-Release-Publish 37 | steps: 38 | 39 | - name: Checkout code 40 | uses: actions/checkout@v4 41 | 42 | - name: setup node.js ${{ env.NODE_VERSION }} 43 | uses: actions/setup-node@v4 44 | with: 45 | node-version: ${{ env.NODE_VERSION }} 46 | 47 | - name: install node deps 48 | run: npm ci 49 | 50 | - name: install vscode marketplace cli (vsce) 51 | run: npm install -g vsce 52 | 53 | - name: install open-vsix marketplace cli (ovsx) 54 | run: npm install -g ovsx 55 | 56 | # - name: install teem keys 57 | # run: echo "${{ secrets.TEEM_KEY }}" >> TEEM_KEY 58 | 59 | - name: package extension 60 | id: vsce 61 | run: vsce package 62 | 63 | - name: get extension path 64 | run: echo "VSIX_PATH=$(find . -maxdepth 1 -type f -iname "*.vsix" | head -1)" >> $GITHUB_ENV 65 | 66 | - name: get extension name 67 | run: echo "VSIX_NAME=$(basename $(find . -maxdepth 1 -type f -iname "*.vsix" | head -1))" >> $GITHUB_ENV 68 | 69 | - name: get extension version 70 | run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV 71 | 72 | # https://github.com/marketplace/actions/changelog-reader 73 | - name: Get Changelog Entry 74 | id: changelog_reader 75 | uses: mindsers/changelog-reader-action@v2 76 | with: 77 | validation_level: warn 78 | version: ${{ env.PACKAGE_VERSION }} 79 | path: ./CHANGELOG.md 80 | 81 | - name: create upload artifacts 82 | uses: actions/upload-artifact@v4 83 | with: 84 | path: ${{ env.VSIX_PATH }} 85 | name: ${{ env.VSIX_NAME }} 86 | 87 | - name: create github release 88 | uses: ncipollo/release-action@v1 89 | id: create_release 90 | with: 91 | tag: v${{ env.PACKAGE_VERSION }} 92 | name: ${{ env.VSIX_NAME }} 93 | body: "${{ steps.changelog_reader.outputs.changes }}" 94 | artifacts: ${{ env.VSIX_NAME }} 95 | draft: false 96 | prerelease: false 97 | 98 | # - name: upload releases 99 | # uses: actions/upload-release-asset@v1 100 | # env: 101 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 102 | # PUBLISH_TOKEN: ${{ secrets.MARKETPLACE_PUBLISH_KEY }} 103 | # with: 104 | # upload_url: ${{ steps.create_release.outputs.upload_url }} 105 | # asset_path: ${{ env.VSIX_PATH }} 106 | # asset_name: ${{ env.VSIX_NAME }} 107 | # asset_content_type: application/zip 108 | 109 | - name: publish to marketplace 110 | run: vsce publish -i ${{ env.VSIX_PATH }} -p ${{ secrets.MARKETPLACE_PUBLISH_KEY }} 111 | 112 | - name: publish to open-vsix 113 | run: ovsx publish ${{ env.VSIX_PATH }} -p ${{ secrets.OPEN_VSX_TOKEN }} 114 | 115 | 116 | 117 | # good example of action workflow for publishing an extension 118 | # https://github.com/politie/omt-odt-language/pull/30/files#diff-87db21a973eed4fef5f32b267aa60fcee5cbdf03c67fafdc2a9b553bb0b15f34 119 | 120 | # vsce source for understanding switches 121 | # https://github.com/microsoft/vscode-vsce/tree/main/src 122 | 123 | # ovsx source 124 | # https://github.com/eclipse/openvsx 125 | 126 | # another ci/cd example 127 | # https://dev.to/shaimendel/vs-code-extension-building-auto-ci-cd-with-github-actions-2dmf 128 | # https://github.com/shaimendel/vscode-plugin-cicd-github-actions/blob/master/.github/workflows/ci.yaml -------------------------------------------------------------------------------- /.github/workflows/test_matrix.yml: -------------------------------------------------------------------------------- 1 | name: "test-matrix" 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - "!main" 8 | 9 | env: 10 | NODE_VERSION: 14.x 11 | 12 | jobs: 13 | 14 | test: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | matrix: 18 | os: [windows-latest, ubuntu-latest, macos-latest] 19 | name: Test on ${{ matrix.os }} 20 | steps: 21 | - uses: actions/checkout@v2 22 | - uses: actions/setup-node@v2 23 | with: 24 | node-version: ${{ env.NODE_VERSION }} 25 | - run: /usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & echo "Started xvfb" 26 | shell: bash 27 | if: ${{ success() && matrix.os == 'ubuntu-latest' }} 28 | - run: npm install 29 | - name: Cache node modules 30 | uses: actions/cache@v2 31 | env: 32 | cache-name: cache-node-modules 33 | with: 34 | # npm cache files are stored in `~/.npm` on Linux/macOS 35 | path: ~/.npm 36 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} 37 | restore-keys: | 38 | ${{ runner.os }}-build-${{ env.cache-name }}- 39 | ${{ runner.os }}-build- 40 | ${{ runner.os }}- 41 | - run: npm test 42 | env: 43 | DISPLAY: ":99.0" 44 | CI: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore 'out' directory which holds all the js files from TS compile 2 | out 3 | # any "old" files I'm pending removal... 4 | .old 5 | 6 | # ignore directory that holds node_modules, these should be installed when npm installs the necessary packages from the package.json file 7 | node_modules 8 | 9 | # ignore ilx rpm cache directory 10 | atc_ilx_rpm_cache 11 | .vscode-test/ 12 | # ignore any extension install files and zips 13 | *.vsix 14 | *.zip 15 | /fastTemplateUpload/ 16 | /fastTemplateFolderUploadTemp/ 17 | *.http 18 | /restTests/ 19 | 20 | 21 | # ignore f5 iApp template files 22 | *.tmpl 23 | # ignore temp mini_ucs for config explorere (corkscrew) 24 | mini_ucs.tar.gz 25 | # ignore node cpu profiling outputs 26 | *.cpuprofile 27 | # ignore big dev files in cache 28 | cache/*.rpm 29 | cache/*.sha256 30 | cache/*.qkview 31 | cache/*.ucs -------------------------------------------------------------------------------- /.markdownlint.yml: -------------------------------------------------------------------------------- 1 | MD024: false 2 | MD013: false 3 | MD033: false 4 | MD012: false -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "bitwisecook.iapp", 6 | "bitwisecook.irule", 7 | "f5devcentral.vscode-f5-chariot" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/out/**/*.js" 18 | ], 19 | "preLaunchTask": "${defaultBuildTask}" 20 | }, 21 | { 22 | "name": "Extension Tests", 23 | "type": "extensionHost", 24 | "request": "launch", 25 | "runtimeExecutable": "${execPath}", 26 | "args": [ 27 | "--extensionDevelopmentPath=${workspaceFolder}", 28 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" 29 | ], 30 | "outFiles": [ 31 | "${workspaceFolder}/out/test/**/*.js" 32 | ], 33 | "preLaunchTask": "${defaultBuildTask}" 34 | }, 35 | { 36 | "name": "Debug current test", 37 | "type": "node", 38 | "request": "launch", 39 | "runtimeVersion": "16.18.0", 40 | "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", 41 | "args": [ 42 | "-r", 43 | "ts-node/register", 44 | "-u", 45 | "tdd", 46 | "--no-timeout", 47 | "--colors", 48 | "${file}", 49 | ], 50 | "internalConsoleOptions": "neverOpen", 51 | }, 52 | { 53 | "name": "device import Tests", 54 | "type": "node", 55 | "request": "launch", 56 | "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", 57 | "args": [ 58 | "-r", 59 | "ts-node/register", 60 | "--timeout", 61 | "999999", 62 | "--colors", 63 | "${workspaceFolder}/src/test/suite/deviceImport.tests.ts", 64 | ], 65 | "internalConsoleOptions": "neverOpen", 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off", 11 | "workbench.colorCustomizations": { 12 | "activityBar.activeBackground": "#600215", 13 | "activityBar.activeBorder": "#1b7d03", 14 | "activityBar.background": "#600215", 15 | "activityBar.foreground": "#e7e7e7", 16 | "activityBar.inactiveForeground": "#e7e7e799", 17 | "activityBarBadge.background": "#1b7d03", 18 | "activityBarBadge.foreground": "#e7e7e7", 19 | "statusBar.background": "#2e010a", 20 | "statusBar.foreground": "#e7e7e7", 21 | "statusBarItem.hoverBackground": "#600215", 22 | "titleBar.activeBackground": "#2e010a", 23 | "titleBar.activeForeground": "#e7e7e7", 24 | "titleBar.inactiveBackground": "#2e010a99", 25 | "titleBar.inactiveForeground": "#e7e7e799", 26 | "sash.hoverBorder": "#600215", 27 | "statusBarItem.remoteBackground": "#2e010a", 28 | "statusBarItem.remoteForeground": "#e7e7e7", 29 | "commandCenter.border": "#e7e7e799" 30 | }, 31 | "peacock.remoteColor": "#2e010a", 32 | "peacock.color": "#2e010a", 33 | "typescript.tsdk": "node_modules/typescript/lib" 34 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/test/** 4 | # ignore new documentation site 5 | docs/** 6 | # ignore source typescript files 7 | src/** 8 | .gitignore 9 | # ignore original readme docs 10 | README_docs/** 11 | vsc-extension-quickstart.md 12 | **/tsconfig.json 13 | **/.eslintrc.json 14 | **/*.map 15 | **/*.ts 16 | # **/*.gif 17 | # ignore cache directories 18 | atc_ilx_rpm_cache/** 19 | cache/** 20 | fastTemplateFolderUploadTemp/** 21 | # ignore test seed file 22 | *.vscode-f5.json 23 | # ignore github actions 24 | .github/** 25 | # ignore node cpu profiling file 26 | *.cpuprofile 27 | *.qkview -------------------------------------------------------------------------------- /README_docs/fast.md: -------------------------------------------------------------------------------- 1 | # FAST Templates information 2 | 3 | [BACK TO MAIN README](../README.md) 4 | 5 | --- 6 | 7 | Details about FAST templates, authoring and uploading 8 | 9 | ## Commands -------------------------------------------------------------------------------- /README_docs/images/as3SchemaInYaml.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/as3SchemaInYaml.PNG -------------------------------------------------------------------------------- /README_docs/images/as3_snippet_9.9.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/as3_snippet_9.9.2020.gif -------------------------------------------------------------------------------- /README_docs/images/f5-demo-1_4.27.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/f5-demo-1_4.27.2020.gif -------------------------------------------------------------------------------- /README_docs/images/f5-demo-hostMgmt_5.7.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/f5-demo-hostMgmt_5.7.2020.gif -------------------------------------------------------------------------------- /README_docs/images/f5-demo-postAS3_5.7.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/f5-demo-postAS3_5.7.2020.gif -------------------------------------------------------------------------------- /README_docs/images/vscode-f5-fast_as3TenantTree_5.15.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/vscode-f5-fast_as3TenantTree_5.15.2020.PNG -------------------------------------------------------------------------------- /README_docs/images/vscode-f5-fast_mainView_5.15.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/vscode-f5-fast_mainView_5.15.2020.PNG -------------------------------------------------------------------------------- /README_docs/images/vscode-fast_demo_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/vscode-fast_demo_01.png -------------------------------------------------------------------------------- /README_docs/images/vscodeDebugConsole_5.20.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/vscodeDebugConsole_5.20.2020.PNG -------------------------------------------------------------------------------- /README_docs/images/vscode_statusBar_colors.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/images/vscode_statusBar_colors.PNG -------------------------------------------------------------------------------- /README_docs/rawApiCalls.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Make HTTP/S Request documentation and examples 4 | 5 | [BACK TO MAIN README](../README.md) 6 | 7 | --- 8 | 9 | This function provides the necessary flexbility to make any API call to ANYthing 10 | 11 | Highlight text, right-click, select: `Make HTTPS Request` 12 | 13 | ## Calls without "http" in url 14 | This assumes the request is intented for the currently connected device, of which host details are already known. 15 | 16 | K13225405: Common iControl REST API command examples 17 | - https://support.f5.com/csp/article/K13225405 18 | 19 | ### simple url as string 20 | ``` 21 | /mgmt/tm/sys/clock 22 | ``` 23 | 24 | ### simple url in yaml format 25 | ``` 26 | url: /mgmt/tm/sys/clock 27 | ``` 28 | 29 | ### simple url in json format 30 | ``` 31 | { 32 | "url": "/mgmt/tm/sys/clock" 33 | } 34 | ``` 35 | 36 | ### list vlans 37 | ``` 38 | /mgmt/tm/net/vlan/ 39 | ``` 40 | 41 | 42 | 43 | ### url post in yaml 44 | ``` 45 | url: /mgmt/shared/authn/login 46 | method: POST 47 | body: 48 | username: user1 49 | password: dobgispet 50 | ``` 51 | 52 | ### url post in yaml 53 | ``` 54 | url: /mgmt/tm/sys/config 55 | method: POST 56 | body: 57 | command: save 58 | ``` 59 | 60 | ### list sys options 61 | ``` 62 | /mgmt/tm/sys/ 63 | ``` 64 | 65 | ### list sys ucs 66 | ``` 67 | /mgmt/tm/sys/ucs/ 68 | ``` 69 | 70 | ### url post in json 71 | ``` 72 | { 73 | "url": "/mgmt/shared/authn/login", 74 | "method": "POST", 75 | "body": { 76 | "username": "todai", 77 | "password": "dobgispet" 78 | } 79 | } 80 | ``` 81 | 82 | --- 83 | 84 | ## Calls for outside f5 85 | 86 | The command will detect if the url has "http", if found, it considers it a fully qualified request destined for something outside of a device defined within the extension 87 | 88 | Default HTTP method = GET 89 | 90 | data, or body, must also include 'POST' HTTP method 91 | 92 | ### Simple get 93 | ``` 94 | https://api.chucknorris.io/jokes/random 95 | ``` 96 | 97 | ### simple get in yaml 98 | ``` 99 | url: https://api.chucknorris.io/jokes/random 100 | ``` 101 | 102 | ### simple get in yaml - shows broken response 103 | ``` 104 | url: https://broken.extra.io/whah 105 | ``` 106 | 107 | ### simple POST in yaml 108 | ``` 109 | url: https://postman-echo.com/post 110 | method: POST 111 | data: 'hi' 112 | ``` 113 | 114 | ### simple POST in json 115 | ``` 116 | { 117 | "url": "https://postman-echo.com/post", 118 | "method": "POST", 119 | "data": "hi" 120 | } 121 | ``` 122 | 123 | -------------------------------------------------------------------------------- /README_docs/rpmMgmt.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /README_docs/schemaValidation.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Research 5 | 6 |

 

7 | 8 | [BACK TO MAIN README](../README.md) 9 | 10 |

 

11 | 12 | --- 13 | 14 |

 

15 | 16 | ## Schama Validation 17 | 18 |

 

19 | 20 | One of the primary uses of this tool is to provide schema validation of the ATC declaration during the authoring process. Understanding and having constant feedback about the declaration and it's content during development can drastically improve the expereince. 21 | 22 | There is a schema for each of the different ATC services (AS3/DO/TS), these methods apply to all. 23 | 24 | 25 | 26 | > NOTE: Schemas are versioned but are BACKWARD COMPATIBLE, meaning ***ALWAYS USE LATEST SCHEMA VERSION*** to validate any declaration 27 | 28 | 29 | There are two main ways schema validation can be applied: 30 | 31 | ### Untitled document schema or in-declaration direct reference 32 | 33 | Just as documented here: https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/userguide/validate.html, the necessary json schema can be referenced diretly within the declaration. 34 | 35 | This scenario is common when first starting out with automation since it is very easy to open an editor, copy an example declaration and start editing. Since the file has not been saved (with the appropriate file type discussed later), VSCode does not know what schema to apply, therefore, just providing basic json syntax validation. 36 | 37 | The extension contains basics example declaration of AS3/DO/TS, each containing the respective schema. This is a good place to quickly access access an example declaration with schema validation to get started. 38 | 39 | ***See extension Snippets below*** 40 | 41 |

 

42 | 43 | --- 44 | 45 |

 

46 | 47 | ### File Type schema reference 48 | 49 |

 

50 | 51 | The other method of providing schema validation, and recommended method, is through file types. A typical AS3/DO/TS declaration may be saved as a JSON (app1.json) file since that is the structure of the data. To follow on with this, the extension utilizes file sub-types to associate the appropriate schema. 52 | 53 | - *.as3.json 54 | - *.do.json 55 | - *.ts.json 56 | 57 | Examples can be found in the f5-fasting repo 58 | 59 |

 

60 | 61 | --- 62 | 63 |

 

64 | 65 | ## Extension Snippets 66 | 67 |

 

68 | 69 | Snippets are code blocks that are used to quickly insert code within an editor in VSCode. The extension includes the basic example for each of the ATC services (AS3/DO/TS). 70 | 71 | To access the snippets, open an editor file, change the language to JSON, then start typing 'as3', 'do' or 'ts', the hit 'enter". This should insert the example snippet for the respective ATC service. 72 | 73 | > NOTE: these snippets include the direct schema reference 74 | 75 | 76 | drawing 77 | 78 | VSCode guide for defining customer user snippets 79 | https://code.visualstudio.com/docs/editor/userdefinedsnippets 80 | 81 |

 

82 | 83 | --- 84 | 85 |

 

86 | 87 | ## Schema Links 88 | 89 |

 

90 | 91 | ### Latest AS3 Schema 92 | https://raw.githubusercontent.com/F5Networks/f5-appsvcs-extension/main/schema/latest/as3-schema.json 93 | 94 | ### Latest DO Schema 95 | https://raw.githubusercontent.com/F5Networks/f5-declarative-onboarding/HEAD/src/schema/latest/base.schema.json 96 | 97 | ### Latest TS Schema 98 | https://raw.githubusercontent.com/F5Networks/f5-telemetry-streaming/HEAD/src/schema/latest/base_schema.json 99 | 100 |

 

101 | 102 | --- 103 | 104 |

 

105 | 106 | ## Validating YAML ATC Declarations with JSON Schemas 107 | 108 |

 

109 | 110 | 111 | Install the RedHat YAML extension 112 | https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml 113 | 114 | 115 | In the vscode settings for that extension: 116 |

 

117 | 118 | ```json 119 | "yaml.schemas": { 120 | "https://raw.githubusercontent.com/F5Networks/f5-appsvcs-extension/main/schema/latest/as3-schema.json": ["*.as3.yml"], 121 | "https://raw.githubusercontent.com/F5Networks/f5-declarative-onboarding/HEAD/src/schema/latest/base.schema.json": ["*.do.yml"], 122 | "https://raw.githubusercontent.com/F5Networks/f5-telemetry-streaming/HEAD/src/schema/latest/base_schema.json": ["*.ts.*"], 123 | } 124 | ``` 125 |

 

126 | 127 | create a yaml file for as3 like: `as3Dec1.as3.yml ` 128 | 129 | ![example1](./images/as3SchemaInYaml.PNG) -------------------------------------------------------------------------------- /README_docs/tcl.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/README_docs/tcl.md -------------------------------------------------------------------------------- /README_docs/tools.md: -------------------------------------------------------------------------------- 1 | # Tools 2 | 3 | [BACK TO MAIN README](../README.md) 4 | 5 | --- 6 | 7 | Additional tools included to make life easier... 8 | 9 | ## Commands 10 | 11 | 12 | - base64 encode/decode 13 | - json <-> yaml converter 14 | 15 | - raw HTTP rest function? -------------------------------------------------------------------------------- /README_docs/vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | [BACK TO MAIN README](../README.md) 4 | 5 | ## What's in the folder 6 | 7 | * This folder contains all of the files necessary for your extension. 8 | * `package.json` - this is the manifest file in which you declare your extension and command. 9 | * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. 10 | * `src/extension.ts` - this is the main file where you will provide the implementation of your command. 11 | * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. 12 | * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. 13 | 14 | ## Get up and running straight away 15 | 16 | * Press `F5` to open a new window with your extension loaded. 17 | * Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. 18 | * Set breakpoints in your code inside `src/extension.ts` to debug your extension. 19 | * Find output from your extension in the debug console. 20 | 21 | ## Make changes 22 | 23 | * You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. 24 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 25 | 26 | 27 | ## Explore the API 28 | 29 | * You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. 30 | 31 | ## Run tests 32 | 33 | * Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`. 34 | * Press `F5` to run the tests in a new window with your extension loaded. 35 | * See the output of the test result in the debug console. 36 | * Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder. 37 | * The provided test runner will only consider files matching the name pattern `**.test.ts`. 38 | * You can create folders inside the `test` folder to structure your tests any way you want. 39 | 40 | ## Go further 41 | 42 | * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). 43 | * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace. 44 | * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). 45 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # The F5 VSCode Extension 4 | 5 | Let the F5 VSCode Extension supercharge your abilities to write (A)utomated (T)ool(C)hain declarations with snippets, examples and declaration schema validation, and also assist with connecting, deploying, retrieving and updating declarations on F5 devices. 6 | 7 | It can also help with iRules/iApps, BIG-IQ, and regular configuration/migration. 8 | 9 | - GET/POST/DELETE of all ATC services, including FAST/AS3/DO/TS/CF 10 | - links to quickly open related ATC documentation 11 | - Direct access to ATC examples from git repo 12 | - Install/UnInstall of ATC rpms 13 | - Convert JSON <-> YAML 14 | - Hovers to view decoded information for (certificates/base64) 15 | - Extract TMOS applications (per virtual server) 16 | - Write, deploy and modify iRules/iApps (with vscode-irule extension for language support) 17 | 18 | ## Documentation 19 | 20 | 21 | 22 | ## Getting the extension 23 | 24 | The best path is to install Visual Studio Code from: 25 | 26 | ### VSCode Marketplace 27 | 28 | - 29 | 30 | ### Open Source Marketplace 31 | 32 | - 33 | 34 | ### VSCode Marketplace 35 | 36 | - https://marketplace.visualstudio.com/items?itemName=F5DevCentral.vscode-f5 37 | 38 | ### Open Source Marketplace 39 | 40 | - https://open-vsx.org/extension/F5DevCentral/vscode-f5 41 | 42 | Then install the extension following the steps below: 43 | 44 | Select the extensions view 45 | 46 | drawing 47 | 48 | Search for `F5`, select the extension "The F5 Extension", then `Install` 49 | 50 | drawing 51 | 52 | ## Create a device and connect 53 | 54 | Select `Add Host` in the `F5: Hosts` view. Then type in device details in the \@x.x.x.x format, hit `Enter` to submit 55 | 56 | drawing 57 | 58 | ## Deploy example as3 app 59 | 60 | Click on the hostname of the connected device at the bottom of the window. 61 | 62 | > This is the easiest way to get an editor window for JSON files and it also demontrates how to get device details 63 | 64 | Now that we have a json editor, select all text (`control + a`), then `delete`. 65 | 66 | Type `as3` to get the example AS3 snippet, press `Enter`. 67 | 68 | This should insert a sample AS3 declaration into the editor 69 | 70 | > Note the declaration schema reference at the top. This provides instant feedback and validation for any necssary modifications. Please see [Schema Validation](schema_validation.md) for more details 71 | 72 | Right-click in the editor and select `POST as AS3 Declaration`. This should post the declaration to the currently connected device 73 | 74 | !> Please be sure to have the AS3 service installed prior. See [ATC RPM Mgmt](atc_rpm_mgmt.md) for assistance with getting a service installed 75 | 76 | drawing 77 | 78 | ### To delete deployed AS3 tenant from device 79 | 80 | Right-click on the tenant in the AS3 view on the left, then select `Delete Tenant` 81 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ![logo](media/f5.png ':size=30%') 4 | 5 | # F5 VSCode Extension 6 | 7 | > Accelerate your F5 work flows 8 | 9 | - REST based 10 | - VSCode extensible 11 | - F5 ATC SUPERCHARGED! 12 | 13 | [GitHub](https://github.com/f5devcentral/vscode-f5) 14 | [Get Started](#the-f5-vscode-extension) 15 | -------------------------------------------------------------------------------- /docs/_navbar.md: -------------------------------------------------------------------------------- 1 | - Translations 2 | - planned 3 | 4 | - themes 5 | 6 | - Simple 7 | - Simple Dark 8 | - Buble 9 | - Dark 10 | - Pure 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [Home](README.md) 4 | - [General](general.md) 5 | - [Schema Validation](schema_validation.md) 6 | - [AS3](as3.md) 7 | - [DO/TS](do_ts.md) 8 | - [FAST](fast.md) 9 | - [Config Explorer](config_explorer.md) 10 | - [TCL/iRules/iApps](tcl.md) 11 | - [Device Importing](device_importing.md) 12 | - [ATC RPM Mgmt](atc_rpm_mgmt.md) 13 | - [Generic Rest Calls](generic_rest_calls.md) 14 | - [TMOS -> XC Diagnostics](xcDiagnostics.md) 15 | - [Utilities](utilities.md) 16 | - [Change Log](/changelog) 17 | 18 |   19 | 20 | - **Links** 21 | - [![Github](media/github.svg)Github: vscode-f5](https://github.com/f5devcentral/vscode-f5) 22 | - [![Github](media/github.svg)Github: f5-appsvcs-extension](https://github.com/F5Networks/f5-appsvcs-extension) -------------------------------------------------------------------------------- /docs/as3.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # AS3 4 | 5 | ## get/post/delete/tenants/tasks 6 | 7 | Once a device is connected, and the extension detects that AS3 is installed, a status bar will show up on the bottom indicating the running AS3 service verson. 8 | 9 | The AS3 Tenant TreeView on the left shows AS3 tenants and apps for each tenant. Select a tenant to see all the app configuration details for that tenant. You cannot select individual apps from the tree, they are just there for visibility 10 | 11 | The AS3 Tasks TreeVew on the left is just to provide some visibility into the tasks/jobs that the AS3 service has run. 12 | 13 | To post an AS3 declaration, select the command from the palette by pressing `F1`. You may need to search for 'as3' or 'f5'. 14 | 15 | Select the declaration text to send or it will capture the entire editor window 16 | 17 | To delete a tenant, right-click the tenant in the AS3 Tenant TreeView on the left and select `Delete` 18 | 19 | !> As of 11.1.2020 v2.5+ most of these commands are accessible via right click in the editor, as seen below 20 | 21 | drawing 22 | 23 | -------------------------------------------------------------------------------- /docs/assets/main.css: -------------------------------------------------------------------------------- 1 | .markdown-section iframe[src*="buttons.github.io"] { 2 | margin: 0; 3 | } 4 | 5 | figure.thumbnails img { 6 | margin: 0.75em 0; 7 | border-radius: 3px; 8 | box-shadow: 0 2px 6px rgba(0,0,0,0.1), 0 4px 12px rgba(0,0,0,0.15); 9 | } 10 | 11 | @media (min-width: 30em) { 12 | figure.thumbnails:after { 13 | content: ""; 14 | display: table; 15 | clear: both; 16 | } 17 | 18 | figure.thumbnails img { 19 | float: left; 20 | width: calc(50% - 0.75em); 21 | } 22 | 23 | figure.thumbnails img:nth-child(even) { 24 | margin-left: 1.5em; 25 | } 26 | 27 | @supports (display: flex) { 28 | figure.thumbnails { 29 | display: flex; 30 | align-items: center; 31 | } 32 | 33 | figure.thumbnails img { 34 | flex-grow: 1; 35 | width: 0; 36 | } 37 | 38 | figure.thumbnails img + img { 39 | margin: 0 0 0 1.5em; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /docs/assets/main.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // Functions 3 | // ========================================================================= 4 | /** 5 | * Adds event listeners to change active stylesheet and restore previously 6 | * activated stylesheet on reload. 7 | * 8 | * @example 9 | * 10 | * This link: 11 | * Foo 12 | * Will active this existing link: 13 | * 14 | * 15 | * @example 16 | * 17 | * This link: 18 | * Bar 19 | * Will activate this existing link: 20 | * 21 | * Or generate this active link: 22 | * 23 | */ 24 | function initStyleSwitcher() { 25 | var isInitialzed = false; 26 | var sessionStorageKey = 'activeStylesheetHref'; 27 | 28 | function handleSwitch(activeHref, activeTitle) { 29 | var activeElm = document.querySelector('link[href*="' + activeHref +'"],link[title="' + activeTitle +'"]'); 30 | 31 | if (!activeElm && activeHref) { 32 | activeElm = document.createElement('link'); 33 | activeElm.setAttribute('href', activeHref); 34 | activeElm.setAttribute('rel', 'stylesheet'); 35 | activeElm.setAttribute('title', activeTitle); 36 | 37 | document.head.appendChild(activeElm); 38 | 39 | activeElm.addEventListener('load', function linkOnLoad() { 40 | activeElm.removeEventListener('load', linkOnLoad); 41 | setActiveLink(activeElm); 42 | }); 43 | } 44 | else if (activeElm) { 45 | setActiveLink(activeElm); 46 | } 47 | } 48 | 49 | function setActiveLink(activeElm) { 50 | var activeHref = activeElm.getAttribute('href'); 51 | var activeTitle = activeElm.getAttribute('title'); 52 | var inactiveElms = document.querySelectorAll('link[title]:not([href*="' + activeHref +'"]):not([title="' + activeTitle +'"])'); 53 | 54 | // Remove "alternate" keyword 55 | activeElm.setAttribute('rel', (activeElm.rel || '').replace(/\s*alternate/g, '').trim()); 56 | 57 | // Force enable stylesheet (required for some browsers) 58 | activeElm.disabled = true; 59 | activeElm.disabled = false; 60 | 61 | // Store active style sheet 62 | sessionStorage.setItem(sessionStorageKey, activeHref); 63 | 64 | // Disable other elms 65 | for (var i = 0; i < inactiveElms.length; i++) { 66 | var elm = inactiveElms[i]; 67 | 68 | elm.disabled = true; 69 | 70 | // Fix for browsersync and alternate stylesheet updates. Will 71 | // cause FOUC when switching stylesheets during development, but 72 | // required to properly apply style updates when alternate 73 | // stylesheets are enabled. 74 | if (window.browsersyncObserver) { 75 | var linkRel = elm.getAttribute('rel') || ''; 76 | var linkRelAlt = linkRel.indexOf('alternate') > -1 ? linkRel : (linkRel + ' alternate').trim(); 77 | 78 | elm.setAttribute('rel', linkRelAlt); 79 | } 80 | } 81 | 82 | // CSS custom property ponyfil 83 | if ((window.$docsify || {}).themeable) { 84 | window.$docsify.themeable.util.cssVars(); 85 | } 86 | } 87 | 88 | // Event listeners 89 | if (!isInitialzed) { 90 | isInitialzed = true; 91 | 92 | // Restore active stylesheet 93 | document.addEventListener('DOMContentLoaded', function() { 94 | var activeHref = sessionStorage.getItem(sessionStorageKey); 95 | 96 | if (activeHref) { 97 | handleSwitch(activeHref); 98 | } 99 | }); 100 | 101 | // Update active stylesheet 102 | document.addEventListener('click', function(evt) { 103 | var dataHref = evt.target.getAttribute('data-link-href'); 104 | var dataTitle = evt.target.getAttribute('data-link-title') 105 | 106 | if (dataHref || dataTitle) { 107 | dataTitle = dataTitle 108 | || evt.target.textContent 109 | || '_' + Math.random().toString(36).substr(2, 9); // UID 110 | 111 | handleSwitch(dataHref, dataTitle); 112 | evt.preventDefault(); 113 | } 114 | }); 115 | } 116 | } 117 | 118 | // Main 119 | // ========================================================================= 120 | initStyleSwitcher(); 121 | })(); -------------------------------------------------------------------------------- /docs/atc_rpm_mgmt.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ATC ILX RPM MANAGEMENT 4 | 5 | The extension can install and un-install ILX rpms on the connected device 6 | 7 | ## Commands 8 | 9 | * `F5: Install/Update RPM`: Installs selected ATC and version 10 | * Updating an existing rpm to a newer version "should" work but hasn't been thoroughly tested 11 | * Provides a list of ATC tools to install (FAST, AS3, DO, TS) 12 | * When ATC service has been selected, a list of available version is presented 13 | * When a version is selected, the extension will check the local cache 14 | * if already downloaded, upload and install 15 | * if NOT already downloaded, then download from repo, upload to device, install 16 | * Also exposed as a right-click option in the explorer view 17 | * This allows the selection of local ILX RPMs that may be part of a repo 18 | 19 | * `F5: Un-Install RPM`: Un-Installs selected rpm 20 | * Querys the device for currently installed rpm packages 21 | * On select, issues task to delete rpm install 22 | 23 | >**Note: the install/un-install task completes rather quickly but it can take another 20-60 seconds for restnoded/restjavad to complete the restart** 24 | 25 | ## Install 26 | 27 | `F1`, then select `F5: Install RPM`, select the desired ATC service to install 28 | 29 | Select the desired ATC RPM version 30 | 31 | > ATC RPM/versions are queried directly from the respective github repos, so latest versions should be in this list as they are released. 32 | 33 | drawing 34 | 35 | > This process downloads the rpm to the local machine running VSCode (example path: C:\Users\ted\.vscode\extensions\f5devcentral.vscode-f5-2.8.1\atc_ilx_rpm_cache). If the selected version is found in the local cache, cache will be used instead of downloading the rpm every time. Then the rpm is uploaded to the connected device and installed accordingly 36 | 37 | > The `waiting for services to restart` is just a 30 second timer. It doesn't actually monitor the services as they restart (RFE?). So, it may be necessary to disconnect and re-connect to the device to get the statu bars at the bottom to update. 38 | 39 | 40 | ## Uninstall 41 | 42 | `F1`, then select `F5: Un-Install RPM`, select the RPM to uninstall 43 | 44 | drawing 45 | -------------------------------------------------------------------------------- /docs/config_explorer.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Config Explorer 4 | 5 | The configuration explorer is a tool that can take a bigip.conf, ucs, or qkview and provide configuration browsing, including extracted applications 6 | 7 | !> application extraction is in it's early release phase and is based on most common profile options. It is scoped to what is in the bigip.conf (and other partitions). So, things like certificates are not included at this time. 8 | 9 | > INSIDER: The application discovery process does included attempting to discover pools referenced in iRules and Local Traffic Policies 10 | 11 | ## Local UCS/QKVIEW 12 | 13 | By right-clicking on a ucs/qkview in the explorer view, the option to `Explore TMOS Config` should be available 14 | 15 | drawing 16 | 17 | ## Connected Device 18 | 19 | The explore config functionality can also be used on the currently connected device. 20 | 21 | This is accessed by right-clicking on the device name and selecting `Explore Config`. 22 | 23 | !> Must be connected to device first 24 | 25 | This will produce the same `Config Explorer` view 26 | 27 | > INSIDER: This process creates a mini_ucs file that includes all config files (from all partitions), bigip_base.conf and bundles them as a mini_ucs like package 28 | 29 | !> Some UCS/QKVIEWS/Configs can get very large. Please be patient as these files are collected, unpacked and parsed. The progress bar at the bottom should provide any change in status during processing 30 | 31 | ## Multi-App Select 32 | 33 | Multiple apps can be selected to produce a single file. 34 | 35 | To use multi-select, hold the `control` key while clicking on all the desired applications, then right-click `Show Apps` to produce a single file with the selected application configs 36 | 37 | drawing 38 | 39 | ## Clearing Config Explorer Details 40 | 41 | The explorer view details are only cleared when selecting the `CLEAR` button at the top of the view. 42 | 43 | The allows for expanded possible workflows where details can be loaded via any method independent of connecting to a device and sending information 44 | 45 | > example 1: connect to a device, explore the config, then connect to another device and merge config object/applications with the newly connected device 46 | 47 | > example 2: load config from qkview, then merge an application with a connected device 48 | 49 | drawing 50 | 51 | ## Searching Config Explorer View 52 | 53 | The config explorer view has a simple search/filter function that can be accessed by clicking on the device item at the top, the typing in the text to search. All matches are highlighted. 54 | 55 | Additionally, clicking in the search text box will filter the results 56 | 57 | drawing 58 | -------------------------------------------------------------------------------- /docs/device_importing.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Importing devices 4 | 5 | There are functions to automatically import devices into the list or import devices by right clicking on data in an editor. Both methods support the same data structure defined below. 6 | 7 | ## Auto import using seed file 8 | 9 | For automated deployments (mainly for coder), place a seed file named `.vscode-f5.json` in the base install directory of the vscode extension directoy, typically under 10 | 11 | - `local windows location` - C:\Users\SomeUser\.vscode\extensions\devcentral.vscode-f5-v3.0.0 12 | - `linux over remote-ssh extension` - /home/SomeUser/.vscode-server/extensions/devcentral.vscode-f5-v3.0.0/ 13 | 14 | When the extension launches and finishes loading, it should detect the seed file and prompt to install. See import formats below for more details on input types. 15 | 16 | - `Yes` will import the devices and details found in the seed file 17 | - `Yes-Consume` will import like above but then delete the file so passwords at not left behind 18 | - `No` or `closing the window`, will just cancel the operation (like saying no) 19 | 20 | ## Import from right click in an editor 21 | 22 | The following formats are also supported by right-click in an editor (highlight text), then `Import Devices` 23 | 24 | ### Don't see anything happending? 25 | 26 | Check the `f5` log OUTPUT for more details on what might be missing 27 | 28 | ### simple string import 29 | 30 | ```yaml 31 | admin@1.1.1.1 32 | ``` 33 | 34 | ### json array import structure (list) 35 | 36 | ```json 37 | [ 38 | "admin@1.1.1.1", 39 | "user2@2.2.2.2:8443", 40 | "user3@testf5.com" 41 | ] 42 | ``` 43 | 44 | ### single json object import structure 45 | 46 | ```json 47 | { 48 | "device": "dude@2.1.3.4", 49 | "password": "coolness", 50 | "provider": "tmos" 51 | } 52 | ``` 53 | 54 | ### json object list import structure 55 | 56 | ```json 57 | [ 58 | { 59 | "device": "admin@2.168.1.1:8443" 60 | }, 61 | { 62 | "device": "admin@2.168.6.5", 63 | "password": "giraffie" 64 | }, 65 | { 66 | "device": "dude@2.1.3.4", 67 | "password": "coolness", 68 | "provider": "tmos" 69 | } 70 | ] 71 | ``` 72 | -------------------------------------------------------------------------------- /docs/do_ts.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # DO/TS 4 | 5 | --- 6 | 7 | ## DO Management (get/post) 8 | 9 | If the extension detects the DO is running, a status bar will show up on the bottom showing the running service software version 10 | 11 | Select the status bar item to see the current DO declaration 12 | 13 | Select the command from the palette drop down to post a declaration 14 | 15 | ![DO Mgmt](./media/getModifyDO_5.18.2020.gif) 16 | 17 | --- 18 | 19 | ## TS Management (get/post/clear) 20 | 21 | If the extension detects the TS is running, a status bar will show up on the bottom showing the running service software version 22 | 23 | Select the status bar item to see the current TS declaration 24 | 25 | Select the command from the palette drop down to post a declaration 26 | 27 | ![TS Mgmt](./media/getModifyTS_5.18.2020.gif) 28 | 29 | -------------------------------------------------------------------------------- /docs/fast.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # FAST Management 4 | 5 | FAST view on the left will display applications deployed with device fast service, last five FAST tasks executed, templates and template sets 6 | 7 | ![as3 to mst](./media/FAST_view_6.23.2020.PNG) 8 | 9 | ## AS3 -> FAST YAML command 10 | 11 | As of v2.10 a command was added to convert and wrap an as3 declaration into a yaml fast template. 12 | 13 | !> Notice how the tenant paramter is already has a fast template string 14 | 15 | With an editor with an AS3 declaration, right-click, select `AS3 -> FAST YAML`. 16 | 17 | drawing 18 | 19 | ### Deployed AS3 to FAST YAML 20 | 21 | This flow shows how to take a deployed AS3 declaration and convert it to a FAST YAML template. 22 | 23 | !> This flow is different from the above example declaration because AS3 returns the ADC class without the AS3 class of the declartion. ***Injecting the schema wraps the ADC class with the necessary AS3 class information*** 24 | 25 | drawing 26 | 27 | ## How to create FAST template from AS3 declaration 28 | 29 | The following is an example FAST template in YAML form. FAST accepts other template types, like .mst, but .yml is the recommended path since it provides the interface HTML paramters to make the template more consumable to the end users 30 | 31 | !> Notice the `template` parameter is a regular AS3 declaration with the template variables `{{ tenant_name }}` 32 | 33 | ```yaml 34 | title: Simple Application 35 | description: Simple load balanced vs using the same port on client and server side. 36 | template: | 37 | { 38 | "class": "ADC", 39 | "schemaVersion": "3.20.0", 40 | "{{tenant_name}}": { 41 | "class": "Tenant", 42 | "{{application_name}}": { 43 | "class": "Application", 44 | "template": "udp", 45 | "serviceMain": { 46 | "class": "Service_UDP", 47 | "virtualAddresses": [ 48 | "{{virtual_address}}" 49 | ], 50 | "virtualPort": {{virtual_port::integer}}, 51 | "pool": "{{application_name}}_Pool1" 52 | }, 53 | "{{application_name}}_Pool1": { 54 | "class": "Pool", 55 | "monitors": [ 56 | "icmp" 57 | ], 58 | "members": [ 59 | { 60 | "serverAddresses": {{server_addresses::array}}, 61 | "servicePort": {{service_port::integer}} 62 | } 63 | ] 64 | } 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | ## Previewing a FAST template 71 | 72 | FAST templates have an HTML view for the UI. It can be access through the extension for testing. 73 | 74 | On a template from the `FAST VIEW` or template file in explorer, right-click, select `Render Fast Template HTML Preview`. 75 | 76 | This will produce the final HTML view for the UI 77 | 78 | At the bottom of the preview, the extension adds the `Render` button, which will render the output of the template 79 | 80 | !> For the template preview to work, the template must not have any dependencies or referenced schemas as part of a 'template set'. The template must be able to be validated on it's own as a single file 81 | 82 | drawing 83 | 84 | !> This workflow also ties into being able to post the fast template output to an AS3 service if the connected device is running one 85 | 86 | ## Uploading a single template 87 | 88 | Open an mst/template. 89 | 90 | Post template to fast engine via the command palette: press `F1`, then filter/select `F5-Fast: Post mst as new fast template`. Change the folder name if needed, provide a template name. 91 | 92 | >NOTE: Uploading a single template to an existing folder overwrites other templates. The single template method is primarily for testing. It is recommended to upload template sets 93 | 94 | ## Uploading a template set 95 | 96 | Template sets are the recommended method for long term template authoring and mgmt. It is recommended to have a folder with different folders for the different template sets you may be creating. 97 | 98 | ***example layout*** 99 | 100 | - main_templates_folder 101 | - prod_templates 102 | - qa_templates 103 | - dev_templates 104 | - infra_templates 105 | 106 | ***example directory structure*** 107 | 108 | - sample_decs 109 | - app1Templates 110 | - app2Templates 111 | - goodFastTemplates 112 | 113 | Press `F1`, then filter/select `F5-Fast: Post Template Set` 114 | 115 | !> this command is also found via righ click on folder or .yml/.yaml file in explorer view 116 | 117 | !>All files in the selected fast template folder must be valid templates. 118 | 119 | !>Each template is validated before all of them are zipped and uploaded/installed to the selected device with fast service 120 | 121 | > Example of opening a workspace, then connecting to f5 with fast, and uploading folder of templates as a template set 122 | 123 | drawing 124 | 125 | ## Uploading via right-click 126 | 127 | The latest method to upload templates is with a simple right click from within the explorer view 128 | 129 | drawing 130 | 131 | ## Deploying an application through FAST 132 | 133 | To deploy an application with FAST, utilize the followin structure 134 | 135 | The name should reference the fast folder/template to deploy, while the parameters object should contain all the necessary paramters to deploy the template 136 | 137 | Press `F1`, then filter/select `F5-Fast: Deploy Fast App` 138 | 139 | ```json 140 | { 141 | "name": "demo_step2b/demo_step2b", 142 | "parameters": { 143 | "tenant_name": "demoTen", 144 | "app_name": "demoApp1", 145 | "virtual_address": "100.0.0.1", 146 | "port": 80, 147 | "server_addresses": [ 148 | "100.0.0.11", 149 | "100.0.0.12" 150 | ] 151 | } 152 | } 153 | ``` 154 | 155 | ![deploy fast app](./media/FAST_deployApp_6.23.2020.gif) 156 | 157 | ## Delete Fast application 158 | 159 | Find the deployed application in the Fast view under "Deployed Applications", right click on the app, then select `Delete Fast App` 160 | 161 | drawing 162 | -------------------------------------------------------------------------------- /docs/generic_rest_calls.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Make HTTP/S Request documentation and examples 4 | 5 | This function provides the necessary flexbility to make any API call to ANYthing 6 | 7 | Highlight text, right-click, select: `Make HTTPS Request` 8 | 9 | 10 | 11 | ## Calls without "http" in url 12 | 13 | This assumes the request is intented for the currently connected device, of which host details are already known. 14 | 15 | K13225405: Common iControl REST API command examples 16 | 17 | - 18 | 19 | How to use postman api for external tests like post 20 | 21 | - 22 | 23 | 24 | >The underlying HTTP client is AXIOS, so most AXIOS parameters should work 25 | 26 | 27 | ### simple url as string 28 | 29 | ```url 30 | /mgmt/tm/sys/clock 31 | ``` 32 | 33 | ### simple url in yaml format 34 | 35 | ```yaml 36 | url: /mgmt/tm/sys/clock 37 | ``` 38 | 39 | ### simple url in json format 40 | 41 | ```json 42 | { 43 | "url": "/mgmt/tm/sys/clock" 44 | } 45 | ``` 46 | 47 | ### list vlans 48 | 49 | ```yaml 50 | /mgmt/tm/net/vlan/ 51 | ``` 52 | 53 | ### list nodes 54 | 55 | ```yaml 56 | /mgmt/tm/ltm/node 57 | ``` 58 | 59 | 60 | 61 | ### url post in yaml 62 | 63 | ```yaml 64 | url: /mgmt/shared/authn/login 65 | method: POST 66 | body: 67 | username: user1 68 | password: dobgispet 69 | ``` 70 | 71 | ### url post in yaml 72 | 73 | ```yaml 74 | url: /mgmt/tm/sys/config 75 | method: POST 76 | body: 77 | command: save 78 | ``` 79 | 80 | ### list sys options 81 | 82 | ```yaml 83 | /mgmt/tm/sys/ 84 | ``` 85 | 86 | ### list sys ucs 87 | 88 | ```yaml 89 | /mgmt/tm/sys/ucs/ 90 | ``` 91 | 92 | ### url post in json 93 | 94 | ```json 95 | { 96 | "url": "/mgmt/shared/authn/login", 97 | "method": "POST", 98 | "body": { 99 | "username": "todai", 100 | "password": "dobgispet" 101 | } 102 | } 103 | ``` 104 | 105 | ### tmsh save sys config (all partitions) 106 | 107 | > /mgmt/tm/sys/config -d '{"command":"save","partition":"all"}' 108 | 109 | ```yaml 110 | url: /mgmt/tm/sys/config 111 | method: POST 112 | body: 113 | command: save 114 | ``` 115 | 116 | 117 | 118 | 119 | --- 120 | 121 | ## Calls for outside f5 122 | 123 | The command will detect if the url has "http", if found, it considers it a fully qualified request destined for something outside of a device defined within the extension 124 | 125 | This is based off of NodeJS AXIOS request 126 | https://www.npmjs.com/package/axios#request-config 127 | 128 | Default HTTP method = GET 129 | 130 | data, or body, must also include 'POST' HTTP method 131 | 132 | ### Simple get 133 | 134 | ```yaml 135 | https://api.chucknorris.io/jokes/random 136 | ``` 137 | 138 | ### simple get in yaml 139 | 140 | ```yaml 141 | url: https://api.chucknorris.io/jokes/random 142 | ``` 143 | 144 | ### simple get in yaml - shows broken destination 145 | 146 | ```yaml 147 | url: https://broken.extra.io/whah 148 | ``` 149 | 150 | ### simple POST in yaml 151 | 152 | ```yaml 153 | url: 'https://postman-echo.com/post' 154 | method: POST 155 | data: 156 | hi: yo 157 | ``` 158 | 159 | ### simple POST in json 160 | 161 | ```json 162 | { 163 | "url": "https://postman-echo.com/post", 164 | "method": "POST", 165 | "data": { 166 | "hi": "yo" 167 | } 168 | } 169 | ``` 170 | 171 | 172 | ### raw get to external F5 using basic auth - DEV 173 | 174 | ```json 175 | { 176 | "url": "https://192.168.200.131/mgmt/tm/sys/ntp", 177 | "auth": { 178 | "username": "admin", 179 | "password": "yayPassword!", 180 | "sendImmediately": "true" 181 | } 182 | } 183 | ``` 184 | 185 | ## External Calls to another F5 186 | 187 | The following calls show the outline of how to interact with another f5 while currently connected to an F5 188 | 189 | 190 | ### raw get to external F5 using basic auth - DEV 191 | 192 | ### Create F5 Auth Token 193 | 194 | ```json 195 | { 196 | "url": "https://192.168.200.131/mgmt/shared/authn/login", 197 | "method": "POST", 198 | "rejectUnauthorized": "false", 199 | "data": { 200 | "username":"admin", 201 | "password":"*******", 202 | "loginProviderName": "tmos" 203 | } 204 | } 205 | ``` 206 | 207 | 208 | ### Get All Tokens 209 | 210 | ```json 211 | { 212 | "url": "https://192.168.200.131/mgmt/shared/authz/tokens/", 213 | "rejectUnauthorized": "false", 214 | "headers": { 215 | "Content-Type": "application/json", 216 | "X-F5-Auth-Token": "UJ6OX3WUSRBIHJMPH7EBFKRODW" 217 | } 218 | } 219 | ``` 220 | 221 | 222 | ### get f5 auth provider 223 | 224 | ```yaml 225 | url: 'https://10.200.244.110:8443/mgmt/tm/auth/source' 226 | headers: 227 | Content-Type: application/json 228 | X-F5-Auth-Token: ZM2MKZCDJ5FSDIPDVAVQIW7IBQ 229 | ``` 230 | 231 | ### get nodes 232 | 233 | ```json 234 | { 235 | "url": "https://192.168.200.131/mgmt/tm/ltm/node", 236 | "rejectUnauthorized": "false", 237 | "headers": { 238 | "Content-Type": "application/json", 239 | "X-F5-Auth-Token": "QL2HLEO6DSWS2DVT5BFNJYWGBA" 240 | } 241 | } 242 | ``` 243 | -------------------------------------------------------------------------------- /docs/media/AS3_2_FAST_YAML_02.09.2021.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/AS3_2_FAST_YAML_02.09.2021.gif -------------------------------------------------------------------------------- /docs/media/AS3_deployed_2_FAST_YAML_02.09.2021.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/AS3_deployed_2_FAST_YAML_02.09.2021.gif -------------------------------------------------------------------------------- /docs/media/FAST_as3JSON_to_mst_6.22.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_as3JSON_to_mst_6.22.2020.PNG -------------------------------------------------------------------------------- /docs/media/FAST_deleteApp_6.23.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_deleteApp_6.23.2020.gif -------------------------------------------------------------------------------- /docs/media/FAST_deployApp_6.23.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_deployApp_6.23.2020.gif -------------------------------------------------------------------------------- /docs/media/FAST_mst_ADC_Declaration_6.23.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_mst_ADC_Declaration_6.23.2020.PNG -------------------------------------------------------------------------------- /docs/media/FAST_mst_template_params_6.23.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_mst_template_params_6.23.2020.PNG -------------------------------------------------------------------------------- /docs/media/FAST_tempSet_upload_6.23.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_tempSet_upload_6.23.2020.gif -------------------------------------------------------------------------------- /docs/media/FAST_view_6.23.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/FAST_view_6.23.2020.PNG -------------------------------------------------------------------------------- /docs/media/OUTPUT_logging_9.9.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/OUTPUT_logging_9.9.2020.PNG -------------------------------------------------------------------------------- /docs/media/addDeviceConnect_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/addDeviceConnect_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/appMove_tclMerge_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/appMove_tclMerge_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/as3GetPostDeleteTask_5.18.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/as3GetPostDeleteTask_5.18.2020.gif -------------------------------------------------------------------------------- /docs/media/as3SchemaInYaml.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/as3SchemaInYaml.PNG -------------------------------------------------------------------------------- /docs/media/as3SnippetDemo_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/as3SnippetDemo_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/as3_snippet_9.9.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/as3_snippet_9.9.2020.gif -------------------------------------------------------------------------------- /docs/media/base64_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/base64_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/configExplerSearching_3.7.2021.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/configExplerSearching_3.7.2021.gif -------------------------------------------------------------------------------- /docs/media/configExplore_clear_11.04.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/configExplore_clear_11.04.2020.PNG -------------------------------------------------------------------------------- /docs/media/connectDisPassCache_5.18.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/connectDisPassCache_5.18.2020.gif -------------------------------------------------------------------------------- /docs/media/deviceMgmt_5.18.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/deviceMgmt_5.18.2020.gif -------------------------------------------------------------------------------- /docs/media/exploreUCS_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/exploreUCS_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/exploreUCS_multiSelect_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/exploreUCS_multiSelect_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/f5.png -------------------------------------------------------------------------------- /docs/media/f5_24x24.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/media/f5_white_24x24.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | background 9 | 10 | 11 | 12 | Layer 1 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/media/fastTemplatePreview_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/fastTemplatePreview_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/favicon.png -------------------------------------------------------------------------------- /docs/media/getModifyDO_5.18.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/getModifyDO_5.18.2020.gif -------------------------------------------------------------------------------- /docs/media/getModifyTS_5.18.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/getModifyTS_5.18.2020.gif -------------------------------------------------------------------------------- /docs/media/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/media/hostsView_labelsConfig.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/hostsView_labelsConfig.gif -------------------------------------------------------------------------------- /docs/media/injectSchema_existingBroken_v2.8.0_10.30.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/injectSchema_existingBroken_v2.8.0_10.30.2020.gif -------------------------------------------------------------------------------- /docs/media/injectSchema_existing_v2.8.0_10.30.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/injectSchema_existing_v2.8.0_10.30.2020.gif -------------------------------------------------------------------------------- /docs/media/injectSchema_v2.8.0_10.30.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/injectSchema_v2.8.0_10.30.2020.gif -------------------------------------------------------------------------------- /docs/media/installTsRpm_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/installTsRpm_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/installWithinCode_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/installWithinCode_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/json_yaml_coverter_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/json_yaml_coverter_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/onConnect_11.05.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/onConnect_11.05.2020.gif -------------------------------------------------------------------------------- /docs/media/remoteCMD_5.18.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/remoteCMD_5.18.2020.gif -------------------------------------------------------------------------------- /docs/media/tcl_createModifyDelete_iApp_8.21.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/tcl_createModifyDelete_iApp_8.21.2020.gif -------------------------------------------------------------------------------- /docs/media/tcl_createModifyDelete_rule_8.21.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/tcl_createModifyDelete_rule_8.21.2020.gif -------------------------------------------------------------------------------- /docs/media/tcl_setting_8.21.2020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/tcl_setting_8.21.2020.PNG -------------------------------------------------------------------------------- /docs/media/unInstallRPM_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/unInstallRPM_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/uploadFastTemplates_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/uploadFastTemplates_11.04.2020.gif -------------------------------------------------------------------------------- /docs/media/vscode_extensions_icon.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/vscode_extensions_icon.PNG -------------------------------------------------------------------------------- /docs/media/xcApps.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/xcApps.PNG -------------------------------------------------------------------------------- /docs/media/xcDiagRules.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/xcDiagRules.PNG -------------------------------------------------------------------------------- /docs/media/xcGettingStarted.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/docs/media/xcGettingStarted.PNG -------------------------------------------------------------------------------- /docs/schemaRefVariables.md: -------------------------------------------------------------------------------- 1 | # documenting local schema reference veriables in vscode json editor 2 | 3 | This whole process is part of an effort to figure out how to get vscode schema validation working with json bodies destined for an api endpoint with a swagger/OpenApi spec 4 | 5 | The key point about OpenApi schema, is that we can have many different endpoints with many different schemas. So, the typical schema mapping provided by vscode doesn't scale. But I can programmatically provide the schema/reference depending on how the user got the json. 6 | 7 | Also, as noted in this issue, there is no programmatic way to provide the schema and/or reference 8 | 9 | Seems someone has already opened an issue for this feature (it was pretty much rejected) 10 | [json] $schema: support predefined variables like ${workspaceFolder} #166438 11 | 12 | 13 | OpenApi schema validation #162 14 | 15 | 16 | ## package.json contributes 17 | 18 | 19 | 20 | ## current understanding of behavior 21 | 22 | Currently the "$schema" value in a vscode editor/textDocument with the language set to json, is used to provide schema validation of the json object. 23 | 24 | This schema reference in the json body can be a local file or an HTTP destination that will be fetched 25 | 26 | ## Behavior change or feature request 27 | 28 | Requesting the support of variables in the "$schema" reference value, preferrably the vscode variables for debugging and task json files, so something similar. 29 | 30 | The intent is to reference many different schema files bundled with an extension. 31 | 32 | ### extension schema references? 33 | 34 | What about the current ability to reference a schema provided by the extension "contributes" package.json 35 | 36 | It is my understanding that this is a static reference of a single schema to many file types 37 | 38 | ### local project schema reference 39 | 40 | The following example shows local workspace reference, meaning the device_schema.json file is in the same directory as the current open project/workspace 41 | 42 | ```json 43 | { 44 | "$schema": "./device_schema.json", 45 | "address": "10.1.1.7", 46 | "port": "5443", 47 | "device_user": "admin", 48 | "device_password": "whos-clues", 49 | "management_user": "admin-cm", 50 | "management_password": "blues-clues", 51 | "something": "new" 52 | } 53 | ``` 54 | 55 | ## Other parts of the local file system 56 | 57 | The following shows how absolute directory traversal is possible 58 | 59 | ```json 60 | { 61 | "$schema": "/home/ted/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json", 62 | "address": "10.1.1.7", 63 | "port": "5443", 64 | "device_user": "admin", 65 | "device_password": "whos-clues", 66 | "management_user": "admin-cm", 67 | "management_password": "blues-clues", 68 | "something": "new" 69 | } 70 | ``` 71 | 72 | ## linux local user home system variable 73 | 74 | Attempting to use a linux current user dir var is unsuccessful 75 | 76 | ```json 77 | { 78 | "$schema": "$HOME/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json", 79 | "address": "10.1.1.7", 80 | "port": "5443", 81 | "device_user": "admin", 82 | "device_password": "whos-clues", 83 | "management_user": "admin-cm", 84 | "management_password": "blues-clues", 85 | "something": "new" 86 | } 87 | ``` 88 | 89 | ### error 90 | 91 | ```text 92 | Unable to load schema from '/home/ted/projects/f5-fasting/NEXT/$HOME/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json': ENOENT: no such file or directory, open '/home/ted/projects/f5-fasting/NEXT/$HOME/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json'.(768) 93 | ``` 94 | 95 | ## vscode exec path 96 | 97 | Attempting to use built in vscode variables is unsuccessful (${execPath}) 98 | 99 | 100 | 101 | ### execPath 102 | 103 | ```json 104 | { 105 | "$schema": "${execPath}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json", 106 | "address": "10.1.1.7", 107 | "port": "5443", 108 | "device_user": "admin", 109 | "device_password": "whos-clues", 110 | "management_user": "admin-cm", 111 | "management_password": "blues-clues", 112 | "something": "new" 113 | } 114 | ``` 115 | 116 | ```text 117 | Unable to load schema from '/home/ted/projects/f5-fasting/NEXT/${execPath}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json': ENOENT: no such file or directory, open '/home/ted/projects/f5-fasting/NEXT/${execPath}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json'.(768) 118 | ``` 119 | 120 | ### userHome 121 | 122 | ```json 123 | { 124 | "$schema": "${userHome}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json", 125 | "address": "10.1.1.7", 126 | "port": "5443", 127 | "device_user": "admin", 128 | "device_password": "whos-clues", 129 | "management_user": "admin-cm", 130 | "management_password": "blues-clues", 131 | "something": "new" 132 | } 133 | ``` 134 | 135 | ```text 136 | Unable to load schema from '/home/ted/projects/f5-fasting/NEXT/${userHome}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json': ENOENT: no such file or directory, open '/home/ted/projects/f5-fasting/NEXT/${userHome}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json'.(768) 137 | ``` 138 | 139 | ## double bracket on vscode variable 140 | 141 | double bracket vscode variables do not work 142 | 143 | ```json 144 | { 145 | "$schema": "${{userHome}}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json", 146 | "address": "10.1.1.7", 147 | "port": "5443", 148 | "device_user": "admin", 149 | "device_password": "whos-clues", 150 | "management_user": "admin-cm", 151 | "management_password": "blues-clues", 152 | "something": "new" 153 | } 154 | ``` 155 | 156 | ```text 157 | Unable to load schema from '/home/ted/projects/f5-fasting/NEXT/${{userHome}}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json': ENOENT: no such file or directory, open '/home/ted/projects/f5-fasting/NEXT/${{userHome}}/projects/vscode-f5/schemas/nextCm/DeviceDiscoveryRequest.json'.(768) 158 | ``` 159 | -------------------------------------------------------------------------------- /docs/schema_validation.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Schama Validation 4 | 5 | 6 | 7 | One of the primary uses of this tool is to provide schema validation of the ATC declaration during the authoring process. Understanding and having constant feedback about the declaration and it's content during development can drastically improve the expereince. 8 | 9 | There is a schema for each of the different ATC services (AS3/DO/TS), these methods apply to all. 10 | 11 | 12 | 13 | > NOTE: Schemas are versioned but are BACKWARD COMPATIBLE, meaning ***ALWAYS USE LATEST SCHEMA VERSION*** to validate any declaration 14 | 15 | 16 | There are two main ways schema validation can be applied: 17 | 18 | ## Untitled document schema or in-declaration direct reference 19 | 20 | Just as documented here: , the necessary json schema can be referenced diretly within the declaration. 21 | 22 | This scenario is common when first starting out with automation since it is very easy to open an editor, copy an example declaration and start editing. Since the file has not been saved (with the appropriate file type discussed later), VSCode does not know what schema to apply, therefore, just providing basic json syntax validation. 23 | 24 | The extension contains basics example declaration of AS3/DO/TS, each containing the respective schema. This is a good place to quickly access access an example declaration with schema validation to get started. 25 | 26 | [***See extension Snippets below***](/schema_validation#extension-snippets) 27 | 28 | ## Inject/Remove Schema Reference Command 29 | 30 | There is a command to inject the appropriate schema reference into any editor declaration (mainly the untitled). 31 | 32 | This commmand is easily accessable with a right click in an editor window, then selecting `Inject/Remove Schema Reference`. This will read the declaration in the current active editor and attempt to inject the appropriate schema. This is done by parsing the text into a json object, detecting the particular class parameters for each of the ATC services, adding the appropriate object schema reference, and updating all the text in the editor. 33 | 34 | 35 | 36 | ### Removing and re-injecting schema to the as3 example declaration snippet 37 | 38 | drawing 39 | 40 | ### Injecting schema into an as3 declaration when viewing a deployed as3 declaration 41 | 42 | drawing 43 | 44 | ### Schema mgmt with invalid json 45 | 46 | If invalid json is detected but a schema reference is found in the text, it will remove the schema reference 47 | 48 | If invalid json is detected and no schema reference is found, it will present an option to add the desired schema at the top of the editor/text. 49 | 50 | drawing 51 | 52 | 53 | --- 54 | 55 | 56 | 57 | ## File Type schema reference 58 | 59 | 60 | 61 | The other method of providing schema validation, and recommended method, is through file types. A typical AS3/DO/TS declaration may be saved as a JSON (app1.json) file since that is the structure of the data. To follow on with this, the extension utilizes file sub-types to associate the appropriate schema. 62 | 63 | - *.as3.json 64 | - *.do.json 65 | - *.ts.json 66 | 67 | Examples can be found in the f5-fasting repo 68 | 69 | 70 | 71 | --- 72 | 73 | 74 | 75 | ## Extension Snippets 76 | 77 | 78 | 79 | Snippets are code blocks that are used to quickly insert code within an editor in VSCode. The extension includes the basic example for each of the ATC services (AS3/DO/TS). 80 | 81 | To access the snippets, open an editor file, change the language to JSON, then start typing 'as3', 'do' or 'ts', the hit 'enter". This should insert the example snippet for the respective ATC service. 82 | 83 | > NOTE: these snippets include the direct schema reference 84 | 85 | drawing 86 | 87 | VSCode guide for defining customer user snippets 88 | 89 | 90 | 91 | 92 | --- 93 | 94 | 95 | 96 | ## Schema Links 97 | 98 | 99 | 100 | ### Latest AS3 Schema 101 | 102 | 103 | 104 | ### Latest DO Schema 105 | 106 | 107 | 108 | ### Latest TS Schema 109 | 110 | 111 | 112 | --- 113 | 114 | ## Validating YAML ATC Declarations with JSON Schemas 115 | 116 | Install the RedHat YAML extension 117 | 118 | > 119 | 120 | In the vscode settings for that extension: 121 | 122 | ```json 123 | "yaml.schemas": { 124 | "https://raw.githubusercontent.com/F5Networks/f5-appsvcs-extension/main/schema/latest/as3-schema.json": ["*.as3.yml"], 125 | "https://raw.githubusercontent.com/F5Networks/f5-declarative-onboarding/HEAD/src/schema/latest/base.schema.json": ["*.do.yml"], 126 | "https://raw.githubusercontent.com/F5Networks/f5-telemetry-streaming/HEAD/src/schema/latest/base_schema.json": ["*.ts.yml"], 127 | } 128 | ``` 129 | 130 | create a yaml file for as3 like: `as3Dec1.as3.yml` 131 | 132 | drawing 133 | -------------------------------------------------------------------------------- /docs/tcl.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # TCL/iRules/iApps 4 | 5 | This VSCode extension now supports the management of TCL/TMOS objects, including iRules/iApps. iRules and iApps are listed/viewed via the API, but merged with the running config when uploaded/updated. 6 | 7 | This functionality can also be used for creating/modifying or migrating applictions 8 | 9 | While this extension does help with the managment of iRules/iApps, it does not provide any validation or language features like syntax checking or auto-complete. For language features, it is highly recommended to utilize the following extensions. 10 | 11 | All these extension combined provide a very power platform for writing and deploying iRule/iApps. 12 | 13 | !> NOTE: Be cautious of editing iRules in a production environment since any changes can affect client connections. 14 | 15 | ## iRules 16 | 17 | Recommended iRule language extension 18 | 19 | https://marketplace.visualstudio.com/items?itemName=bitwisecook.irule 20 | 21 | 22 | ## iApps 23 | 24 | Recommended iApp language extension 25 | 26 | https://marketplace.visualstudio.com/items?itemName=bitwisecook.iapp 27 | 28 | 29 | ## Commands 30 | 31 | * `F5: Merge TCL/TMOS`: Used to merge editor/highlighted text with running connfig of connected bigip 32 | - Use this to push a new TMOS config object or after modifing an existing irule (format is a tmos object) 33 | - Available: right-click in editor 34 | - Uploads a file with configuration objects, moves them to a temp directory, then attempts to merge with running config 35 | - /var/config/rest/downloads/tempTmosConfigMerge.tcl -> /tmp/tempTmosConfigMerge.tcl 36 | - `tmsh load sys config merge file /tmp/tempTmosConfigMerge.tcl` 37 | - If no error|fail detected -> pop-up success message 38 | - else display editor with full error message 39 | 40 | 41 | * `F5: DELETE iRule`: Used to delete irule 42 | - Available: right-click irule item in TCL view tree 43 | - Deletes irule object from device, refreshes TCL tree view to show changes 44 | 45 | * `F5: Get iApp Template Origin .tmpl`: Displays the original .tmpl iApp template format 46 | - Available: regular click on iApp item in IRULE/IAPPS view 47 | - Primary recommended method for modifying an iApp 48 | 49 | * `F5: Get iApp Template JSON`: Displays the JSON format of selected iApp template 50 | - Available: right-click on iApp item in IRULE/IAPPS view 51 | - Don't really see any use for this, but it's there for show 52 | 53 | * `F5: RE-DEPLOY iApp-App`: Redeploys iApp-App using current paramters 54 | - Available: right-click on Deployed-Apps item in IRULE/IAPPS view 55 | - Like issuing command: modify sys application service my_app.app/my_app execute-action definition 56 | - This is used for redeploying an app after making changes to the source iapp template 57 | 58 | * `F5: DELETE iApp-App`: Deletes iApp-App 59 | - Available: right-click on Deployed-Apps item in IRULE/IAPPS view tree 60 | 61 | * `F5: DELETE iApp Template`: Deletes iApp Template 62 | - Available: right-click on iApp-Templates item in IRULES/IAPPS view tree 63 | 64 | * `F5: POST iApp Template .tmpl`: Uploads and imports iApp template 65 | - Available: right-click in editor and right-click on explorer file with .tmpl extension 66 | 67 | 68 | --- 69 | 70 | ## Create/Modify/Delete iRule 71 | 72 | ![create/modify/delete iRule](./media/tcl_createModifyDelete_rule_8.21.2020.gif) 73 | 74 |   75 | 76 | 77 | --- 78 | 79 | ## iApp Template Management 80 | 81 | * Upload .tmpl from explorer file 82 | * Upload iApp from editor 83 | * Modify existing iApp 84 | * Delete iApp 85 | 86 | ![create/modify/delete iRule](./media/tcl_createModifyDelete_rule_8.21.2020.gif) 87 | 88 |   89 | 90 | --- 91 | 92 | ## Config Migration 93 | 94 | The following workflow shows how an application can be extracted from a config and merged with the running config of another device 95 | 96 | !> Be aware of configuration object parameters which are not user settable like the `last-modified-time` of the virtual server. They will need to be removed before merge. 97 | 98 | !> It is recommended to only merge configurations items that are sourced from the same TMOS version 99 | 100 | drawing 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/utilities.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Utilities 4 | 5 | ## JSON <-> YAML converter 6 | 7 | There is a json <-> yaml converter via right-click in the editor as shown below: 8 | 9 | drawing 10 | 11 | ## Base64 encode/decode 12 | 13 | Right-click in an editor will also present the option to base64 encode/decode 14 | 15 | drawing 16 | 17 | ## onConnect/onDisconnect Commands 18 | 19 | The onConnect and onDisconnect commands are configurable via the user settings json file for the extension. This feature allows commands to be executed on connect and on disconnect of the related device. 20 | 21 | This feature is useful for workflows like automatically connecting over ssh and tailing the logs for a specific device 22 | 23 | drawing 24 | 25 | ## Remote Command Execute 26 | 27 | Command to issue on the remote device. Good for quickly getting information while building declarations! 28 | 29 | drawing -------------------------------------------------------------------------------- /docs/xcDiagnostics.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # TMOS -> XC Diagnostics 4 | 5 | XC Diagnostics attempts to provide an easy go/no-go interface to understand what app can possibly be configured on F5 Distributed Cloud 6 | 7 | ## Getting started 8 | 9 | XC Diagnostics are based on TMOS configs. This diagnostic feedback is built around the F5 config explorer (f5-corkscrew) feature, which aids in exploring and abstracting applications from .conf/ucs/qkview files. 10 | 11 | > To get started with [Config Explorer](config_explorer.md) 12 | 13 | Then enable XC Diagnostics by clicking the button 14 | 15 | drawing 16 | 17 | From here, expand/click on different apps and watch the diagnostics update 18 | 19 | drawing 20 | 21 | ## Rules 22 | 23 | This tools was designed to be extensible, and therefore, the ruleset can easily be updated to accomodate different scenarios. 24 | 25 | The rules can be access by clicking on the pencil icon in the "XC Diagnostics" view item. 26 | 27 | drawing 28 | 29 | ### Rule Details 30 | 31 | The following is a breakdown of the rule structure 32 | 33 | |key | details | 34 | | --- | --- | 35 | | code | Four digit hex code unique to each rule; makes the rule easily referencable | 36 | | severity | Error/Warning/Information/Hint shows the importance of each rule | 37 | | title | Short title of the rule | 38 | | message | Detailed rule body; can include markdown/links formatting | 39 | | regex | Regex used to support the rule | 40 | 41 | 42 | ### Example 43 | 44 | ```json 45 | { 46 | "code": "e3d6", 47 | "severity": "Warning", 48 | "title": "Virtual References Local Traffic Policy(s)", 49 | "message": "Virtual Server references Local Traffic Policy(s), review policies for compatibility", 50 | "regex": "policies {" 51 | } 52 | ``` 53 | 54 | ### Rules updates 55 | 56 | Once the ruleset has been updated, save the file (cntrl+s), then click on the refresh icon in the XC Diagnostics view item used to enable diagnostics 57 | 58 | That refresh icon will re-load that saved rule file into the workspace and re-apply the XC diagnostics. 59 | 60 | ### Providing feedback 61 | 62 | Please open a github issue with any questions, new rules and/or updates 63 | 64 | Issues 65 | 66 | 67 | Main ruleset file 68 | (https://github.com/f5devcentral/vscode-f5/blob/main/diagRules/tmosXcRules.json) -------------------------------------------------------------------------------- /images/BIG-IQ-sticker_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/images/BIG-IQ-sticker_transparent.png -------------------------------------------------------------------------------- /images/addDeviceConnect_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/images/addDeviceConnect_11.04.2020.gif -------------------------------------------------------------------------------- /images/as3SnippetDemo_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/images/as3SnippetDemo_11.04.2020.gif -------------------------------------------------------------------------------- /images/big-iq-centralized-mngmnt.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/bigiq1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Layer 1 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /images/bigiq_text.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 15 | 16 | 20 | 21 | 26 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /images/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/images/f5.png -------------------------------------------------------------------------------- /images/f5_24x24.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /images/f5_open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/f5_open_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /images/f5_open_light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/f5_white_24x24.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | background 9 | 10 | 11 | 12 | Layer 1 13 | 14 | 15 | -------------------------------------------------------------------------------- /images/greenCheck.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /images/greenDot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Layer 1 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/greyLine.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /images/installWithinCode_11.04.2020.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/images/installWithinCode_11.04.2020.gif -------------------------------------------------------------------------------- /images/next12-cm.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 38 | 41 | 42 | 44 | 50 | 53 | 56 | 57 | 59 | 67 | 68 | 70 | 78 | 79 | 86 | N-CM 94 | 95 | -------------------------------------------------------------------------------- /images/next12.svg: -------------------------------------------------------------------------------- 1 | 2 | 12 | 14 | 20 | 23 | 26 | 27 | 29 | 37 | 38 | 40 | 48 | 49 | 56 | NEXT 64 | 65 | -------------------------------------------------------------------------------- /images/orangeDot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Layer 1 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/redDot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Layer 1 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/swagger.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/vscode_extensions_icon.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f5devcentral/vscode-f5/d661bedb8c0d873adde11cded0089100d2dff08e/images/vscode_extensions_icon.PNG -------------------------------------------------------------------------------- /images/yellowDot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Layer 1 4 | 5 | 6 | -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#", 4 | "blockComment": ["/*", "*/"] 5 | }, 6 | "brackets": [ 7 | ["{", "}"], 8 | ["[", "]"], 9 | ["(", ")"] 10 | ], 11 | "autoClosingPairs": [ 12 | { "open": "{", "close": "}" }, 13 | { "open": "[", "close": "]" }, 14 | { "open": "(", "close": ")" }, 15 | { "open": "'", "close": "'", "notIn": ["string", "comment"] }, 16 | { "open": "\"", "close": "\"", "notIn": ["string"] }, 17 | { "open": "`", "close": "`", "notIn": ["string", "comment"] }, 18 | { "open": "/**", "close": " */", "notIn": ["string"] } 19 | ], 20 | "autoCloseBefore": ";:.,=}])>` \n\t", 21 | "surroundingPairs": [ 22 | ["{", "}"], 23 | ["[", "]"], 24 | ["(", ")"], 25 | ["'", "'"], 26 | ["\"", "\""], 27 | ["`", "`"] 28 | ], 29 | "folding": { 30 | "markers": { 31 | "start": "^\\s*//\\s*#?region\\b", 32 | "end": "^\\s*//\\s*#?endregion\\b" 33 | } 34 | }, 35 | "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", 36 | "indentationRules": { 37 | "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", 38 | "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$" 39 | } 40 | } -------------------------------------------------------------------------------- /snippets/fastYamlSnippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "FAST YAML Base": { 3 | "prefix": "fast", 4 | "body": [ 5 | "title: ${1:template title}", 6 | "description: ${2:template description}", 7 | "template: | ", 8 | "" 9 | ], 10 | "description": "Base FAST YAML template properties" 11 | }, 12 | "FAST YAML Extended": { 13 | "prefix": "fast", 14 | "body": [ 15 | "title: ${1:template title}", 16 | "description: ${2:template description}", 17 | "parameters:", 18 | " tenant_name: ${3:default tenant name}", 19 | "definitions: ", 20 | " tenant_name:", 21 | " title: Tenant Name", 22 | " type: string", 23 | " description: partition on bigip", 24 | "template: | ", 25 | "" 26 | ], 27 | "description": "Extended FAST YAML template" 28 | } 29 | } -------------------------------------------------------------------------------- /src/bigiqCore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | * may copy and modify this software product for its internal business purposes. 5 | * Further, Licensee may upload, publish and distribute the modified version of 6 | * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | import { 12 | commands, 13 | ExtensionContext, 14 | window 15 | } from "vscode"; 16 | import { ext } from "./extensionVariables"; 17 | import { BigiqTreeProvider } from "./treeViewsProviders/bigiqTreeProvider"; 18 | import { getText } from "./utils/utils"; 19 | 20 | import { logger } from './logger'; 21 | 22 | export class BigiqCore { 23 | 24 | constructor(context: ExtensionContext) { 25 | 26 | const iqProvider = new BigiqTreeProvider(context); 27 | const iqTreeView = window.createTreeView('iqView', { 28 | treeDataProvider: iqProvider, 29 | showCollapseAll: true, 30 | canSelectMany: false 31 | }); 32 | 33 | context.subscriptions.push(commands.registerCommand('f5.iqViewShow', async (el) => { 34 | 35 | ext.telemetry.capture({ command: 'f5.iqViewShow' }); 36 | 37 | if (el.selfLink && el.type === 'app') { 38 | 39 | // overwrite the id with the full app details from response 40 | el = await iqProvider.getApp(el.selfLink) 41 | .catch(err => logger.error('f5.iqViewShow:', err)); 42 | 43 | 44 | } else if (el.script) { 45 | iqProvider.render([], el); 46 | } else { 47 | iqProvider.render(el); 48 | } 49 | })); 50 | 51 | context.subscriptions.push(commands.registerCommand('f5.iqPostTemplate', async () => { 52 | 53 | ext.telemetry.capture({ command: 'f5.iqPostTemplate' }); 54 | 55 | await getText() 56 | .then(async text => { 57 | await iqProvider.postTemplate(text); 58 | }) 59 | .catch(err => logger.error('f5.iqPostTemplate failed with', err)); 60 | })); 61 | 62 | context.subscriptions.push(commands.registerCommand('f5.iqTemplatePublish', async (item) => { 63 | 64 | ext.telemetry.capture({ command: 'f5.iqTemplatePublish' }); 65 | 66 | await iqProvider.publishTemplate(item) 67 | .catch(err => logger.error('f5.iqTemplatePublish failed with', err)); 68 | })); 69 | 70 | context.subscriptions.push(commands.registerCommand('f5.iqTemplateDelete', async (item) => { 71 | 72 | ext.telemetry.capture({ command: 'f5.iqTemplateDelete' }); 73 | 74 | await iqProvider.deleteTemplate(item) 75 | .catch(err => logger.error('f5.iqTemplateDelete failed with', err)); 76 | })); 77 | 78 | context.subscriptions.push(commands.registerCommand('f5.iqAppMoveApp', async (item) => { 79 | 80 | ext.telemetry.capture({ command: 'f5.iqAppMoveApp' }); 81 | 82 | await iqProvider.moveApp(item) 83 | .catch(err => logger.error('f5.iqAppMoveApp failed with', err)); 84 | })); 85 | 86 | context.subscriptions.push(commands.registerCommand('f5.iqAppDelete', async (item) => { 87 | 88 | ext.telemetry.capture({ command: 'f5.iqAppDelete' }); 89 | 90 | await iqProvider.deleteApp(item) 91 | .catch(err => logger.error('f5.iqAppDelete failed with', err)); 92 | })); 93 | 94 | context.subscriptions.push(commands.registerCommand('f5.iqViewRefresh', async () => { 95 | iqProvider.refresh(); 96 | })); 97 | 98 | 99 | 100 | context.subscriptions.push(commands.registerCommand('f5.iqScriptDelete', async (item) => { 101 | 102 | ext.telemetry.capture({ command: 'f5.iqScriptDelete' }); 103 | 104 | await iqProvider.deleteScript(item) 105 | .catch(err => logger.error('f5.iqScriptDelete failed with', err)); 106 | })); 107 | 108 | context.subscriptions.push(commands.registerCommand('f5.iqScriptPost', async (item) => { 109 | 110 | ext.telemetry.capture({ command: 'f5.iqScriptPost' }); 111 | 112 | getText().then(async text => { 113 | await iqProvider.postScript(text) 114 | .catch(err => logger.error('f5.iqScriptPost failed with', err)); 115 | }); 116 | })); 117 | 118 | context.subscriptions.push(commands.registerCommand('f5.iqScriptExecute', async (item) => { 119 | 120 | ext.telemetry.capture({ command: 'f5.iqScriptExecute' }); 121 | 122 | await iqProvider.executeScript(item) 123 | .catch(err => { 124 | 125 | logger.error('f5.iqScriptExecute failed with', err); 126 | }); 127 | })); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/cfCore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | * may copy and modify this software product for its internal business purposes. 5 | * Further, Licensee may upload, publish and distribute the modified version of 6 | * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | import { 12 | commands, 13 | ExtensionContext, 14 | ProgressLocation, 15 | window 16 | } from 'vscode'; 17 | 18 | import { ext } from './extensionVariables'; 19 | import * as utils from './utils/utils'; 20 | import { 21 | cfDeclaration 22 | } from 'f5-conx-core'; 23 | import { logger } from './logger'; 24 | 25 | /** 26 | * ``` 27 | * ######################################################################### 28 | * 29 | * 30 | * ██████ ███████ 31 | * ██ ██ 32 | * ██ █████ 33 | * ██ ██ 34 | * ██████ ██ 35 | * 36 | * 37 | * ######################################################################### 38 | * http://patorjk.com/software/taag/#p=display&h=0&f=ANSI%20Regular&t=CF 39 | * 40 | * registers CF commands in vscode 41 | * 42 | * ``` 43 | */ 44 | export class CfCore { 45 | 46 | constructor(context: ExtensionContext) { 47 | 48 | context.subscriptions.push(commands.registerCommand('f5-cf.inspect', async () => { 49 | 50 | ext.telemetry.capture({ command: 'f5-cf.inspect' }); 51 | 52 | await window.withProgress({ 53 | location: ProgressLocation.Notification, 54 | title: `Getting CF inspect` 55 | }, async () => { 56 | 57 | await ext.f5Client?.cf?.inspect() 58 | .then(resp => utils.displayJsonInEditor(resp.data)); 59 | 60 | }); 61 | 62 | 63 | })); 64 | 65 | context.subscriptions.push(commands.registerCommand('f5-cf.getDec', async () => { 66 | 67 | ext.telemetry.capture({ command: 'f5-cf.getDec' }); 68 | 69 | await window.withProgress({ 70 | location: ProgressLocation.Notification, 71 | title: `Getting CF Dec` 72 | }, async () => { 73 | 74 | await ext.f5Client?.cf?.getDeclare() 75 | .then(resp => utils.displayJsonInEditor(resp.data)); 76 | 77 | }); 78 | 79 | 80 | })); 81 | 82 | context.subscriptions.push(commands.registerCommand('f5-cf.postDec', async () => { 83 | 84 | ext.telemetry.capture({ command: 'f5-cf.postDec' }); 85 | 86 | await window.withProgress({ 87 | location: ProgressLocation.Notification, 88 | title: `Posting CF Dec` 89 | }, async () => { 90 | 91 | await utils.getText() 92 | .then(async text => { 93 | 94 | // convert text into json 95 | let dec: cfDeclaration = utils.isValidJson(text); 96 | 97 | if (!dec) { 98 | // if not valid json, return error message 99 | return window.showErrorMessage('Not valid JSON object'); 100 | } 101 | 102 | await ext.f5Client?.cf?.postDeclare(dec) 103 | .then(resp => utils.displayJsonInEditor(resp.data) ); 104 | }); 105 | 106 | 107 | }); 108 | 109 | })); 110 | 111 | 112 | context.subscriptions.push(commands.registerCommand('f5-cf.getTrigger', async () => { 113 | 114 | ext.telemetry.capture({ command: 'f5-cf.getTrigger' }); 115 | 116 | await window.withProgress({ 117 | location: ProgressLocation.Notification, 118 | title: `Getting CF Trigger details` 119 | }, async () => { 120 | 121 | await ext.f5Client?.cf?.getTrigger() 122 | .then(resp => utils.displayJsonInEditor(resp.data)); 123 | 124 | }); 125 | 126 | })); 127 | 128 | 129 | 130 | context.subscriptions.push(commands.registerCommand('f5-cf.triggerDryRun', async () => { 131 | 132 | ext.telemetry.capture({ command: 'f5-cf.triggerDryRun' }); 133 | await window.withProgress({ 134 | location: ProgressLocation.Notification, 135 | title: `Posting CF Trigger as Dry-Run` 136 | }, async () => { 137 | 138 | await ext.f5Client?.cf?.trigger('dry-run') 139 | .then(resp => logger.info('f5-cf.triggerDryRun -> COMPLETE', resp.data)); 140 | 141 | }); 142 | })); 143 | 144 | context.subscriptions.push(commands.registerCommand('f5-cf.trigger', async () => { 145 | 146 | ext.telemetry.capture({ command: 'f5-cf.trigger' }); 147 | 148 | await window.withProgress({ 149 | location: ProgressLocation.Notification, 150 | title: `Posting CF Trigger as Execute` 151 | }, async () => { 152 | 153 | await ext.f5Client?.cf?.trigger() 154 | .then(resp => logger.info('f5-cf.trigger -> COMPLETE', resp.data)); 155 | 156 | }); 157 | })); 158 | 159 | context.subscriptions.push(commands.registerCommand('f5-cf.reset', async () => { 160 | 161 | ext.telemetry.capture({ command: 'f5-cf.reset' }); 162 | await window.withProgress({ 163 | location: ProgressLocation.Notification, 164 | title: `Posting CF RESET` 165 | }, async () => { 166 | 167 | await ext.f5Client?.cf?.reset() 168 | .then(resp => logger.info('f5-cf.reset -> COMPLETE', resp.data)); 169 | 170 | }); 171 | })); 172 | } 173 | 174 | } 175 | 176 | -------------------------------------------------------------------------------- /src/changeVersion.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | * may copy and modify this software product for its internal business purposes. 5 | * Further, Licensee may upload, publish and distribute the modified version of 6 | * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | import * as path from 'path'; 12 | import * as fs from 'fs'; 13 | 14 | import { commands, ExtensionContext, window } from 'vscode'; 15 | import { getRPMgit, listGitReleases } from './utils/rpmMgmt'; 16 | import { ExtHttp } from 'f5-conx-core'; 17 | 18 | import { logger } from './logger'; 19 | import { ext } from './extensionVariables'; 20 | 21 | /** 22 | * Provides command to download github releases of this extension so users can easily access beta versions for testing 23 | */ 24 | export class ChangeVersion { 25 | /** 26 | * base repo releases 27 | */ 28 | readonly repo = 'https://api.github.com/repos/f5devcentral/vscode-f5/releases'; 29 | 30 | constructor(context: ExtensionContext, extHttp: ExtHttp) { 31 | 32 | context.subscriptions.push(commands.registerCommand('f5.changeVersion', async () => { 33 | 34 | ext.telemetry.capture({ command: 'f5.changeVersion' }); 35 | 36 | // 1. list releases on github repo 37 | // 2. provide list/selector for version 38 | // 3. download version 39 | // 4. install version, reload window? 40 | 41 | // get current extension home folder 42 | const extDir = path.join(context.extensionPath, '..'); 43 | 44 | logger.info('f5.changeVersion, fetching github releases'); 45 | 46 | // list available git releases and have the user select one 47 | const chosenVersion: string | { label: string, asset: string } | undefined = await listGitReleases(this.repo) 48 | .then(async versions => { 49 | logger.debug('f5.changeVersion, available version', versions); 50 | return await window.showQuickPick(versions, { placeHolder: 'Select Version' }); 51 | }); 52 | 53 | logger.info('f5.changeVersion, downloading chosen version', chosenVersion); 54 | 55 | // if we have a selection from the previous list 56 | if (chosenVersion && typeof chosenVersion === 'object' && chosenVersion.asset) { 57 | 58 | const downloadLocation = await extHttp.makeRequest({ url: chosenVersion.asset }) 59 | .then(async resp => { 60 | 61 | // loop through assets get needed information 62 | const assetSet = resp.data.assets.map((item: { name: string; browser_download_url: string; }) => { 63 | return { name: item.name, browser_download_url: item.browser_download_url }; 64 | }); 65 | logger.debug('f5.changeVersion assetSet', assetSet[0]); 66 | 67 | const destPath = path.join(extDir, assetSet[0].name); 68 | // if item already exists 69 | if (fs.existsSync(destPath)) { 70 | logger.debug(`${destPath} already cached!`); 71 | return destPath; 72 | } else { 73 | logger.debug(`${assetSet[0].name} NOT found in local cache, downloading...`); 74 | // await rpmDownload(item.browser_download_url, destPath); 75 | // return await downloadToFileNew(assetSet[0].browser_download_url, destPath) 76 | return await extHttp.download(assetSet[0].browser_download_url, undefined, extDir) 77 | .then(resp => { 78 | // return path to downloaded file 79 | return resp.data.file; 80 | }); 81 | } 82 | }) 83 | .catch(err => { 84 | logger.error('f5.changeVersion, choose/download failed', err); 85 | }); 86 | 87 | // // this command really doesn't work. 88 | // // https://github.com/microsoft/vscode-remote-release/issues/385 89 | // // https://github.com/microsoft/vscode-remote-release/issues/2749 90 | // // furthermore, code-server command for web based code would require detecting the environemnt and changing the command accordingly 91 | // logger.info('f5.changeVersion, the install command will probably NOT work, but at least the new extenion version will be downloaded and easily installable via the UI'); 92 | 93 | const cmd2Install = `code --install-extension ${downloadLocation}`; 94 | logger.info('f5.changeVersion, you can try the following command, or just "install vsix from UI", cmd: \n\n', cmd2Install, '\n\n'); 95 | 96 | // try { 97 | // // try to issue the install command via node sub-process 98 | // const installResp = cp.execSync(cmd2Install).toString(); 99 | // logger.info('f5.changeVersion, install response', installResp); 100 | 101 | // // TODO: this need some work. over remote-ssh file does not download and it doesn't fail appropriately 102 | // } catch (e) { 103 | 104 | // logger.info('f5.changeVersion, failed install', e); 105 | // } 106 | 107 | } else { 108 | logger.info('f5.changeVersion, valid selection details not detected, user probably exited quick pick dropdown'); 109 | } 110 | 111 | })); 112 | } 113 | } -------------------------------------------------------------------------------- /src/codeLens.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | import path from 'path'; 5 | import { 6 | CodeLens, 7 | CodeLensProvider as CLP, 8 | Range, 9 | TextDocument, 10 | EventEmitter as VsEventEmitter, 11 | Event as VsEvent, 12 | workspace 13 | } from "vscode"; 14 | 15 | 16 | 17 | 18 | 19 | 20 | export class CodeLensProvider implements CLP { 21 | 22 | private _onDidChangeCodeLenses: VsEventEmitter = new VsEventEmitter(); 23 | public readonly onDidChangeCodeLenses: VsEvent = this._onDidChangeCodeLenses.event; 24 | 25 | constructor() { 26 | 27 | workspace.onDidChangeConfiguration((_) => { 28 | this._onDidChangeCodeLenses.fire(); 29 | }); 30 | } 31 | 32 | async provideCodeLenses(document: TextDocument): Promise { 33 | 34 | const codeLens: CodeLens[] = []; 35 | 36 | const firstLine = new Range(0, 0, 0, 0); 37 | const secondLine = new Range(1, 0, 0, 0); 38 | 39 | const justFileName = path.parse(document.fileName).base; 40 | 41 | if (justFileName === 'tmosXcRules.json') { 42 | 43 | codeLens.push( 44 | new CodeLens( 45 | firstLine, 46 | { 47 | command: 'workbench.action.files.save', 48 | title: '--- SAVE ---', 49 | tooltip: 'Click to save diagnostic rules', 50 | } 51 | ) 52 | ); 53 | } 54 | 55 | return codeLens; 56 | } 57 | } -------------------------------------------------------------------------------- /src/doCore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | * may copy and modify this software product for its internal business purposes. 5 | * Further, Licensee may upload, publish and distribute the modified version of 6 | * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | import { 12 | commands, 13 | ExtensionContext, 14 | ProgressLocation, 15 | window 16 | } from 'vscode'; 17 | 18 | import { ext } from './extensionVariables'; 19 | import * as utils from './utils/utils'; 20 | // import { 21 | // DoDeclartion, 22 | // DeviceDeclartion 23 | // } from 'f5-conx-core'; 24 | import { logger } from './logger'; 25 | 26 | /** 27 | * ``` 28 | * ######################################################################### 29 | * 30 | * █████   ██████  31 | * ██   ██ ██    ██  32 | * ██  ██ ██  ██  33 | * ██  ██ ██  ██  34 | * █████    ██████   35 | * 36 | * ######################################################################### 37 | * http://patorjk.com/software/taag/#p=display&h=0&f=ANSI%20Regular&t=DO 38 | * 39 | * registers DO commands in vscode 40 | * 41 | * ``` 42 | */ 43 | export class DoCore { 44 | 45 | constructor(context: ExtensionContext) { 46 | 47 | context.subscriptions.push(commands.registerCommand('f5-do.getDec', async () => { 48 | 49 | ext.telemetry.capture({ command: 'f5-do.getDec' }); 50 | 51 | await window.withProgress({ 52 | location: ProgressLocation.Notification, 53 | title: `Getting DO Dec` 54 | }, async () => { 55 | 56 | await ext.f5Client?.do?.get() 57 | .then(resp => ext.panel.render(resp)); 58 | 59 | }); 60 | 61 | 62 | })); 63 | 64 | context.subscriptions.push(commands.registerCommand('f5-do.postDec', async () => { 65 | 66 | ext.telemetry.capture({ command: 'f5-do.postDec' }); 67 | 68 | await window.withProgress({ 69 | location: ProgressLocation.Notification, 70 | title: `Posting DO Dec` 71 | }, async () => { 72 | 73 | await utils.getText() 74 | .then(async text => { 75 | 76 | // convert text into json 77 | let dec = utils.isValidJson(text); 78 | 79 | if (!dec) { 80 | // if not valid json, return error message 81 | return window.showErrorMessage('Not valid JSON object'); 82 | } 83 | 84 | // testing this new function provided by f5-conx-core 85 | logger.info('is DO declaration async? =>', ext.f5Client?.do?.isAsync(dec)); 86 | 87 | // inspect json dec for async param 88 | if (!ext.f5Client?.do?.isAsync(dec)) { 89 | window.showWarningMessage('async DO post highly recommended!!!'); 90 | } 91 | 92 | // old way I was checking DO declaration for async post (now using above) 93 | // if (dec.class === 'DO' && (dec.declaration.async === false || dec.declaration.async === undefined)) { 94 | // window.showWarningMessage('async DO post highly recommended!!!'); 95 | // } else if (dec.class === 'Device' && (dec.async === false || dec.async === undefined)) { 96 | // window.showWarningMessage('async DO post highly recommended!!!'); 97 | // } 98 | 99 | await ext.f5Client?.do?.post(dec) 100 | .then(resp => ext.panel.render(resp) ); 101 | }); 102 | 103 | 104 | }); 105 | 106 | })); 107 | 108 | 109 | context.subscriptions.push(commands.registerCommand('f5-do.inspect', async () => { 110 | 111 | ext.telemetry.capture({ command: 'f5-do.inspect' }); 112 | 113 | await window.withProgress({ 114 | location: ProgressLocation.Notification, 115 | title: `Getting DO Inspect` 116 | }, async () => { 117 | 118 | await ext.f5Client?.do?.inpsect() 119 | .then(resp => ext.panel.render(resp)); 120 | 121 | }); 122 | 123 | })); 124 | 125 | 126 | 127 | context.subscriptions.push(commands.registerCommand('f5-do.getTasks', async () => { 128 | 129 | ext.telemetry.capture({ command: 'f5-do.getTasks' }); 130 | 131 | await window.withProgress({ 132 | location: ProgressLocation.Notification, 133 | title: `Getting DO Tasks` 134 | }, async () => { 135 | 136 | await ext.f5Client?.do?.task() 137 | .then(resp => ext.panel.render(resp)); 138 | 139 | }); 140 | })); 141 | } 142 | 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/editorViews/fastWebView.ts: -------------------------------------------------------------------------------- 1 | 2 | import { WebviewPanel, window, commands, ViewColumn, EventEmitter, Event, Uri } from 'vscode'; 3 | 4 | import { ext } from '../extensionVariables'; 5 | import { logger } from '../logger'; 6 | 7 | const fast = require('@f5devcentral/f5-fast-core'); 8 | 9 | type HttpResponse = ''; 10 | 11 | export class FastWebView { 12 | 13 | protected _onDidCloseAllWebviewPanels = new EventEmitter(); 14 | protected readonly panels: WebviewPanel[] = []; 15 | private showResponseInDifferentTab = false; 16 | protected activePanel: WebviewPanel | undefined; 17 | protected fastTemplateYml: string | undefined; 18 | protected fastEngine: any | undefined; 19 | 20 | private readonly panelResponses: Map; 21 | 22 | public constructor() { 23 | this.panelResponses = new Map(); 24 | // this.fastEngine = new fast.FsTemplateProvider(localPath); 25 | } 26 | 27 | public get onDidCloseAllWebviewPanels(): Event { 28 | 29 | return this._onDidCloseAllWebviewPanels.event; 30 | } 31 | 32 | protected get previewActiveContextKey(): string { 33 | return 'httpResponsePreviewFocus'; 34 | } 35 | 36 | protected setPreviewActiveContext(value: boolean) { 37 | commands.executeCommand('setContext', this.previewActiveContextKey, value); 38 | } 39 | 40 | protected displayRenderedTemplate(tempParams: string) { 41 | /** 42 | * take params from panel submit button 43 | * process through fast with template 44 | * then display in new editor to the right... 45 | */ 46 | 47 | // const final = this.fastEngine.template.render(tempParams); 48 | 49 | // ext.panel.render('text'); 50 | } 51 | 52 | protected async renderHTML(fastYml: string) { 53 | 54 | // invalidate the cache to load any template changes 55 | // this.fastEngine.invalidateCache(); 56 | 57 | /** 58 | * add checking for YAML format since we only want to support yaml 59 | * 60 | */ 61 | try { 62 | this.fastEngine = await fast.Template.loadYaml(fastYml); 63 | } catch (e: any) { 64 | logger.error(e); 65 | window.showErrorMessage(e.message); 66 | } 67 | 68 | // this.fastEngine.invalidateCache(); 69 | const schema = this.fastEngine.getParametersSchema(); 70 | const defaultParams = this.fastEngine.getCombinedParameters(); 71 | const htmlData = fast.guiUtils.generateHtmlPreview(schema, defaultParams); 72 | return htmlData; 73 | } 74 | 75 | public async render(fastYml: string) { 76 | 77 | // put the incoming fast template somewhere 78 | this.fastTemplateYml = fastYml; 79 | 80 | // // invalidate the cache to load any template changes 81 | // this.fastEngine.invalidateCache(); 82 | 83 | // create 84 | let html = await this.renderHTML(fastYml); 85 | 86 | let title = 'test-title'; 87 | 88 | const newEditorColumn = ext.settings.previewColumn; 89 | const preserveEditorFocus = ext.settings.preserveEditorFocus; 90 | const newEditorTabForAll = ext.settings.newEditorTabForAll; 91 | let viewColumn: ViewColumn | undefined; 92 | 93 | viewColumn = viewColumn ? viewColumn : newEditorColumn; 94 | 95 | let panel: WebviewPanel; 96 | if (this.showResponseInDifferentTab || this.panels.length === 0) { 97 | panel = window.createWebviewPanel( 98 | 'fast webView', 99 | title, 100 | { viewColumn: viewColumn, preserveFocus: !preserveEditorFocus }, 101 | { 102 | enableFindWidget: true, 103 | enableScripts: true, 104 | retainContextWhenHidden: true 105 | }); 106 | 107 | panel.onDidDispose(() => { 108 | if (panel === this.activePanel) { 109 | this.setPreviewActiveContext(false); 110 | this.activePanel = undefined; 111 | } 112 | 113 | const index = this.panels.findIndex(v => v === panel); 114 | if (index !== -1) { 115 | this.panels.splice(index, 1); 116 | this.panelResponses.delete(panel); 117 | } 118 | if (this.panels.length === 0) { 119 | this._onDidCloseAllWebviewPanels.fire(); 120 | } 121 | }); 122 | 123 | panel.onDidChangeViewState(({ webviewPanel }) => { 124 | const active = this.panels.some(p => p.active); 125 | this.setPreviewActiveContext(active); 126 | this.activePanel = webviewPanel.active ? webviewPanel : undefined; 127 | }); 128 | 129 | panel.webview.onDidReceiveMessage(async message => { 130 | // console.log( message ); 131 | 132 | try { 133 | const final = await this.fastEngine.render(message); 134 | ext.panel.render(final); 135 | } catch (e) { 136 | logger.error(e); 137 | // window.showErrorMessage(e.message); 138 | } 139 | 140 | }); 141 | 142 | this.panels.push(panel); 143 | } else { 144 | panel = this.panels[this.panels.length - 1]; 145 | panel.title = title; 146 | } 147 | 148 | 149 | /** 150 | * Appends the necessary stuff for submit button and getting template params 151 | * move the following to it's own function 152 | */ 153 | const htmlSubmitBtn = ` 154 | 160 | 161 |

162 | `; 163 | 164 | html += htmlSubmitBtn; 165 | 166 | panel.webview.html = html; 167 | panel.reveal(viewColumn, !preserveEditorFocus); 168 | this.activePanel = panel; 169 | } 170 | 171 | } -------------------------------------------------------------------------------- /src/extLoader.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export type PerfStats = { 4 | loadStartTime: number; 5 | loadEndTime?: number; 6 | activationTime?: number; 7 | load?: number; 8 | activate?: number; 9 | }; 10 | 11 | const perfStats: PerfStats = { 12 | loadStartTime: Date.now() 13 | }; 14 | 15 | // Object.defineProperty(exports, "__esModule", { value: true }); 16 | 17 | import { ExtensionContext } from 'vscode'; 18 | import { 19 | activate as activateInternal, 20 | deactivate as deactivateInternal 21 | } from './extension'; 22 | 23 | // while this may load the code/references, it will be empty 24 | import { ext } from './extensionVariables'; 25 | import { logger } from './logger'; 26 | 27 | async function activate(ctx: ExtensionContext) { 28 | 29 | // we need to await this to complete so we can gather stats and log as needed 30 | await activateInternal(ctx); 31 | perfStats.activationTime = Date.now(); 32 | 33 | perfStats.activate = (perfStats.activationTime - perfStats.loadStartTime); 34 | 35 | // now that the entire extension has loaded, we can actually call the following telemtry and logging functions and they work 36 | ext.telemetry.capture({ 37 | command: "extensionActivation", 38 | stats: perfStats 39 | }); 40 | logger.info(`load stats: ${JSON.stringify(perfStats)}`); 41 | 42 | return; 43 | } 44 | 45 | async function deactivate(ctx: any) { 46 | await deactivateInternal(ctx); 47 | console.log(`de-activation complete in ${Math.floor((Date.now() - perfStats.loadStartTime) / 1000 )}ms`); 48 | return; 49 | } 50 | 51 | exports.activate = activate; 52 | exports.deactivate = deactivate; 53 | 54 | perfStats.loadEndTime = Date.now(); 55 | perfStats.load = (perfStats.loadEndTime - perfStats.loadStartTime); -------------------------------------------------------------------------------- /src/logger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 F5 Networks, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 'use strict'; 18 | 19 | import Logger from 'f5-conx-core/dist/logger'; 20 | 21 | 22 | /** 23 | * the whole point of this logger file is to instantiate a unique logger instance and return the singleton instance for the rest of the extension 24 | * 25 | * This allows for another unique instance to be used for other extensions 26 | * 27 | * https://stackoverflow.com/questions/30174078/how-to-define-singleton-in-typescript 28 | * 29 | * 30 | */ 31 | 32 | export const logger = new Logger('F5_VSCODE_LOG_LEVEL'); 33 | // export const logger = loggerInst; 34 | -------------------------------------------------------------------------------- /src/models.ts: -------------------------------------------------------------------------------- 1 | import { F5TmosProduct } from "f5-conx-core"; 2 | import { Stats, TmosApp } from "f5-corkscrew"; 3 | 4 | 5 | 6 | export type CfgExploreReport = { 7 | Greeting: string; 8 | repo: string; 9 | extensionVersion: string; 10 | corkscrewVersion: string; 11 | issues: string; 12 | documentation: string; 13 | label?: string; 14 | description?: string; 15 | id: string; 16 | dateTime: Date; 17 | hostname?: string; 18 | baseRegKey?: string; 19 | inputFileType: string; 20 | sourceFileCount?: number; 21 | appCount?: number; 22 | cfgExploreStats: Stats; 23 | cfgExploreParsedFiles: string[]; 24 | xcDiagStats?: { 25 | Green?: number; 26 | Error?: number; 27 | Warning?: number; 28 | Information?: number; 29 | defaultRedirects: number; 30 | }; 31 | xcDiags?: { 32 | Green?: string[]; 33 | Information?: { 34 | appName: string; 35 | diagnostics: string[]; 36 | }[]; 37 | Warning?: { 38 | appName: string; 39 | diagnostics: string[]; 40 | }[]; 41 | Error?: { 42 | appName: string; 43 | diagnostics: string[]; 44 | }[]; 45 | defaultRedirects: string[]; 46 | } 47 | apps: TmosAppReport[]; 48 | gslb?: any; 49 | }; 50 | 51 | export interface TmosAppReport extends TmosApp { 52 | xcDiagnostics: string[] 53 | xcDiagStats: unknown; 54 | xcDiagStatus: string; 55 | } 56 | 57 | /** 58 | * extension device model for hosts view 59 | */ 60 | export type BigipHost = { 61 | device: string, 62 | label?: string, 63 | folder?: string, 64 | product?: F5TmosProduct; 65 | details?: { 66 | platformMarketingName?: string; 67 | version?: string; 68 | hostname?: string; 69 | managementAddress?: string; 70 | platform?: string; 71 | physicalMemory?: number; 72 | } 73 | provider: string, 74 | onConnect?: string[], 75 | onDisconnect?: string[] 76 | }; -------------------------------------------------------------------------------- /src/proxy_issue#88.md: -------------------------------------------------------------------------------- 1 | 2 | # proxy configuration objects 3 | 4 | this is just a placeholder for configuration/documentation for the external HTTP proxy support 5 | 6 | issue details can be found here: 7 | 8 | - [#88](https://github.com/f5devcentral/vscode-f5/issues/88) - [RFE] Examples Requests with web proxy support (**PENDING**) 9 | - Provides configuration options for external proxy support 10 | - This would be for all calls not destined for an F5 11 | 12 | 13 | proxy "configuration" section for the package.json 14 | 15 | ```json 16 | "f5.proxy": { 17 | "type": "object", 18 | "description": "external HTTP(s) proxy details", 19 | "port": { 20 | "type": "number" 21 | }, 22 | "host": { 23 | "type": "string" 24 | }, 25 | "required": [ 26 | "host", 27 | "port" 28 | ], 29 | "examples": [ 30 | { 31 | "protocol": "https", 32 | "host": "127.0.0.1", 33 | "port": 9000, 34 | "auth": { 35 | "username": "mikeymike", 36 | "password": "rapunz3l" 37 | } 38 | } 39 | ] 40 | }, 41 | "f5.proxyAuth": { 42 | "type": "object", 43 | "username": { 44 | "type": "string" 45 | }, 46 | "password": { 47 | "type": "string" 48 | } 49 | } 50 | ``` 51 | 52 | 53 | extensionVariables.ts 54 | 55 | ```ts 56 | 57 | // in the loadSettings function 58 | 59 | // ext.settings.proxy = workspace.getConfiguration().get('f5.proxy'); 60 | const proxyCfg = workspace.getConfiguration('f5.proxy'); 61 | const proxyAuthCfg = workspace.getConfiguration('f5.proxyAuth'); 62 | 63 | if (proxyCfg) { 64 | 65 | ext.settings.proxy = { 66 | host: proxyCfg.get('host'), 67 | port: proxyCfg.get('port'), 68 | protocol: proxyCfg.get('protocol'), 69 | }; 70 | 71 | if (proxyAuthCfg.has('username') && proxyAuthCfg.has('password')) { 72 | ext.settings.proxy.auth = { 73 | username: proxyAuthCfg.get('username'), 74 | password: proxyAuthCfg.get('password') 75 | }; 76 | } 77 | const y = 'x'; 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /src/rpmCore.ts: -------------------------------------------------------------------------------- 1 | // /* 2 | // * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | // * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | // * may copy and modify this software product for its internal business purposes. 5 | // * Further, Licensee may upload, publish and distribute the modified version of 6 | // * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | // */ 8 | 9 | // 'use strict'; 10 | 11 | // import { 12 | // window, 13 | // commands, 14 | // ProgressLocation, 15 | // ExtensionContext 16 | // } from "vscode"; 17 | // import { ext } from "./extensionVariables"; 18 | // import * as rpmMgmt from './utils/rpmMgmt'; 19 | // import { Asset, HttpResponse, isArray } from 'f5-conx-core'; 20 | // import { BigipTreeProvider } from "./treeViewsProviders/bigipTreeProvider"; 21 | 22 | 23 | // /** 24 | // * core rpm install/unInstall functionality 25 | // */ 26 | // export default function rpmCore(context: ExtensionContext) { 27 | 28 | 29 | 30 | 31 | 32 | // } -------------------------------------------------------------------------------- /src/tclCore.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | * may copy and modify this software product for its internal business purposes. 5 | * Further, Licensee may upload, publish and distribute the modified version of 6 | * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | import { 12 | window, 13 | commands, 14 | ExtensionContext 15 | } from "vscode"; 16 | import { ext } from "./extensionVariables"; 17 | import { TclTreeProvider } from "./treeViewsProviders/tclTreeProvider"; 18 | 19 | import { logger } from './logger'; 20 | 21 | /** 22 | * core tcl commands functionality 23 | */ 24 | export default function tclCore(context: ExtensionContext) { 25 | 26 | 27 | 28 | 29 | /** 30 | * ########################################################################### 31 | * 32 | * TTTTTTT CCCCC LL 33 | * TTT CC C LL 34 | * TTT CC LL 35 | * TTT CC C LL 36 | * TTT CCCCC LLLLLLL 37 | * 38 | * ############################################################################ 39 | * http://patorjk.com/software/taag/#p=display&h=0&f=Letters&t=FAST 40 | */ 41 | 42 | 43 | const tclTreeProvider = new TclTreeProvider(); 44 | const tctTreeView = window.createTreeView('as3Tasks', { 45 | treeDataProvider: tclTreeProvider, 46 | showCollapseAll: true 47 | }); 48 | commands.registerCommand('f5.refreshTclTree', () => tclTreeProvider.refresh()); 49 | 50 | 51 | // --- IRULE COMMANDS --- 52 | context.subscriptions.push(commands.registerCommand('f5-tcl.getRule', async (rule) => { 53 | return tclTreeProvider.displayRule(rule); 54 | })); 55 | 56 | context.subscriptions.push(commands.registerCommand('f5-tcl.deleteRule', async (rule) => { 57 | return tclTreeProvider.deleteRule(rule); 58 | })); 59 | 60 | // --- ICALL Script COMMANDS --- 61 | context.subscriptions.push(commands.registerCommand('f5-tcl.getIcallscript', async (icallscript) => { 62 | return tclTreeProvider.displayIcallscript(icallscript); 63 | })); 64 | 65 | context.subscriptions.push(commands.registerCommand('f5-tcl.deleteIcallscript', async (icallscript) => { 66 | return tclTreeProvider.deleteIcallscript(icallscript); 67 | })); 68 | 69 | 70 | // --- TMSH Script COMMANDS --- 71 | context.subscriptions.push(commands.registerCommand('f5-tcl.getTMSHscript', async (tmshscript) => { 72 | return tclTreeProvider.displayTMSHscript(tmshscript); 73 | })); 74 | 75 | context.subscriptions.push(commands.registerCommand('f5-tcl.deleteTMSHscript', async (tmshscript) => { 76 | return tclTreeProvider.deleteTMSHscript(tmshscript); 77 | })); 78 | 79 | 80 | // --- IAPP COMMANDS --- 81 | context.subscriptions.push(commands.registerCommand('f5-tcl.getApp', async (item) => { 82 | logger.debug('f5-tcl.getApp command: ', item); 83 | return ext.panel.render(item); 84 | })); 85 | 86 | 87 | context.subscriptions.push(commands.registerCommand('f5-tcl.getTemplate', async (item) => { 88 | // returns json view of iApp Template 89 | return ext.panel.render(item); 90 | })); 91 | 92 | 93 | context.subscriptions.push(commands.registerCommand('f5-tcl.getTMPL', async (item) => { 94 | // gets the original .tmpl output 95 | const temp = await tclTreeProvider.getTMPL(item); 96 | tclTreeProvider.displayTMPL(temp); 97 | })); 98 | 99 | context.subscriptions.push(commands.registerCommand('f5-tcl.iAppRedeploy', async (item) => { 100 | const temp = await tclTreeProvider.iAppRedeploy(item); 101 | /** 102 | * setup appropriate response 103 | * - if no error - nothing 104 | * - if error, editor/pop-up to show error 105 | */ 106 | // return utils.displayJsonInEditor(item); 107 | })); 108 | 109 | context.subscriptions.push(commands.registerCommand('f5-tcl.iAppDelete', async (item) => { 110 | const temp = await tclTreeProvider.iAppDelete(item); 111 | tclTreeProvider.refresh(); 112 | })); 113 | 114 | context.subscriptions.push(commands.registerCommand('f5-tcl.postTMPL', async (item) => { 115 | const resp: any = await tclTreeProvider.postTMPL(item); 116 | window.showInformationMessage(resp); 117 | return resp; 118 | })); 119 | 120 | context.subscriptions.push(commands.registerCommand('f5-tcl.deleteTMPL', async (item) => { 121 | const resp: any = await tclTreeProvider.deleteTMPL(item); 122 | return resp; 123 | })); 124 | 125 | context.subscriptions.push(commands.registerCommand('f5-tcl.mergeTCL', async (item) => { 126 | await tclTreeProvider.mergeTCL(item); 127 | })); 128 | 129 | context.subscriptions.push(commands.registerCommand('f5-tcl.replaceTCL', async (item) => { 130 | await tclTreeProvider.mergeTCL(item, true); 131 | })); 132 | 133 | 134 | } -------------------------------------------------------------------------------- /src/test/runTest.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | import { runTests } from '@vscode/test-electron'; 4 | 5 | // set the version of vscode engine to use for tests 6 | const version = 'stable'; 7 | // https://code.visualstudio.com/updates/ 8 | 9 | async function main() { 10 | try { 11 | // The folder containing the Extension Manifest package.json 12 | // Passed to `--extensionDevelopmentPath` 13 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 14 | 15 | // The path to test runner 16 | // Passed to --extensionTestsPath 17 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 18 | 19 | // Download VS Code, unzip it and run the integration test 20 | await runTests({ extensionDevelopmentPath, extensionTestsPath, version }); 21 | } catch (err) { 22 | console.error('Failed to run tests'); 23 | process.exit(1); 24 | } 25 | } 26 | 27 | main(); 28 | -------------------------------------------------------------------------------- /src/test/suite/deviceImport.tests.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import fs = require('fs'); 3 | import path = require('path'); 4 | 5 | // import * as vscode from 'vscode'; 6 | import { deviceImport, exampleImport } from '../../deviceImport'; 7 | 8 | 9 | suite('device import tests', () => { 10 | // vscode.window.showInformationMessage('Starting gui tests.'); 11 | test('import seed file - success', async () => { 12 | 13 | deviceImport('this is a seed file'); 14 | 15 | // check snippet against isolated copy 16 | assert.deepStrictEqual('a', 'a'); 17 | 18 | }).timeout(5000); 19 | 20 | 21 | 22 | 23 | 24 | }); -------------------------------------------------------------------------------- /src/test/suite/deviceMgmt.test.ts: -------------------------------------------------------------------------------- 1 | 2 | import { commands } from 'vscode'; 3 | import { logger } from '../../logger'; 4 | 5 | suite('device mgmt tasks', () => { 6 | 7 | 8 | 9 | 10 | test('preclear the device to prep for add', async () => { 11 | 12 | try { 13 | 14 | await commands.executeCommand('f5.removeHost', 'tst9843@1.1.1.1'); 15 | } catch (e) { 16 | 17 | console.log(e, logger.journal.join('\n')); 18 | } 19 | 20 | }).timeout(10000); 21 | 22 | test('add new device', async () => { 23 | 24 | await commands.executeCommand('f5.addHost', 'tst9843@1.1.1.1'); 25 | 26 | }).timeout(10000); 27 | 28 | test('remove new device just added', async () => { 29 | 30 | await new Promise(r => setTimeout(r, 500)); 31 | 32 | try { 33 | 34 | await commands.executeCommand('f5.removeHost', 'tst9843@1.1.1.1'); 35 | } catch (e) { 36 | 37 | console.log(e, logger.journal.join('\n')); 38 | } 39 | 40 | }).timeout(10000); 41 | 42 | }); 43 | -------------------------------------------------------------------------------- /src/test/suite/extension.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import fs = require('fs'); 3 | import path = require('path'); 4 | 5 | 6 | // You can import and use all API from the 'vscode' module 7 | // as well as import your extension to test it 8 | import { window, commands, EndOfLine, workspace} from 'vscode'; 9 | import * as utils from '../../utils/utils'; 10 | 11 | const snippets = requireText(path.join(__dirname, '..', '..', '..', 'snippets', 'snippets.json')); 12 | 13 | 14 | /** 15 | * import/require file to string variable 16 | * @param path file path/name 17 | * @returns file contents as string 18 | */ 19 | export function requireText(path: string): string { 20 | return fs.readFileSync(require.resolve(path)).toString(); 21 | } 22 | 23 | 24 | suite('Extension GUI tests', () => { 25 | window.showInformationMessage('Starting gui tests.'); 26 | test('open JSON editor -> insert as3 snippet', async () => { 27 | 28 | // // clear all open editors 29 | await commands.executeCommand('workbench.action.closeAllEditors'); 30 | // // open a new text editor 31 | const jsonEditor = await workspace.openTextDocument({ language: 'json' }); 32 | // // show new text editor (make active) 33 | const textDoc = await window.showTextDocument(jsonEditor, {preview: false}); 34 | 35 | // // inject sample as3 snippet 36 | await commands.executeCommand('editor.action.insertSnippet', 37 | { name: "example_F5_AS3_declaration"} 38 | ); 39 | 40 | // set the end of line for linux 41 | await textDoc.edit(e => e.setEndOfLine(EndOfLine.LF)); 42 | 43 | // capture editor text 44 | const editorText = jsonEditor.getText(); 45 | 46 | // get original snippet text to compare 47 | const snippet = JSON.parse(snippets).example_F5_AS3_declaration.body; 48 | const snippet2 = snippet.join('\n').replace('\\$schema', '$schema'); 49 | 50 | // const source = JSON.parse(snippet); 51 | // const output = JSON.parse(editorText); 52 | 53 | // check snippet against isolated copy 54 | assert.deepStrictEqual(snippet2, editorText); 55 | 56 | }).timeout(5000); 57 | 58 | 59 | test('open test json in editor #1 - tests utils.displayJsonInEditor', async () => { 60 | await commands.executeCommand('workbench.action.closeAllEditors'); 61 | 62 | // // option #1 - use the editor object created by the displayJsonInEditor function 63 | // to know which editor has the text we need to test 64 | const testObj: object = { "key1": "value1", "key2": "value2"}; 65 | const editr = await utils.displayJsonInEditor(testObj); 66 | assert.deepStrictEqual(testObj, JSON.parse(editr.document.getText())); 67 | }); 68 | 69 | test('open test json in editor #2 - tests utils.displayJsonInEditor', async () => { 70 | await commands.executeCommand('workbench.action.closeAllEditors'); 71 | 72 | // // option #2 - capture the active editor since we don't know what it is 73 | // to know which editor has the text we need to test 74 | const testObj2: object = { "key1": "value1", "key2": "value2"}; 75 | 76 | // need to wait for this to complete 77 | await utils.displayJsonInEditor(testObj2); 78 | 79 | // capture currrent editor 80 | const editor = window.activeTextEditor; 81 | 82 | if(!editor) { 83 | return Error("uh..oh..."); 84 | } 85 | 86 | // get text from editor 87 | const text = editor.document.getText(); 88 | 89 | assert.deepStrictEqual(testObj2, JSON.parse(text)); 90 | 91 | }).timeout(5000); 92 | }); -------------------------------------------------------------------------------- /src/test/suite/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import Mocha from 'mocha'; 3 | import glob from 'glob'; 4 | 5 | export function run(): Promise { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | }); 10 | // mocha.c(true); 11 | mocha.options.color = true; 12 | 13 | const testsRoot = path.resolve(__dirname, '..'); 14 | 15 | return new Promise((c, e) => { 16 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 17 | if (err) { 18 | return e(err); 19 | } 20 | 21 | // Add files to the test suite 22 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 23 | 24 | try { 25 | // Run the mocha test 26 | mocha.run(failures => { 27 | if (failures > 0) { 28 | e(new Error(`${failures} tests failed.`)); 29 | } else { 30 | c(); 31 | } 32 | }); 33 | } catch (err) { 34 | console.error(err); 35 | e(err); 36 | } 37 | }); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /src/test/testingProceedure.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Testing 4 | 5 | This document is an attempt to detail the general steps to "test" this vscode extension 6 | 7 | ## Cor 8 | -------------------------------------------------------------------------------- /src/tokenTimer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 3 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 4 | * may copy and modify this software product for its internal business purposes. 5 | * Further, Licensee may upload, publish and distribute the modified version of 6 | * the software product on devcentral.f5.com or github.com/f5devcentral. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | import { 12 | window, 13 | StatusBarItem, 14 | StatusBarAlignment 15 | } from 'vscode'; 16 | import { ext } from './extensionVariables'; 17 | import { logger } from './logger'; 18 | 19 | export function tokenTimer(hide?: boolean) { 20 | 21 | const tokenTimerBar: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 50); 22 | 23 | tokenTimerBar.tooltip = 'F5 AuthToken Timer'; 24 | 25 | if (hide) { 26 | tokenTimerBar.hide(); 27 | } 28 | 29 | ext.eventEmitterGlobal 30 | .on('token-timer-start', msg => { 31 | 32 | tokenTimerBar.show(); 33 | logger.info(msg); 34 | 35 | }) 36 | .on('token-timer-expired', msg => { 37 | 38 | tokenTimerBar.hide(); 39 | logger.info(msg); 40 | 41 | }) 42 | .on('token-timer-count', second => { 43 | 44 | if (second <= 30) { 45 | // turn text color reddish/pink to indicate expiring token 46 | tokenTimerBar.color = '#ED5A75'; 47 | } else { 48 | tokenTimerBar.color = 'silver'; 49 | } 50 | 51 | tokenTimerBar.text = `${second}`; 52 | }); 53 | } -------------------------------------------------------------------------------- /src/utils/f5FastApi.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { ext } from '../extensionVariables'; 3 | import { logger } from '../logger'; 4 | 5 | 6 | /** 7 | * Post/Deploy fast app 8 | * @param device BIG-IP/Host/Device in @ format 9 | * @param password User Password 10 | * @param postParam 11 | * @param dec Delcaration 12 | */ 13 | export async function deployFastApp(dec: object) { 14 | 15 | // logger.debug(`fast app declaration`, dec); 16 | 17 | const progressPost = await vscode.window.withProgress({ 18 | location: vscode.ProgressLocation.Notification, 19 | title: "Deploying FAST Application", 20 | cancellable: true 21 | }, async (progress, token) => { 22 | token.onCancellationRequested(() => { 23 | // this logs but doesn't actually cancel... 24 | logger.debug("User canceled the async post"); 25 | return new Error(`User canceled the async post`); 26 | }); 27 | 28 | // post initial dec 29 | let response: any = await ext.f5Client?.https(`/mgmt/shared/fast/applications`, { 30 | method: 'POST', 31 | data: dec 32 | }); 33 | 34 | progress.report({ message: `${response.statusText}`}); 35 | 36 | let taskId: string | undefined; 37 | if(response.status === 202) { 38 | taskId = response.data.message[0].id; 39 | 40 | await new Promise(resolve => { setTimeout(resolve, (ext.settings.asyncInterval * 1000)); }); 41 | 42 | 43 | // get got a 202 and a taskId (single dec), check task status till complete 44 | while(taskId) { 45 | response = await ext.f5Client?.https(`/mgmt/shared/fast/tasks/${taskId}`); 46 | 47 | // if not 'in progress', its done, clear taskId to break loop 48 | if(response.data.message !== 'in progress'){ 49 | taskId = undefined; 50 | vscode.window.showInformationMessage(`Deploying FAST Application: ${response.data.message}`); 51 | return response; 52 | } 53 | 54 | progress.report({ message: `${response.data.message}`}); 55 | await new Promise(resolve => { setTimeout(resolve, (ext.settings.asyncInterval * 1000)); }); 56 | } 57 | 58 | // progress.report({ message: `${response.data.message}`}); 59 | // await new Promise(resolve => { setTimeout(resolve, 3000); }); 60 | } 61 | // return response from regular post 62 | 63 | return response; 64 | }); 65 | return progressPost; 66 | } 67 | 68 | 69 | 70 | /** 71 | * Delete FAST app 72 | * @param device BIG-IP/Host/Device in @ format 73 | * @param password User Password 74 | * @param tenApp tenant/app 75 | */ 76 | export async function delTenApp(tenApp: string) { 77 | 78 | const progressDelete = await vscode.window.withProgress({ 79 | location: vscode.ProgressLocation.Notification, 80 | title: `Deleting FAST App: ${tenApp}` 81 | }, async (progress) => { 82 | 83 | let response: any = await ext.f5Client?.https(`/mgmt/shared/fast/applications/${tenApp}`, { 84 | method: 'DELETE' 85 | }); 86 | 87 | let taskId: string | undefined; 88 | if(response.status === 202) { 89 | taskId = response.data.id; 90 | 91 | await new Promise(resolve => { setTimeout(resolve, 1000); }); 92 | while(taskId) { 93 | 94 | response = await ext.f5Client?.https(`/mgmt/shared/fast/tasks/${taskId}`); 95 | 96 | // if not 'in progress', its done, clear taskId to break loop 97 | if(response.data.message !== 'in progress'){ 98 | taskId = undefined; 99 | return response; 100 | } 101 | 102 | progress.report({ message: `${response.data.message}`}); 103 | await new Promise(resolve => { setTimeout(resolve, (ext.settings.asyncInterval * 1000)); }); 104 | } 105 | } 106 | 107 | return response; 108 | }); 109 | return progressDelete; 110 | } 111 | 112 | 113 | 114 | /** 115 | * Delete FAST template set 116 | * @param device BIG-IP/Host/Device in @ format 117 | * @param password User Password 118 | * @param tempSet templateSet anme 119 | */ 120 | export async function delTempSet(tempSet: string) { 121 | 122 | const progressDelete = await vscode.window.withProgress({ 123 | location: vscode.ProgressLocation.Notification, 124 | title: `Deleting FAST Template Set: ${tempSet}` 125 | }, async (progress) => { 126 | 127 | let response: any = await ext.f5Client?.https(`/mgmt/shared/fast/templatesets/${tempSet}`, { 128 | method: 'DELETE' 129 | }); 130 | 131 | let taskId: string | undefined; 132 | if(response.status === 202) { 133 | taskId = response.data.id; 134 | 135 | await new Promise(resolve => { setTimeout(resolve, 1000); }); 136 | while(taskId) { 137 | response = await ext.f5Client?.https(`/mgmt/shared/fast/tasks/${taskId}`); 138 | 139 | // if not 'in progress', its done, clear taskId to break loop 140 | if(response.data.message !== 'in progress'){ 141 | taskId = undefined; 142 | return response; 143 | } 144 | 145 | progress.report({ message: `${response.data.message}`}); 146 | await new Promise(resolve => { setTimeout(resolve, (ext.settings.asyncInterval * 1000)); }); 147 | 148 | } 149 | } 150 | 151 | return response; 152 | }); 153 | return progressDelete; 154 | } -------------------------------------------------------------------------------- /src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { TextDocument, window, workspace } from 'vscode'; 2 | import { ext } from '../extensionVariables'; 3 | import { logger } from '../logger'; 4 | 5 | 6 | /** 7 | * display json in new editor window 8 | * @param item json object to display in new editor 9 | */ 10 | export async function displayJsonInEditor(item: object): Promise { 11 | return workspace.openTextDocument({ 12 | language: 'json', 13 | content: JSON.stringify(item, undefined, 4) 14 | }) 15 | .then( doc => 16 | window.showTextDocument( 17 | doc, 18 | { 19 | preview: false 20 | } 21 | ) 22 | ); 23 | } 24 | 25 | 26 | /** 27 | * display mst in new editor window 28 | * @param item json object to display in new editor for mst 29 | */ 30 | export async function displayMstInEditor(item: object): Promise { 31 | return workspace.openTextDocument({ 32 | language: 'handlebars', 33 | content: JSON.stringify(item, undefined, 4) 34 | }) 35 | .then( doc => 36 | window.showTextDocument( 37 | doc, 38 | { 39 | preview: false 40 | } 41 | ) 42 | ); 43 | } 44 | 45 | 46 | /** 47 | * display text in new editor window 48 | * @param item string to display in new editor 49 | */ 50 | export async function displayInTextEditor(text: string): Promise { 51 | return workspace.openTextDocument({ 52 | content: text 53 | }) 54 | .then( doc => 55 | window.showTextDocument( 56 | doc, 57 | { 58 | preview: false 59 | } 60 | ) 61 | ); 62 | } 63 | 64 | 65 | /** 66 | * validates json blob 67 | * @param json 68 | * @returns parsed json object 69 | */ 70 | export function isValidJson(json: string) { 71 | try { 72 | return JSON.parse(json); 73 | // return true; 74 | } catch (e) { 75 | return false; 76 | } 77 | } 78 | 79 | 80 | 81 | 82 | /** 83 | * Get password from keytar or prompt 84 | * @param device BIG-IP/Host/Device in @ format 85 | */ 86 | export async function getPassword(device: string): Promise { 87 | 88 | // logger.debug(`getPassword Device: ${device}`); 89 | 90 | // let password = await ext.keyTar.getPassword('f5Hosts', device).then( passwd => passwd ); 91 | let password = await ext.context.secrets.get(device); 92 | 93 | // logger.debug(`IS PASSWORD IN KEYTAR?: ${password}`); 94 | if (!password) { 95 | // logger.debug(`NO PASSWORD IN KEYTAR! - PROMPTING!!! - ${password}`); 96 | password = await window.showInputBox({ 97 | placeHolder: 'Password', 98 | prompt: 'Input device password: ', 99 | password: true 100 | }) 101 | .then( password => { 102 | if (!password) { 103 | throw new Error('User cancelled password input'); 104 | } 105 | // logger.debug(`USER INPUT PASSWORD!!! - ${password}`); 106 | return password; 107 | }); 108 | } 109 | // logger.debug(`PASSWORD BOUT TO BE RETURNED!!! - ${password}`); 110 | return password; 111 | } 112 | 113 | /** 114 | * capture entire active editor text or selected text 115 | */ 116 | export async function getText(doc?: TextDocument): Promise { 117 | 118 | // todo: update function to accept doc and a flag to confirm/parse json 119 | 120 | // get editor window 121 | var editor = window.activeTextEditor; 122 | if (editor) { 123 | // capture selected text or all text in editor 124 | if (editor.selection.isEmpty) { 125 | return editor.document.getText(); // entire editor/doc window 126 | } else { 127 | return editor.document.getText(editor.selection); // highlighted text 128 | } 129 | } else { 130 | logger.warn('getText was called, but no active editor... this should not happen'); 131 | throw new Error('getText was called, but no active editor... this should not happen'); // No open/active text editor 132 | } 133 | 134 | } -------------------------------------------------------------------------------- /src/x509.ts: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for 4 | * license terms. Notwithstanding anything to the contrary in the EULA, Licensee 5 | * may copy and modify this software product for its internal business purposes. 6 | * Further, Licensee may upload, publish and distribute the modified version of 7 | * the software product on devcentral.f5.com or github.com/f5devcentral. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | 13 | import * as tls from 'tls'; 14 | import * as net from 'net'; 15 | 16 | type tlsCert = { 17 | subject: unknown, 18 | issuer: unknown, 19 | valid_from: unknown, 20 | valid_to: unknown, 21 | serialNumber: string, 22 | bits: number 23 | }; 24 | 25 | /** 26 | * parse/decode raw cert body 27 | * -----BEGIN CERTIFICATE----- / -----END CERTIFICATE----- 28 | * 29 | * returns { subject, issuer, valid_from, valid_to, serialNumber, bits } 30 | * 31 | * @param cert 32 | */ 33 | export function parseX509(cert: string): string { 34 | // https://stackoverflow.com/questions/58724396/parse-x509-certificate-string-in-node 35 | 36 | cert = cert.replace(/\\n/g, "\n"); 37 | 38 | // create a tls context with the certificate (like we are going to make an https connection) 39 | const secureContext = tls.createSecureContext({ cert }); 40 | 41 | // create a tls socket with the cert/context 42 | const secureSocket = new tls.TLSSocket(new net.Socket(), { secureContext }); 43 | 44 | // deconstruct the output of the certificate from the secureSocket connection, then we typecast the output since the default typings lack... 45 | const { 46 | subject, 47 | issuer, 48 | valid_from, 49 | valid_to, 50 | serialNumber, 51 | bits 52 | } = secureSocket.getCertificate() as tlsCert; 53 | 54 | // destroy the socket to return resources 55 | secureSocket.destroy(); 56 | 57 | // return the stringified cert to strip out the object prototype tags 58 | return JSON.stringify({ 59 | subject, 60 | issuer, 61 | valid_from, 62 | valid_to, 63 | serialNumber, 64 | bits 65 | }); 66 | 67 | } 68 | 69 | 70 | const testCert = ` 71 | -----BEGIN CERTIFICATE----- 72 | MIIDkDCCAnigAwIBAgIEFPQQhjANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC 73 | VVMxDzANBgNVBAgTBnN0YXRlMTEPMA0GA1UEBxMGbG9jYWwxMQ0wCwYDVQQKEwRv 74 | cmcxMQ0wCwYDVQQLEwRkaXYxMR0wGwYDVQQDExRzZWN1cmVUZXN0LmJlbmxhYi5p 75 | bzEbMBkGCSqGSIb3DQEJARYMbm9AZW1haWwuY29tMB4XDTIxMDIyMTAxNDg1NFoX 76 | DTMxMDIxOTAxNDg1NFowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZzdGF0ZTEx 77 | DzANBgNVBAcTBmxvY2FsMTENMAsGA1UEChMEb3JnMTENMAsGA1UECxMEZGl2MTEd 78 | MBsGA1UEAxMUc2VjdXJlVGVzdC5iZW5sYWIuaW8xGzAZBgkqhkiG9w0BCQEWDG5v 79 | QGVtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBPo2RN 80 | 8hCBs9cP4CTSZXdcqZwxzPxiEM3j1Bbtr+jlLTtlV0BAcWTOzBYQCb96aTKQABOo 81 | 8jblJ01c72QVCka05Onyne9qIzeWOpAfAyl9ZK+xNSXAsZpflpzciQes8HHPGqGT 82 | WTZkDuEKSgu59Bc6kk+FJ9QjHBfkySy0IHw1tymFPJKCx2MECE3ohqzdC/B6jCMr 83 | j2fMGlBkuy2ubUKwYlyJCDuFUiTwsVc1kVVS/ZRarSwjzeZ6pO0HdOToNh23hAw5 84 | Ut9tDr1VHiv+XQ/fB3oSoE8SElLLTgxUAe87lH/noPcVMR9QC2XlBXnJPY/cmWi/ 85 | YUZIkY472V+zP58CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEATdFUp4Ey59UGpLMa 86 | Y3FnuF3BTfljZdFSFOMnKCys0yyEuMKzn5Im/x2WETlv5O0wcTOBjXeZSA28pkdG 87 | LQNqmxrLDeqcEpdFwpLXokQ44Hu9aiTt/8zLhzmg25YNQqYecsilCczFDk3rXV7H 88 | KF5vgJImE48pG9zYuwhtYBD4dwxw73wRre5toyC/S4VCfIiL7ZREr1dHduchWjCZ 89 | o1fjz76NgFDSONPdrDygPfvKTcWSuMKa9bQuLCy14m4sCGdhJxtw9IjXvFxU7d7b 90 | Gpe/MKf6tci5fKJC4PL6YSFq64THs/is4tNG1kU4YGGcGe8NAbobOyUsQPb0Nb89 91 | 9ZKM/g== 92 | -----END CERTIFICATE----- 93 | `; 94 | 95 | 96 | const z = ` 97 | { 98 | subject: [Object: null prototype] { 99 | C: 'US', 100 | ST: 'state1', 101 | L: 'local1', 102 | O: 'org1', 103 | OU: 'div1', 104 | CN: 'secureTest.benlab.io', 105 | emailAddress: 'no@email.com' 106 | }, 107 | issuer: [Object: null prototype] { 108 | C: 'US', 109 | ST: 'state1', 110 | L: 'local1', 111 | O: 'org1', 112 | OU: 'div1', 113 | CN: 'secureTest.benlab.io', 114 | emailAddress: 'no@email.com' 115 | }, 116 | modulus: 'C04FA3644DF21081B3D70FE024D265775CA99C31CCFC6210CDE3D416EDAFE8E52D3B655740407164CECC161009BF7A6932900013A8F236E5274D5CEF64150A46B4E4E9F29DEF6A2337963A901F03297D64AFB13525C0B19A5F969CDC8907ACF071CF1AA1935936640EE10A4A0BB9F4173A924F8527D4231C17E4C92CB4207C35B729853C9282C76304084DE886ACDD0BF07A8C232B8F67CC1A5064BB2DAE6D42B0625C89083B855224F0B15735915552FD945AAD2C23CDE67AA4ED0774E4E8361DB7840C3952DF6D0EBD551E2BFE5D0FDF077A12A04F121252CB4E0C5401EF3B947FE7A0F715311F500B65E50579C93D8FDC9968BF614648918E3BD95FB33F9F', 117 | bits: 2048, 118 | exponent: '0x10001', 119 | pubkey: , 120 | valid_from: 'Feb 21 01:48:54 2021 GMT', 121 | valid_to: 'Feb 19 01:48:54 2031 GMT', 122 | fingerprint: '68:88:11:04:14:EA:99:85:44:E9:E9:08:99:E5:8D:7F:4C:4B:DF:DA', 123 | fingerprint256: '2E:BE:88:73:C5:6A:9A:70:BC:39:A8:CD:DE:3F:17:59:17:4E:53:7B:0C:80:8E:8F:9C:BE:8D:81:A1:CE:A6:4D', 124 | serialNumber: '14F41086', 125 | raw: 126 | } 127 | `; -------------------------------------------------------------------------------- /tcl.tmGrammars.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/HEAD/tmlanguage.json", 3 | "fileTypes": [ 4 | "irul", 5 | "f5", 6 | "f5-tcl", 7 | "conf", 8 | "irule", 9 | "iRule", 10 | "tcl" 11 | ], 12 | "scopeName": "source.tcl", 13 | "name": "f5-tcl", 14 | "patterns": [ 15 | { 16 | "include": "#root" 17 | } 18 | ], 19 | "repository": { 20 | "root": { 21 | "patterns": [ 22 | { 23 | "include": "#comment-blocks" 24 | } 25 | ] 26 | }, 27 | "comment-blocks": { 28 | "patterns": [ 29 | { 30 | "contentName": "comment.line.number-sign.irule", 31 | "begin": "(?<=^|;|{)\\s*((#+))", 32 | "end": "(?=$|\\n)|((#))(?=\\s*(?:[}\\n]))", 33 | "captures": { 34 | "1": { 35 | "name": "comment.line.number-sign.irule" 36 | }, 37 | "2": { 38 | "name": "punctuation.definition.comment.irule" 39 | } 40 | } 41 | }, 42 | { 43 | "contentName": "comment.block.irule", 44 | "begin": "(?<=^|;|\\{)\\s*((?:\\%\\s+\\{)|(?:\\bif\\s+{?0}?\\s+{))", 45 | "end": "\\s*(\\})", 46 | "beginCaptures": { 47 | "1": { 48 | "name": "comment.block.multi.start.irule" 49 | }, 50 | "2": { 51 | "name": "punctuation.definition.comment.irule" 52 | } 53 | }, 54 | "endCaptures": { 55 | "1": { 56 | "name": "comment.block.multi.end.irule" 57 | } 58 | }, 59 | "patterns": [ 60 | { 61 | "include": "#annotate" 62 | }, 63 | { 64 | "include": "#variable-non-substituting" 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "allowJs": false, 6 | "experimentalDecorators": true, 7 | "esModuleInterop": true, 8 | "lib": [ 9 | "es6", 10 | "ES2019.Array" 11 | ], 12 | "sourceMap": true, 13 | "resolveJsonModule": true, 14 | "skipLibCheck": true, 15 | "rootDir": "src", 16 | "outDir": "out", 17 | "strict": true, /* enable all strict type-checking options */ 18 | /* Additional Checks */ 19 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 20 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 21 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 22 | // "alwaysStrict": false, 23 | // "noImplicitUseStrict": true, 24 | }, 25 | "include": [ 26 | "src/**/*" 27 | ] 28 | } --------------------------------------------------------------------------------