mirror of
https://github.com/openziti/zrok.git
synced 2025-06-24 11:41:25 +02:00
Release of v1.0.0
The first release of the 1.0.0 series.
This commit is contained in:
commit
6640c32b20
5
.flake8
5
.flake8
@ -1,6 +1,5 @@
|
||||
[flake8]
|
||||
max-line-length = 120
|
||||
exclude =
|
||||
./sdk/python/sdk/zrok/zrok_api/**,
|
||||
./build/**
|
||||
|
||||
sdk/python/src/zrok_api/*
|
||||
sdk/python/src/test/*
|
||||
|
83
.github/workflows/build-wheels.yml
vendored
83
.github/workflows/build-wheels.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: build wheels
|
||||
name: Publish Python Distributions
|
||||
|
||||
on:
|
||||
release:
|
||||
@ -23,83 +23,86 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build_wheels:
|
||||
build_distributions:
|
||||
name: Building Python Distributions
|
||||
needs: enforce_stable_semver
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: sdk/python/sdk/zrok
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
spec:
|
||||
- { name: 'linux x86_64', runner: ubuntu-20.04, target: manylinux_2_27_x86_64 }
|
||||
- { name: 'macOS x86_64', runner: macos-13, target: macosx_10_14_x86_64 }
|
||||
- { name: 'Windows x86_64', runner: windows-2019, target: win_amd64 }
|
||||
name: building ${{ matrix.spec.name }}
|
||||
runs-on: ${{ matrix.spec.runner }}
|
||||
working-directory: sdk/python/src
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Python
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: '3.13'
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install Python Tools
|
||||
run: python -m pip install -U pip setuptools
|
||||
|
||||
- name: Build distro
|
||||
- name: Build Python distributions
|
||||
env:
|
||||
ZROK_VERSION: ${{ github.event.release.tag_name }}
|
||||
ZROK_PY_NAME: ${{ vars.ZROK_PY_NAME || null }}
|
||||
shell: bash
|
||||
run: |
|
||||
python setup.py sdist
|
||||
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
# Install build requirements
|
||||
pip install --upgrade pip
|
||||
pip install -r build-requirements.txt
|
||||
|
||||
# Build source distribution and wheel
|
||||
python -m build
|
||||
|
||||
# List built distributions
|
||||
ls -lAR ./dist
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: startsWith(matrix.spec.name, 'linux')
|
||||
with:
|
||||
name: zrok_sdk_${{ matrix.spec.target }}
|
||||
path: ${{ github.workspace }}/sdk/python/sdk/zrok/dist/*
|
||||
name: zrok_sdk_distributions
|
||||
path: sdk/python/src/dist/*
|
||||
|
||||
publish-testpypi:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [ build_wheels ]
|
||||
publish_testpypi:
|
||||
name: Publish TestPyPI
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [ build_distributions ]
|
||||
permissions:
|
||||
id-token: write
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./dist
|
||||
path: sdk/python/src/dist
|
||||
merge-multiple: true
|
||||
pattern: zrok_sdk_*
|
||||
pattern: zrok_sdk_distributions
|
||||
|
||||
- name: Publish wheels (TestPYPI)
|
||||
- name: Publish Distributions to TestPyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
packages-dir: dist
|
||||
packages-dir: sdk/python/src/dist
|
||||
skip-existing: true
|
||||
verbose: true
|
||||
|
||||
publish-pypi:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [ publish-testpypi ]
|
||||
publish_pypi:
|
||||
name: Publish PyPI
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [ publish_testpypi ]
|
||||
permissions:
|
||||
id-token: write
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./dist
|
||||
path: sdk/python/src/dist
|
||||
merge-multiple: true
|
||||
pattern: zrok_sdk_*
|
||||
pattern: zrok_sdk_distributions
|
||||
|
||||
- name: Publish wheels (PyPI)
|
||||
- name: Publish Distributions to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages-dir: dist
|
||||
packages-dir: sdk/python/src/dist
|
||||
verbose: true
|
||||
|
80
.github/workflows/ci-build.yml
vendored
80
.github/workflows/ci-build.yml
vendored
@ -17,7 +17,7 @@ concurrency:
|
||||
jobs:
|
||||
ubuntu-build:
|
||||
name: Build Linux AMD64 CLI
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@ -29,20 +29,30 @@ jobs:
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 20.x
|
||||
|
||||
- name: install ui node modules
|
||||
shell: bash
|
||||
run: npm install
|
||||
working-directory: ui
|
||||
|
||||
- name: build node ui
|
||||
- name: build ui
|
||||
shell: bash
|
||||
run: npm run build
|
||||
working-directory: ui
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- name: install agent ui node modules
|
||||
shell: bash
|
||||
run: npm install
|
||||
working-directory: agent/agentUi
|
||||
|
||||
- name: build agent ui
|
||||
shell: bash
|
||||
run: npm run build
|
||||
working-directory: agent/agentUi
|
||||
|
||||
- name: go install
|
||||
shell: bash
|
||||
run: go install -ldflags "-X github.com/openziti/zrok/build.Version=${{ github.ref }} -X github.com/openziti/zrok/build.Hash=${{ github.sha }}" ./...
|
||||
@ -51,19 +61,6 @@ jobs:
|
||||
shell: bash
|
||||
run: go test -v ./...
|
||||
|
||||
- name: setup python
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: python deps
|
||||
shell: bash
|
||||
run: python -m pip install -U pip flake8
|
||||
|
||||
- name: python lint
|
||||
shell: bash
|
||||
run: flake8 sdk/python/sdk/zrok
|
||||
|
||||
- name: solve GOBIN
|
||||
id: solve_go_bin
|
||||
shell: bash
|
||||
@ -78,12 +75,61 @@ jobs:
|
||||
path: ${{ steps.solve_go_bin.outputs.go_bin }}/zrok
|
||||
if-no-files-found: error
|
||||
|
||||
pytest:
|
||||
name: Test the Python SDK
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
||||
defaults:
|
||||
run:
|
||||
working-directory: sdk/python
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r src/requirements.txt
|
||||
pip install -r src/test-requirements.txt
|
||||
pip install -r src/build-requirements.txt
|
||||
pip install -e src/
|
||||
|
||||
- name: Test with pytest
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
pytest --cov=zrok_api --verbose src/
|
||||
|
||||
- name: Lint the Python SDK
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
flake8 .
|
||||
|
||||
# build a release candidate container image for branches named "main" or like "v*"
|
||||
rc-container-build:
|
||||
needs: ubuntu-build
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/v')
|
||||
name: Build Release Candidate Container Image
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Set a container image tag from the branch name
|
||||
id: slug
|
||||
|
34
.github/workflows/node-sdk.yml
vendored
34
.github/workflows/node-sdk.yml
vendored
@ -12,8 +12,6 @@ jobs:
|
||||
name: Require Stable Release Semver
|
||||
if: github.event.action == 'released'
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
version: ${{ steps.parse.outputs.version }}
|
||||
steps:
|
||||
- name: Parse Release Version
|
||||
id: parse
|
||||
@ -32,7 +30,6 @@ jobs:
|
||||
if: always()
|
||||
name: Build for Node-${{ matrix.node_ver }} ${{ matrix.config.target }}/${{ matrix.config.arch }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
env:
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
AWS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
@ -40,7 +37,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- { os: ubuntu-20.04, target: "linux", arch: "x64" }
|
||||
- { os: ubuntu-24.04, target: "linux", arch: "x64" }
|
||||
node_ver: [ 20 ]
|
||||
fail-fast: false
|
||||
|
||||
@ -55,20 +52,22 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Get current zrok repo tag
|
||||
if: github.event.action == 'released'
|
||||
id: tag
|
||||
run: echo "TAG=$(git describe --tags --abbrev=0)" | tee -a $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
run: echo "TAG=$(git describe --tags --always)" | tee -a $GITHUB_OUTPUT
|
||||
|
||||
- name: Update zrok NodeJS-SDK's package.json version based on current zrok repo git tag
|
||||
if: github.ref_type == 'tag'
|
||||
if: github.event.action == 'released'
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${{ runner.workspace }}/${{ github.event.repository.name }}/sdk/nodejs/sdk
|
||||
cd sdk/nodejs/sdk
|
||||
npm version ${{ steps.tag.outputs.TAG }} --no-git-tag-version --allow-same-version
|
||||
|
||||
- name: Setup .npmrc
|
||||
if: github.ref_type == 'tag'
|
||||
if: github.event.action == 'released'
|
||||
# Setup .npmrc file to prepare for possible publish to npm
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@ -76,17 +75,26 @@ jobs:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Build the zrok NodeJS-SDK
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${{ runner.workspace }}/${{ github.event.repository.name }}/sdk/nodejs/sdk
|
||||
cd sdk/nodejs/sdk
|
||||
npm install
|
||||
npm run build
|
||||
env:
|
||||
BUILD_DATE: ${{ steps.date.outputs.date }}
|
||||
|
||||
- name: NPM Publish
|
||||
if: github.ref_type == 'tag'
|
||||
if: github.event.action == 'released'
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${{ runner.workspace }}/${{ github.event.repository.name }}/sdk/nodejs/sdk
|
||||
npm publish --access public
|
||||
cd sdk/nodejs/sdk
|
||||
# Check if this is the official repository
|
||||
if [[ "${{ github.repository_owner }}" == "openziti" ]]; then
|
||||
echo "Publishing from official repository with @latest tag"
|
||||
npm publish --access public
|
||||
else
|
||||
echo "Publishing from fork/test repository with @canary tag"
|
||||
npm publish --access public --tag canary
|
||||
fi
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 20.x
|
||||
|
||||
- run: npm install
|
||||
working-directory: ui
|
||||
@ -61,6 +61,14 @@ jobs:
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- run: npm install
|
||||
working-directory: agent/agentUi
|
||||
|
||||
- run: npm run build
|
||||
working-directory: agent/agentUi
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
@ -177,7 +185,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 20.x
|
||||
|
||||
- run: npm install
|
||||
working-directory: ui
|
||||
@ -187,6 +195,14 @@ jobs:
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- run: npm install
|
||||
working-directory: agent/agentUi
|
||||
|
||||
- run: npm run build
|
||||
working-directory: agent/agentUi
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
@ -222,7 +238,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 20.x
|
||||
|
||||
- run: npm install
|
||||
working-directory: ui
|
||||
@ -232,6 +248,14 @@ jobs:
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- run: npm install
|
||||
working-directory: agent/agentUi
|
||||
|
||||
- run: npm run build
|
||||
working-directory: agent/agentUi
|
||||
env:
|
||||
CI: "true"
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -16,8 +16,6 @@ node_modules/
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
sdk/python/sdk/build/
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
@ -35,3 +33,11 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
.obsidian
|
||||
|
||||
sdk/nodejs/sdk/dist
|
||||
|
||||
# py module artifacts
|
||||
/sdk/python/src/**/*.egg-info/
|
||||
/sdk/python/src/**/__pycache__/
|
||||
/.coverage
|
||||
/sdk/python/src/dist/
|
||||
|
34
CHANGELOG.md
34
CHANGELOG.md
@ -1,5 +1,37 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v1.0.0
|
||||
|
||||
MAJOR RELEASE: zrok reaches version 1.0.0!
|
||||
|
||||
FEATURE: Completely redesigned web interface ("API Console"). New implementation provides a dual-mode interface supporting an improved visual network navigator and also a "tabular" view, which provides a more traditional "data" view. New stack built using vite, React, and TypeScript (https://github.com/openziti/zrok/issues/724)
|
||||
|
||||
FEATURE: New "zrok Agent", a background manager process for your zrok environments, which allows you to easily manage and work with multiple `zrok share` and `zrok access` processes. New `--subordinate` flag added to `zrok share [public|private|reserved]` and `zrok access private` to operate in a mode that allows an Agent to manage shares and accesses (https://github.com/openziti/zrok/issues/463)
|
||||
|
||||
FEATURE: New "zrok Agent UI" a web-based user interface for the zrok Agent, which allows creating and releasing shares and accesses through a web browser. This is just an initial chunk of the new Agent UI, and is considered a "minimum viable" version of this interface (https://github.com/openziti/zrok/issues/221)
|
||||
|
||||
FEATURE: `zrok share [public|private|reserved]` and `zrok access private` now auto-detect if the zrok Agent is running in an environment and will automatically service share and access requests through the Agent, rather than in-process if the Agent is running. If the Agent is not running, operation remains as it was in `v0.4.x` and the share or access is handled in-process. New `--force-agent` and `--force-local` flags exist to skip Agent detection and manually select an operating mode (https://github.com/openziti/zrok/issues/751)
|
||||
|
||||
FEATURE: `zrok access private` supports a new `--auto` mode, which can automatically find an available open address/port to bind the frontend listener on. Also includes `--auto-address`, `--auto-start-port`, and `--auto-end-port` features with sensible defaults. Supported by both the agent and local operating modes (https://github.com/openziti/zrok/issues/780)
|
||||
|
||||
FEATURE: `zrok rebase` commands (`zrok rebase apiEndpoint` and `zrok rebase accountToken`) allows "rebasing" an enabled environment onto a different API endpoint or a different account token. This is useful for migrating already-enabled environments between endpoints supporting different zrok versions, and is also useful when regenerating an account token (https://github.com/openziti/zrok/issues/869, https://github.com/openziti/zrok/issues/897)
|
||||
|
||||
FEATURE: `zrok test canary` CLI tree replaces the old `zrok test loop` tree; new `zrok test canary public-proxy` and `zrok test canary private-proxy` provide modernized, updated versions of what the `zrok test loop` commands used to do. This new approach will serve as the foundation for all future zrok testing infrastructure (https://github.com/openziti/zrok/issues/771)
|
||||
|
||||
FEATURE: New `/api/v1/versions` endpoint to return comprehensive, full stack version information about the deployed service instance. Currently only returns a single `controllerVersion` property (https://github.com/openziti/zrok/issues/881)
|
||||
|
||||
CHANGE: The default API URL for `v1.0.x` zrok clients is now `https://api-v1.zrok.io` (instead of the older `https://api.zrok.io`). The zrok.io deployment will now be maintaining version-specific DNS for versioned API endpoints.
|
||||
|
||||
CHANGE: Refactored API implementation. Cleanup, lint removal, additional data elements added, unused data removed (https://github.com/openziti/zrok/issues/834)
|
||||
|
||||
CHANGE: Deprecated the `passwords` configuration stanza. The zrok controller and API console now use a hard-coded set of (what we believe to be) reasonable assumptions about password quality (https://github.com/openziti/zrok/issues/834)
|
||||
|
||||
CHANGE: The protocol for determining valid client versions has been changed. Previously a zrok client would do a `GET` against the `/api/v1/version` endpoint and do a local version string comparison (as a normal precondition to any API call) to see if the controller version matched. The protocol has been amended so that any out-of-date client using the old protocol will receive a version string indicating that they need to uprade their client. New clients will do a `POST` against the `/api/v1/clientVersionCheck` endpoint, posting their client version, and the server will check for compatibility. Does not change the security posture in any significant way, but gives more flexibility on the server side for managing client compatibility. Provides a better, cleared out-of-date error message for old clients when accessing `v1.0.0`+ (https://github.com/openziti/zrok/issues/859)
|
||||
|
||||
CHANGE: The Node.js SDK is now generated by `openapi-generator` using the `typescript-fetch` template. Examples and SDK components updated to use the `v1.0.0` API and generated client (https://github.com/openziti/zrok/issues/893)
|
||||
|
||||
CHANGE: The Python SDK is now generated by `openapi-generator` and requires a newer `urllib3` version 2.1.0. The published Python module, `zrok`, inherits the dependencies of the generated packages (https://github.com/openziti/zrok/issues/894)
|
||||
|
||||
## v0.4.49
|
||||
|
||||
FIX: Release artifacts now include a reproducible source archive. The archive's download URL is now used by the Homebrew formula when building from source instead of the archive generated on-demand by GitHub (https://github.com/openziti/zrok/issues/858).
|
||||
@ -35,7 +67,7 @@ CHANGE: Add usage hint in `zrok config get --help` to clarify how to list all va
|
||||
CHANGE: The Python SDK's `Overview()` function was refactored as a class method (https://github.com/openziti/zrok/pull/846).
|
||||
|
||||
FEATURE: The Python SDK now includes a `ProxyShare` class providing an HTTP proxy for public and private shares and a
|
||||
Jupyter notebook example (https://github.com/openziti/zrok/pull/847).
|
||||
Jupyter notebook example (https://github.com/openziti/zrok/pull/847).
|
||||
|
||||
FIX: PyPi publishing was failing due to a CI issue (https://github.com/openziti/zrok/issues/849)
|
||||
|
||||
|
14
README.md
14
README.md
@ -1,12 +1,12 @@
|
||||

|
||||

|
||||
|
||||
## Your Secure Internet Sharing Perimeter
|
||||
|
||||
`zrok` is a next-generation, peer-to-peer sharing platform built on top of [OpenZiti](https://docs.openziti.io/docs/learn/introduction/), a programmable zero-trust network overlay. `zrok` is a _Ziti Native Application_.
|
||||
|
||||
`zrok` facilitates sharing resources both publicly and privately. Public sharing allows you to share `zrok` resources with non-`zrok` users over the public internet. Private sharing allows you to directly share your resources peer-to-peer with other `zrok` users without changing your security or firewall settings.
|
||||
`zrok` facilitates both public and private sharing. Public sharing allows you to share securely with non-`zrok` users over the public internet. Private sharing allows you to directly share peer-to-peer with other `zrok` users. No security or firewall changes are required for either type of sharing. No inbound connectivity is required. The OpenZiti overlay provides peer-to-peer connectivity without IP addresses, and employs end-to-end encryption for world-class security.
|
||||
|
||||
Like other offerings in this space, `zrok` allows users to share tunnels for HTTP, TCP and UDP network resources. `zrok` additionally allows users to easily and rapidly share files, web content, and custom resources in a peer-to-peer manner.
|
||||
|
||||
`zrok` is an extensible platform for sharing. Initially we're targeting technical users. Super-simple sharing for end users is planned and in the backlog.
|
||||
Like other offerings in this space, `zrok` allows users to create tunnels for HTTP, TCP and UDP network resources. `zrok` additionally allows users to easily and rapidly share files, web content, and custom resources in a peer-to-peer manner.
|
||||
|
||||

|
||||
|
||||
@ -14,8 +14,8 @@ Like other offerings in this space, `zrok` allows users to share tunnels for HTT
|
||||
|
||||
You can be up and sharing using the `zrok.io` service in minutes. Here is a synopsis of what's involved:
|
||||
|
||||
* Download the binary for your platform [here](https://github.com/openziti/zrok/releases/latest)
|
||||
* `zrok invite` to create an account with the service
|
||||
* [Install the package or download the binary for your platform](https://docs.zrok.io/docs/guides/install/).
|
||||
* `zrok invite` to create an account with the service (use the [NetFoundry hosted zrok.io service](https://docs.zrok.io/docs/getting-started/))
|
||||
* `zrok enable` to enable your shell environment for sharing with the service
|
||||
|
||||
### And then... sharing...
|
||||
|
30
agent/access.go
Normal file
30
agent/access.go
Normal file
@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
)
|
||||
|
||||
type access struct {
|
||||
frontendToken string
|
||||
token string
|
||||
bindAddress string
|
||||
autoMode bool
|
||||
autoAddress string
|
||||
autoStartPort uint16
|
||||
autoEndPort uint16
|
||||
responseHeaders []string
|
||||
|
||||
process *proctree.Child
|
||||
sub *subordinate.MessageHandler
|
||||
|
||||
agent *Agent
|
||||
}
|
||||
|
||||
func (a *access) monitor() {
|
||||
if err := proctree.WaitChild(a.process); err != nil {
|
||||
pfxlog.ChannelLogger(a.token).Error(err)
|
||||
}
|
||||
a.agent.rmAccess <- a
|
||||
}
|
93
agent/accessPrivate.go
Normal file
93
agent/accessPrivate.go
Normal file
@ -0,0 +1,93 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) AccessPrivate(_ context.Context, req *agentGrpc.AccessPrivateRequest) (*agentGrpc.AccessPrivateResponse, error) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
|
||||
}
|
||||
|
||||
accCmd := []string{os.Args[0], "access", "private", "--subordinate", "-b", req.BindAddress, req.Token}
|
||||
if req.AutoMode {
|
||||
accCmd = append(accCmd, "--auto", "--auto-address", req.AutoAddress, "--auto-start-port", fmt.Sprintf("%v", req.AutoStartPort))
|
||||
accCmd = append(accCmd, "--auto-end-port", fmt.Sprintf("%v", req.AutoEndPort))
|
||||
}
|
||||
logrus.Info(accCmd)
|
||||
|
||||
acc := &access{
|
||||
token: req.Token,
|
||||
bindAddress: req.BindAddress,
|
||||
autoMode: req.AutoMode,
|
||||
autoAddress: req.AutoAddress,
|
||||
autoStartPort: uint16(req.AutoStartPort),
|
||||
autoEndPort: uint16(req.AutoEndPort),
|
||||
responseHeaders: req.ResponseHeaders,
|
||||
sub: subordinate.NewMessageHandler(),
|
||||
agent: i.agent,
|
||||
}
|
||||
acc.sub.MessageHandler = func(msg subordinate.Message) {
|
||||
logrus.Info(msg)
|
||||
}
|
||||
var bootErr error
|
||||
acc.sub.BootHandler = func(msgType string, msg subordinate.Message) {
|
||||
switch msgType {
|
||||
case subordinate.BootMessage:
|
||||
if v, found := msg["frontend_token"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
acc.frontendToken = str
|
||||
}
|
||||
}
|
||||
if v, found := msg["bind_address"]; found {
|
||||
if sr, ok := v.(string); ok {
|
||||
acc.bindAddress = sr
|
||||
}
|
||||
}
|
||||
|
||||
case subordinate.ErrorMessage:
|
||||
if v, found := msg[subordinate.ErrorMessage]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
bootErr = errors.New(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.sub.MalformedHandler = func(msg subordinate.Message) {
|
||||
logrus.Error(msg)
|
||||
}
|
||||
|
||||
logrus.Infof("executing '%v'", accCmd)
|
||||
|
||||
acc.process, err = proctree.StartChild(acc.sub.Tail, accCmd...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
<-acc.sub.BootComplete
|
||||
|
||||
if bootErr == nil {
|
||||
go acc.monitor()
|
||||
i.agent.addAccess <- acc
|
||||
return &agentGrpc.AccessPrivateResponse{FrontendToken: acc.frontendToken}, nil
|
||||
|
||||
} else {
|
||||
if err := proctree.WaitChild(acc.process); err != nil {
|
||||
logrus.Errorf("error joining: %v", err)
|
||||
}
|
||||
return nil, fmt.Errorf("unable to start access: %v", bootErr)
|
||||
}
|
||||
}
|
197
agent/agent.go
Normal file
197
agent/agent.go
Normal file
@ -0,0 +1,197 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/agentUi"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Agent struct {
|
||||
cfg *AgentConfig
|
||||
httpEndpoint string
|
||||
root env_core.Root
|
||||
agentSocket string
|
||||
shares map[string]*share
|
||||
addShare chan *share
|
||||
rmShare chan *share
|
||||
accesses map[string]*access
|
||||
addAccess chan *access
|
||||
rmAccess chan *access
|
||||
}
|
||||
|
||||
func NewAgent(cfg *AgentConfig, root env_core.Root) (*Agent, error) {
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.Errorf("unable to load environment; did you 'zrok enable'?")
|
||||
}
|
||||
return &Agent{
|
||||
cfg: cfg,
|
||||
root: root,
|
||||
shares: make(map[string]*share),
|
||||
addShare: make(chan *share),
|
||||
rmShare: make(chan *share),
|
||||
accesses: make(map[string]*access),
|
||||
addAccess: make(chan *access),
|
||||
rmAccess: make(chan *access),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *Agent) Run() error {
|
||||
logrus.Infof("started")
|
||||
|
||||
if err := proctree.Init("zrok Agent"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agentSocket, err := a.root.AgentSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l, err := net.Listen("unix", agentSocket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.agentSocket = agentSocket
|
||||
|
||||
go a.manager()
|
||||
go a.gateway(a.cfg)
|
||||
|
||||
srv := grpc.NewServer()
|
||||
agentGrpc.RegisterAgentServer(srv, &agentGrpcImpl{agent: a})
|
||||
if err := srv.Serve(l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) Shutdown() {
|
||||
logrus.Infof("stopping")
|
||||
|
||||
if err := os.Remove(a.agentSocket); err != nil {
|
||||
logrus.Warnf("unable to remove agent socket: %v", err)
|
||||
}
|
||||
for _, shr := range a.shares {
|
||||
logrus.Debugf("stopping share '%v'", shr.token)
|
||||
a.rmShare <- shr
|
||||
}
|
||||
for _, acc := range a.accesses {
|
||||
logrus.Debugf("stopping access '%v'", acc.token)
|
||||
a.rmAccess <- acc
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) Config() *AgentConfig {
|
||||
return a.cfg
|
||||
}
|
||||
|
||||
func (a *Agent) gateway(cfg *AgentConfig) {
|
||||
logrus.Info("started")
|
||||
defer logrus.Warn("exited")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
mux := runtime.NewServeMux()
|
||||
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
|
||||
endpoint := "unix:" + a.agentSocket
|
||||
logrus.Debugf("endpoint: '%v'", endpoint)
|
||||
if err := agentGrpc.RegisterAgentHandlerFromEndpoint(ctx, mux, "unix:"+a.agentSocket, opts); err != nil {
|
||||
logrus.Fatalf("unable to register gateway: %v", err)
|
||||
}
|
||||
|
||||
listener, err := util.AutoListener("tcp", cfg.ConsoleAddress, cfg.ConsoleStartPort, cfg.ConsoleEndPort)
|
||||
if err != nil {
|
||||
logrus.Fatalf("unable to create a listener: %v", err)
|
||||
}
|
||||
a.httpEndpoint = listener.Addr().String()
|
||||
|
||||
if err := http.Serve(listener, agentUi.Middleware(mux)); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) manager() {
|
||||
logrus.Info("started")
|
||||
defer logrus.Warn("exited")
|
||||
|
||||
for {
|
||||
select {
|
||||
case inShare := <-a.addShare:
|
||||
logrus.Infof("adding new share '%v'", inShare.token)
|
||||
a.shares[inShare.token] = inShare
|
||||
|
||||
case outShare := <-a.rmShare:
|
||||
if shr, found := a.shares[outShare.token]; found {
|
||||
logrus.Infof("removing share '%v'", shr.token)
|
||||
if err := proctree.StopChild(shr.process); err != nil {
|
||||
logrus.Errorf("error stopping share '%v': %v", shr.token, err)
|
||||
}
|
||||
if err := proctree.WaitChild(shr.process); err != nil {
|
||||
logrus.Errorf("error joining share '%v': %v", shr.token, err)
|
||||
}
|
||||
if !shr.reserved {
|
||||
if err := a.deleteShare(shr.token); err != nil {
|
||||
logrus.Errorf("error deleting share '%v': %v", shr.token, err)
|
||||
}
|
||||
}
|
||||
delete(a.shares, shr.token)
|
||||
} else {
|
||||
logrus.Debug("skipping unidentified (orphaned) share removal")
|
||||
}
|
||||
|
||||
case inAccess := <-a.addAccess:
|
||||
logrus.Infof("adding new access '%v'", inAccess.frontendToken)
|
||||
a.accesses[inAccess.frontendToken] = inAccess
|
||||
|
||||
case outAccess := <-a.rmAccess:
|
||||
if acc, found := a.accesses[outAccess.frontendToken]; found {
|
||||
logrus.Infof("removing access '%v'", acc.frontendToken)
|
||||
if err := proctree.StopChild(acc.process); err != nil {
|
||||
logrus.Errorf("error stopping access '%v': %v", acc.frontendToken, err)
|
||||
}
|
||||
if err := proctree.WaitChild(acc.process); err != nil {
|
||||
logrus.Errorf("error joining access '%v': %v", acc.frontendToken, err)
|
||||
}
|
||||
if err := a.deleteAccess(acc.token, acc.frontendToken); err != nil {
|
||||
logrus.Errorf("error deleting access '%v': %v", acc.frontendToken, err)
|
||||
}
|
||||
delete(a.accesses, acc.frontendToken)
|
||||
} else {
|
||||
logrus.Debug("skipping unidentified (orphaned) access removal")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) deleteShare(token string) error {
|
||||
logrus.Debugf("deleting share '%v'", token)
|
||||
if err := sdk.DeleteShare(a.root, &sdk.Share{Token: token}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) deleteAccess(token, frontendToken string) error {
|
||||
logrus.Debugf("deleting access '%v'", frontendToken)
|
||||
if err := sdk.DeleteAccess(a.root, &sdk.Access{Token: frontendToken, ShareToken: token}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type agentGrpcImpl struct {
|
||||
agentGrpc.UnimplementedAgentServer
|
||||
agent *Agent
|
||||
}
|
51
agent/agentClient/agentClient.go
Normal file
51
agent/agentClient/agentClient.go
Normal file
@ -0,0 +1,51 @@
|
||||
package agentClient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/build"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func NewClient(root env_core.Root) (client agentGrpc.AgentClient, conn *grpc.ClientConn, err error) {
|
||||
agentSocket, err := root.AgentSocket()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithContextDialer(func(_ context.Context, addr string) (net.Conn, error) {
|
||||
return net.Dial("unix", addr)
|
||||
}),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
}
|
||||
resolver.SetDefaultScheme("passthrough")
|
||||
conn, err = grpc.NewClient(agentSocket, opts...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return agentGrpc.NewAgentClient(conn), conn, nil
|
||||
}
|
||||
|
||||
func IsAgentRunning(root env_core.Root) (bool, error) {
|
||||
client, conn, err := NewClient(root)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
resp, err := client.Version(context.Background(), &agentGrpc.VersionRequest{})
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
if !strings.HasPrefix(resp.GetV(), build.Series) {
|
||||
return false, errors.Errorf("agent reported version '%v'; we expected version '%v'", resp.GetV(), build.Series)
|
||||
}
|
||||
return true, nil
|
||||
}
|
1625
agent/agentGrpc/agent.pb.go
Normal file
1625
agent/agentGrpc/agent.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
659
agent/agentGrpc/agent.pb.gw.go
Normal file
659
agent/agentGrpc/agent.pb.gw.go
Normal file
@ -0,0 +1,659 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: agent/agentGrpc/agent.proto
|
||||
|
||||
/*
|
||||
Package agentGrpc is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package agentGrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = metadata.Join
|
||||
|
||||
var (
|
||||
filter_Agent_AccessPrivate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Agent_AccessPrivate_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AccessPrivateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_AccessPrivate_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.AccessPrivate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_AccessPrivate_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AccessPrivateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_AccessPrivate_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.AccessPrivate(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Agent_ReleaseAccess_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Agent_ReleaseAccess_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ReleaseAccessRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_ReleaseAccess_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ReleaseAccess(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_ReleaseAccess_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ReleaseAccessRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_ReleaseAccess_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.ReleaseAccess(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Agent_ReleaseShare_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Agent_ReleaseShare_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ReleaseShareRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_ReleaseShare_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ReleaseShare(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_ReleaseShare_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ReleaseShareRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_ReleaseShare_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.ReleaseShare(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Agent_SharePrivate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Agent_SharePrivate_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SharePrivateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_SharePrivate_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.SharePrivate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_SharePrivate_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SharePrivateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_SharePrivate_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.SharePrivate(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Agent_SharePublic_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Agent_SharePublic_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SharePublicRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_SharePublic_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.SharePublic(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_SharePublic_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SharePublicRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Agent_SharePublic_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.SharePublic(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Agent_Status_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq StatusRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.Status(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_Status_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq StatusRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Status(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Agent_Version_0(ctx context.Context, marshaler runtime.Marshaler, client AgentClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq VersionRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.Version(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Agent_Version_0(ctx context.Context, marshaler runtime.Marshaler, server AgentServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq VersionRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Version(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterAgentHandlerServer registers the http handlers for service Agent to "mux".
|
||||
// UnaryRPC :call AgentServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAgentHandlerFromEndpoint instead.
|
||||
func RegisterAgentHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AgentServer) error {
|
||||
|
||||
mux.Handle("POST", pattern_Agent_AccessPrivate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/AccessPrivate", runtime.WithHTTPPathPattern("/v1/agent/accessPrivate"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_AccessPrivate_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_AccessPrivate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_ReleaseAccess_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/ReleaseAccess", runtime.WithHTTPPathPattern("/v1/agent/releaseAccess"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_ReleaseAccess_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_ReleaseAccess_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_ReleaseShare_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/ReleaseShare", runtime.WithHTTPPathPattern("/v1/agent/releaseShare"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_ReleaseShare_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_ReleaseShare_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_SharePrivate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/SharePrivate", runtime.WithHTTPPathPattern("/v1/agent/sharePrivate"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_SharePrivate_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_SharePrivate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_SharePublic_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/SharePublic", runtime.WithHTTPPathPattern("/v1/agent/sharePublic"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_SharePublic_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_SharePublic_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Agent_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/Status", runtime.WithHTTPPathPattern("/v1/agent/status"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_Status_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_Status_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Agent_Version_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/.Agent/Version", runtime.WithHTTPPathPattern("/v1/agent/version"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Agent_Version_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_Version_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterAgentHandlerFromEndpoint is same as RegisterAgentHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterAgentHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.DialContext(ctx, endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterAgentHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterAgentHandler registers the http handlers for service Agent to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterAgentHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterAgentHandlerClient(ctx, mux, NewAgentClient(conn))
|
||||
}
|
||||
|
||||
// RegisterAgentHandlerClient registers the http handlers for service Agent
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AgentClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AgentClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "AgentClient" to call the correct interceptors.
|
||||
func RegisterAgentHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AgentClient) error {
|
||||
|
||||
mux.Handle("POST", pattern_Agent_AccessPrivate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/AccessPrivate", runtime.WithHTTPPathPattern("/v1/agent/accessPrivate"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_AccessPrivate_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_AccessPrivate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_ReleaseAccess_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/ReleaseAccess", runtime.WithHTTPPathPattern("/v1/agent/releaseAccess"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_ReleaseAccess_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_ReleaseAccess_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_ReleaseShare_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/ReleaseShare", runtime.WithHTTPPathPattern("/v1/agent/releaseShare"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_ReleaseShare_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_ReleaseShare_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_SharePrivate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/SharePrivate", runtime.WithHTTPPathPattern("/v1/agent/sharePrivate"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_SharePrivate_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_SharePrivate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Agent_SharePublic_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/SharePublic", runtime.WithHTTPPathPattern("/v1/agent/sharePublic"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_SharePublic_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_SharePublic_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Agent_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/Status", runtime.WithHTTPPathPattern("/v1/agent/status"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_Status_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_Status_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Agent_Version_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/.Agent/Version", runtime.WithHTTPPathPattern("/v1/agent/version"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Agent_Version_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Agent_Version_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_Agent_AccessPrivate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "accessPrivate"}, ""))
|
||||
|
||||
pattern_Agent_ReleaseAccess_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "releaseAccess"}, ""))
|
||||
|
||||
pattern_Agent_ReleaseShare_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "releaseShare"}, ""))
|
||||
|
||||
pattern_Agent_SharePrivate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "sharePrivate"}, ""))
|
||||
|
||||
pattern_Agent_SharePublic_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "sharePublic"}, ""))
|
||||
|
||||
pattern_Agent_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "status"}, ""))
|
||||
|
||||
pattern_Agent_Version_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "agent", "version"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Agent_AccessPrivate_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Agent_ReleaseAccess_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Agent_ReleaseShare_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Agent_SharePrivate_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Agent_SharePublic_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Agent_Status_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Agent_Version_0 = runtime.ForwardResponseMessage
|
||||
)
|
150
agent/agentGrpc/agent.proto
Normal file
150
agent/agentGrpc/agent.proto
Normal file
@ -0,0 +1,150 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/openziti/zrok/agent/agentGrpc";
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
service Agent {
|
||||
rpc AccessPrivate(AccessPrivateRequest) returns (AccessPrivateResponse) {
|
||||
option(google.api.http) = {
|
||||
post: "/v1/agent/accessPrivate"
|
||||
};
|
||||
}
|
||||
rpc ReleaseAccess(ReleaseAccessRequest) returns (ReleaseAccessResponse) {
|
||||
option(google.api.http) = {
|
||||
post: "/v1/agent/releaseAccess"
|
||||
};
|
||||
}
|
||||
rpc ReleaseShare(ReleaseShareRequest) returns (ReleaseShareResponse) {
|
||||
option(google.api.http) = {
|
||||
post: "/v1/agent/releaseShare"
|
||||
};
|
||||
}
|
||||
rpc ShareReserved(ShareReservedRequest) returns (ShareReservedResponse) {}
|
||||
rpc SharePrivate(SharePrivateRequest) returns (SharePrivateResponse) {
|
||||
option(google.api.http) = {
|
||||
post: "/v1/agent/sharePrivate"
|
||||
};
|
||||
}
|
||||
rpc SharePublic(SharePublicRequest) returns (SharePublicResponse) {
|
||||
option(google.api.http) = {
|
||||
post: "/v1/agent/sharePublic"
|
||||
};
|
||||
}
|
||||
rpc Status(StatusRequest) returns (StatusResponse) {
|
||||
option(google.api.http) = {
|
||||
get: "/v1/agent/status"
|
||||
};
|
||||
}
|
||||
rpc Version(VersionRequest) returns (VersionResponse) {
|
||||
option(google.api.http) = {
|
||||
get: "/v1/agent/version"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
message AccessDetail {
|
||||
string frontendToken = 1;
|
||||
string token = 2;
|
||||
string bindAddress = 3;
|
||||
repeated string responseHeaders = 4;
|
||||
}
|
||||
|
||||
message AccessPrivateResponse{
|
||||
string frontendToken = 1;
|
||||
}
|
||||
|
||||
message AccessPrivateRequest{
|
||||
string token = 1;
|
||||
string bindAddress = 2;
|
||||
bool autoMode = 3;
|
||||
string autoAddress = 4;
|
||||
uint32 autoStartPort = 5;
|
||||
uint32 autoEndPort = 6;
|
||||
repeated string responseHeaders = 7;
|
||||
}
|
||||
|
||||
message ReleaseAccessRequest {
|
||||
string frontendToken = 1;
|
||||
}
|
||||
|
||||
message ReleaseAccessResponse {
|
||||
}
|
||||
|
||||
message ReleaseShareRequest {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message ReleaseShareResponse {
|
||||
}
|
||||
|
||||
message ShareDetail {
|
||||
string token = 1;
|
||||
string shareMode = 2;
|
||||
string backendMode = 3;
|
||||
bool reserved = 4;
|
||||
repeated string frontendEndpoint = 5;
|
||||
string backendEndpoint = 6;
|
||||
bool closed = 7;
|
||||
string status = 8;
|
||||
}
|
||||
|
||||
message SharePrivateRequest {
|
||||
string target = 1;
|
||||
string backendMode = 2;
|
||||
bool insecure = 3;
|
||||
bool closed = 4;
|
||||
repeated string accessGrants = 5;
|
||||
}
|
||||
|
||||
message SharePrivateResponse {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message SharePublicRequest {
|
||||
string target = 1;
|
||||
repeated string basicAuth = 2;
|
||||
repeated string frontendSelection = 3;
|
||||
string backendMode = 4;
|
||||
bool insecure = 5;
|
||||
string oauthProvider = 6;
|
||||
repeated string oauthEmailAddressPatterns = 7;
|
||||
string oauthCheckInterval = 8;
|
||||
bool closed = 9;
|
||||
repeated string accessGrants = 10;
|
||||
}
|
||||
|
||||
message SharePublicResponse {
|
||||
string token = 1;
|
||||
repeated string frontendEndpoints = 2;
|
||||
}
|
||||
|
||||
message ShareReservedRequest {
|
||||
string token = 1;
|
||||
string overrideEndpoint = 2;
|
||||
bool insecure = 3;
|
||||
}
|
||||
|
||||
message ShareReservedResponse {
|
||||
string token = 1;
|
||||
string backendMode = 2;
|
||||
string shareMode = 3;
|
||||
repeated string frontendEndpoints = 4;
|
||||
string target = 5;
|
||||
}
|
||||
|
||||
message StatusRequest {
|
||||
}
|
||||
|
||||
message StatusResponse {
|
||||
repeated AccessDetail accesses = 1;
|
||||
repeated ShareDetail shares = 2;
|
||||
}
|
||||
|
||||
message VersionRequest {
|
||||
}
|
||||
|
||||
message VersionResponse {
|
||||
string v = 1;
|
||||
string consoleEndpoint = 2;
|
||||
}
|
525
agent/agentGrpc/agent.swagger.json
Normal file
525
agent/agentGrpc/agent.swagger.json
Normal file
@ -0,0 +1,525 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "agent/agentGrpc/agent.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "Agent"
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {
|
||||
"/v1/agent/accessPrivate": {
|
||||
"post": {
|
||||
"operationId": "Agent_AccessPrivate",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AccessPrivateResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "token",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "bindAddress",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "autoMode",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "autoAddress",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "autoStartPort",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
{
|
||||
"name": "autoEndPort",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
{
|
||||
"name": "responseHeaders",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/agent/releaseAccess": {
|
||||
"post": {
|
||||
"operationId": "Agent_ReleaseAccess",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ReleaseAccessResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "frontendToken",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/agent/releaseShare": {
|
||||
"post": {
|
||||
"operationId": "Agent_ReleaseShare",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ReleaseShareResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "token",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/agent/sharePrivate": {
|
||||
"post": {
|
||||
"operationId": "Agent_SharePrivate",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/SharePrivateResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "target",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "backendMode",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "insecure",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "closed",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "accessGrants",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/agent/sharePublic": {
|
||||
"post": {
|
||||
"operationId": "Agent_SharePublic",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/SharePublicResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "target",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "basicAuth",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
},
|
||||
{
|
||||
"name": "frontendSelection",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
},
|
||||
{
|
||||
"name": "backendMode",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "insecure",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "oauthProvider",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "oauthEmailAddressPatterns",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
},
|
||||
{
|
||||
"name": "oauthCheckInterval",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "closed",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "accessGrants",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/agent/status": {
|
||||
"get": {
|
||||
"operationId": "Agent_Status",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/StatusResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/agent/version": {
|
||||
"get": {
|
||||
"operationId": "Agent_Version",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/VersionResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Agent"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"AccessDetail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"frontendToken": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
"bindAddress": {
|
||||
"type": "string"
|
||||
},
|
||||
"responseHeaders": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AccessPrivateResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"frontendToken": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReleaseAccessResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"ReleaseShareResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"ShareDetail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareMode": {
|
||||
"type": "string"
|
||||
},
|
||||
"backendMode": {
|
||||
"type": "string"
|
||||
},
|
||||
"reserved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"frontendEndpoint": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"backendEndpoint": {
|
||||
"type": "string"
|
||||
},
|
||||
"closed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharePrivateResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharePublicResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
"frontendEndpoints": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ShareReservedResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
"backendMode": {
|
||||
"type": "string"
|
||||
},
|
||||
"shareMode": {
|
||||
"type": "string"
|
||||
},
|
||||
"frontendEndpoints": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StatusResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"accesses": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/AccessDetail"
|
||||
}
|
||||
},
|
||||
"shares": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/ShareDetail"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"VersionResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "string"
|
||||
},
|
||||
"consoleEndpoint": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protobufAny": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"@type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"rpcStatus": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"details": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/protobufAny"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
387
agent/agentGrpc/agent_grpc.pb.go
Normal file
387
agent/agentGrpc/agent_grpc.pb.go
Normal file
@ -0,0 +1,387 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.27.3
|
||||
// source: agent/agentGrpc/agent.proto
|
||||
|
||||
package agentGrpc
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Agent_AccessPrivate_FullMethodName = "/Agent/AccessPrivate"
|
||||
Agent_ReleaseAccess_FullMethodName = "/Agent/ReleaseAccess"
|
||||
Agent_ReleaseShare_FullMethodName = "/Agent/ReleaseShare"
|
||||
Agent_ShareReserved_FullMethodName = "/Agent/ShareReserved"
|
||||
Agent_SharePrivate_FullMethodName = "/Agent/SharePrivate"
|
||||
Agent_SharePublic_FullMethodName = "/Agent/SharePublic"
|
||||
Agent_Status_FullMethodName = "/Agent/Status"
|
||||
Agent_Version_FullMethodName = "/Agent/Version"
|
||||
)
|
||||
|
||||
// AgentClient is the client API for Agent service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type AgentClient interface {
|
||||
AccessPrivate(ctx context.Context, in *AccessPrivateRequest, opts ...grpc.CallOption) (*AccessPrivateResponse, error)
|
||||
ReleaseAccess(ctx context.Context, in *ReleaseAccessRequest, opts ...grpc.CallOption) (*ReleaseAccessResponse, error)
|
||||
ReleaseShare(ctx context.Context, in *ReleaseShareRequest, opts ...grpc.CallOption) (*ReleaseShareResponse, error)
|
||||
ShareReserved(ctx context.Context, in *ShareReservedRequest, opts ...grpc.CallOption) (*ShareReservedResponse, error)
|
||||
SharePrivate(ctx context.Context, in *SharePrivateRequest, opts ...grpc.CallOption) (*SharePrivateResponse, error)
|
||||
SharePublic(ctx context.Context, in *SharePublicRequest, opts ...grpc.CallOption) (*SharePublicResponse, error)
|
||||
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
|
||||
Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error)
|
||||
}
|
||||
|
||||
type agentClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewAgentClient(cc grpc.ClientConnInterface) AgentClient {
|
||||
return &agentClient{cc}
|
||||
}
|
||||
|
||||
func (c *agentClient) AccessPrivate(ctx context.Context, in *AccessPrivateRequest, opts ...grpc.CallOption) (*AccessPrivateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AccessPrivateResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_AccessPrivate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) ReleaseAccess(ctx context.Context, in *ReleaseAccessRequest, opts ...grpc.CallOption) (*ReleaseAccessResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ReleaseAccessResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_ReleaseAccess_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) ReleaseShare(ctx context.Context, in *ReleaseShareRequest, opts ...grpc.CallOption) (*ReleaseShareResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ReleaseShareResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_ReleaseShare_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) ShareReserved(ctx context.Context, in *ShareReservedRequest, opts ...grpc.CallOption) (*ShareReservedResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ShareReservedResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_ShareReserved_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) SharePrivate(ctx context.Context, in *SharePrivateRequest, opts ...grpc.CallOption) (*SharePrivateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SharePrivateResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_SharePrivate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) SharePublic(ctx context.Context, in *SharePublicRequest, opts ...grpc.CallOption) (*SharePublicResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SharePublicResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_SharePublic_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StatusResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_Status_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *agentClient) Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(VersionResponse)
|
||||
err := c.cc.Invoke(ctx, Agent_Version_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AgentServer is the server API for Agent service.
|
||||
// All implementations must embed UnimplementedAgentServer
|
||||
// for forward compatibility.
|
||||
type AgentServer interface {
|
||||
AccessPrivate(context.Context, *AccessPrivateRequest) (*AccessPrivateResponse, error)
|
||||
ReleaseAccess(context.Context, *ReleaseAccessRequest) (*ReleaseAccessResponse, error)
|
||||
ReleaseShare(context.Context, *ReleaseShareRequest) (*ReleaseShareResponse, error)
|
||||
ShareReserved(context.Context, *ShareReservedRequest) (*ShareReservedResponse, error)
|
||||
SharePrivate(context.Context, *SharePrivateRequest) (*SharePrivateResponse, error)
|
||||
SharePublic(context.Context, *SharePublicRequest) (*SharePublicResponse, error)
|
||||
Status(context.Context, *StatusRequest) (*StatusResponse, error)
|
||||
Version(context.Context, *VersionRequest) (*VersionResponse, error)
|
||||
mustEmbedUnimplementedAgentServer()
|
||||
}
|
||||
|
||||
// UnimplementedAgentServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedAgentServer struct{}
|
||||
|
||||
func (UnimplementedAgentServer) AccessPrivate(context.Context, *AccessPrivateRequest) (*AccessPrivateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AccessPrivate not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) ReleaseAccess(context.Context, *ReleaseAccessRequest) (*ReleaseAccessResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReleaseAccess not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) ReleaseShare(context.Context, *ReleaseShareRequest) (*ReleaseShareResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReleaseShare not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) ShareReserved(context.Context, *ShareReservedRequest) (*ShareReservedResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ShareReserved not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) SharePrivate(context.Context, *SharePrivateRequest) (*SharePrivateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SharePrivate not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) SharePublic(context.Context, *SharePublicRequest) (*SharePublicResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SharePublic not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) Version(context.Context, *VersionRequest) (*VersionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Version not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServer) mustEmbedUnimplementedAgentServer() {}
|
||||
func (UnimplementedAgentServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeAgentServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to AgentServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeAgentServer interface {
|
||||
mustEmbedUnimplementedAgentServer()
|
||||
}
|
||||
|
||||
func RegisterAgentServer(s grpc.ServiceRegistrar, srv AgentServer) {
|
||||
// If the following call pancis, it indicates UnimplementedAgentServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Agent_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Agent_AccessPrivate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AccessPrivateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).AccessPrivate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_AccessPrivate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).AccessPrivate(ctx, req.(*AccessPrivateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_ReleaseAccess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReleaseAccessRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).ReleaseAccess(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_ReleaseAccess_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).ReleaseAccess(ctx, req.(*ReleaseAccessRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_ReleaseShare_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReleaseShareRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).ReleaseShare(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_ReleaseShare_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).ReleaseShare(ctx, req.(*ReleaseShareRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_ShareReserved_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ShareReservedRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).ShareReserved(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_ShareReserved_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).ShareReserved(ctx, req.(*ShareReservedRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_SharePrivate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SharePrivateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).SharePrivate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_SharePrivate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).SharePrivate(ctx, req.(*SharePrivateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_SharePublic_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SharePublicRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).SharePublic(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_SharePublic_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).SharePublic(ctx, req.(*SharePublicRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(StatusRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).Status(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_Status_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).Status(ctx, req.(*StatusRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Agent_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(VersionRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServer).Version(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Agent_Version_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServer).Version(ctx, req.(*VersionRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Agent_ServiceDesc is the grpc.ServiceDesc for Agent service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Agent_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Agent",
|
||||
HandlerType: (*AgentServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "AccessPrivate",
|
||||
Handler: _Agent_AccessPrivate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ReleaseAccess",
|
||||
Handler: _Agent_ReleaseAccess_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ReleaseShare",
|
||||
Handler: _Agent_ReleaseShare_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ShareReserved",
|
||||
Handler: _Agent_ShareReserved_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SharePrivate",
|
||||
Handler: _Agent_SharePrivate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SharePublic",
|
||||
Handler: _Agent_SharePublic_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Status",
|
||||
Handler: _Agent_Status_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Version",
|
||||
Handler: _Agent_Version_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "agent/agentGrpc/agent.proto",
|
||||
}
|
10
agent/agentGrpc/tools.go
Normal file
10
agent/agentGrpc/tools.go
Normal file
@ -0,0 +1,10 @@
|
||||
//go:build tools
|
||||
|
||||
package agentGrpc
|
||||
|
||||
import (
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
|
||||
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
|
||||
_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
|
||||
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
|
||||
)
|
24
agent/agentUi/.gitignore
vendored
Normal file
24
agent/agentUi/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
50
agent/agentUi/README.md
Normal file
50
agent/agentUi/README.md
Normal file
@ -0,0 +1,50 @@
|
||||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
|
||||
```js
|
||||
export default tseslint.config({
|
||||
languageOptions: {
|
||||
// other options...
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
|
||||
- Optionally add `...tseslint.configs.stylisticTypeChecked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import react from 'eslint-plugin-react'
|
||||
|
||||
export default tseslint.config({
|
||||
// Set the react version
|
||||
settings: { react: { version: '18.3' } },
|
||||
plugins: {
|
||||
// Add the react plugin
|
||||
react,
|
||||
},
|
||||
rules: {
|
||||
// other rules...
|
||||
// Enable its recommended rules
|
||||
...react.configs.recommended.rules,
|
||||
...react.configs['jsx-runtime'].rules,
|
||||
},
|
||||
})
|
||||
```
|
6
agent/agentUi/embed.go
Normal file
6
agent/agentUi/embed.go
Normal file
@ -0,0 +1,6 @@
|
||||
package agentUi
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed dist
|
||||
var FS embed.FS
|
28
agent/agentUi/eslint.config.js
Normal file
28
agent/agentUi/eslint.config.js
Normal file
@ -0,0 +1,28 @@
|
||||
import js from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import tseslint from 'typescript-eslint'
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ['dist'] },
|
||||
{
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
},
|
||||
plugins: {
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
17
agent/agentUi/index.html
Normal file
17
agent/agentUi/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/zrok.png" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap" rel="stylesheet">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>zrok Agent Console</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
53
agent/agentUi/middleware.go
Normal file
53
agent/agentUi/middleware.go
Normal file
@ -0,0 +1,53 @@
|
||||
package agentUi
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const staticPath = "dist"
|
||||
|
||||
func Middleware(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/v1") {
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
path := filepath.ToSlash(filepath.Join(staticPath, r.URL.Path))
|
||||
logrus.Debugf("path = %v", path)
|
||||
|
||||
f, err := FS.Open(path)
|
||||
if os.IsNotExist(err) {
|
||||
// file does not exist, serve index.gohtml
|
||||
index, err := FS.ReadFile(filepath.ToSlash(filepath.Join(staticPath, "index.html")))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
_, _ = w.Write(index)
|
||||
return
|
||||
|
||||
} else if err != nil {
|
||||
// if we got an error (that wasn't that the file doesn't exist) stating the
|
||||
// file, return a 500 internal server error and stop
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
// get the subdirectory of the static dir
|
||||
if statics, err := fs.Sub(FS, staticPath); err == nil {
|
||||
// otherwise, use http.FileServer to serve the static dir
|
||||
http.FileServer(http.FS(statics)).ServeHTTP(w, r)
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
}
|
4009
agent/agentUi/package-lock.json
generated
Normal file
4009
agent/agentUi/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
33
agent/agentUi/package.json
Normal file
33
agent/agentUi/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "agentui",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@mui/icons-material": "^6.1.7",
|
||||
"@mui/material": "^6.1.7",
|
||||
"formik": "^2.4.6",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.13.0",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.3",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.14",
|
||||
"globals": "^15.11.0",
|
||||
"typescript-eslint": "^8.15.0",
|
||||
"vite": "^6.2.0"
|
||||
}
|
||||
}
|
BIN
agent/agentUi/public/zrok.png
Normal file
BIN
agent/agentUi/public/zrok.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
53
agent/agentUi/src/AccessCard.tsx
Normal file
53
agent/agentUi/src/AccessCard.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import {AgentObject} from "./model/overview.ts";
|
||||
import {AppBar, Box, Button, Card, Chip, Grid2, Toolbar, Typography} from "@mui/material";
|
||||
import LanIcon from "@mui/icons-material/Lan";
|
||||
import {AccessDetail} from "./api";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import {GetAgentApi} from "./model/api.ts";
|
||||
|
||||
interface AccessCardProps {
|
||||
accessObject: AgentObject;
|
||||
}
|
||||
|
||||
const AccessCard = ({ accessObject }: AccessCardProps) => {
|
||||
let access = (accessObject.v as AccessDetail);
|
||||
|
||||
const releaseAccess = () => {
|
||||
GetAgentApi().agentReleaseAccess({frontendToken: access.frontendToken})
|
||||
.catch(e => {
|
||||
console.log("error releasing access", e);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<AppBar position="sticky">
|
||||
<Toolbar variant="dense">
|
||||
<LanIcon />
|
||||
<Grid2 container sx={{ flexGrow: 1 }}>
|
||||
<Grid2 display="flex" justifyContent="center" size="grow">
|
||||
<Typography variant="h6" component="div" style={{ color: "#9bf316" }}>{access.frontendToken}</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
<Grid2 container>
|
||||
<Grid2 display="flex" justifyContent="right">
|
||||
<Chip label="private" size="small" style={{ backgroundColor: "#9bf316" }} />
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box sx={{ p: 2, textAlign: "center" }}>
|
||||
<Typography variant="h6" component="div">
|
||||
{access.token} → {access.bindAddress}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Grid2 container sx={{ flexGrow: 1 }}>
|
||||
<Grid2 display="flex" justifyContent="right" size="grow">
|
||||
<Button variant="contained" onClick={releaseAccess}><DeleteIcon /></Button>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default AccessCard;
|
69
agent/agentUi/src/AgentUi.tsx
Normal file
69
agent/agentUi/src/AgentUi.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {GetAgentApi} from "./model/api.ts";
|
||||
import NavBar from "./NavBar.tsx";
|
||||
import {AgentObject, buildOverview} from "./model/overview.ts";
|
||||
import Overview from "./Overview.tsx";
|
||||
import NewShareModal from "./NewShareModal.tsx";
|
||||
import NewAccessModal from "./NewAccessModal.tsx";
|
||||
|
||||
const AgentUi = () => {
|
||||
const [version, setVersion] = useState("unset");
|
||||
const [overview, setOverview] = useState(new Array<AgentObject>());
|
||||
const [newShareOpen, setNewShareOpen] = useState(false);
|
||||
const [newAccessOpen, setNewAccessOpen] = useState(false);
|
||||
|
||||
const openNewShare = () => {
|
||||
setNewShareOpen(true);
|
||||
}
|
||||
const closeNewShare = () => {
|
||||
setNewShareOpen(false);
|
||||
}
|
||||
|
||||
const openNewAccess = () => {
|
||||
setNewAccessOpen(true);
|
||||
}
|
||||
const closeNewAccess = () => {
|
||||
setNewAccessOpen(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
GetAgentApi().agentVersion()
|
||||
.then(r => {
|
||||
if(r.v) {
|
||||
setVersion(r.v);
|
||||
} else {
|
||||
console.log("unexpected", r);
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let interval = setInterval(() => {
|
||||
GetAgentApi().agentStatus()
|
||||
.then(r => {
|
||||
setOverview(buildOverview(r));
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
})
|
||||
}, 1000);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
setOverview(new Array<AgentObject>());
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<NavBar shareClick={openNewShare} accessClick={openNewAccess} />
|
||||
<Overview overview={overview} shareClick={openNewShare} accessClick={openNewAccess} />
|
||||
<NewShareModal isOpen={newShareOpen} close={closeNewShare} />
|
||||
<NewAccessModal isOpen={newAccessOpen} close={closeNewAccess} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AgentUi;
|
40
agent/agentUi/src/NavBar.tsx
Normal file
40
agent/agentUi/src/NavBar.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import {AppBar, Box, Button, Grid2, Toolbar, Typography} from "@mui/material";
|
||||
import LanIcon from "@mui/icons-material/Lan";
|
||||
import ShareIcon from "@mui/icons-material/Share";
|
||||
import zrokLogo from "./assets/zrok-1.0.0-rocket-green.svg";
|
||||
|
||||
interface NavBarProps {
|
||||
shareClick: () => void;
|
||||
accessClick: () => void;
|
||||
}
|
||||
|
||||
const NavBar = ({ shareClick, accessClick }: NavBarProps) => {
|
||||
return (
|
||||
<Box ssx={{ flexGrow: 1 }}>
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<Typography variant="h6" sx={{ flexGrow: 1 }}>
|
||||
<Grid2 container sx={{ flexGrow: 1 }}>
|
||||
<Grid2 display="flex" justifyContent="left">
|
||||
<img src={zrokLogo} height="30" />
|
||||
</Grid2>
|
||||
<Grid2 display="flex" justifyContent="left" size="grow" sx={{ ml: 3 }} color="#9bf316">
|
||||
<strong>z r o k Agent</strong>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Typography>
|
||||
<Grid2 container sx={{ flexGrow: 1 }}>
|
||||
<Grid2 display="flex" justifyContent="right" size="grow">
|
||||
<Button color="inherit" onClick={shareClick}><ShareIcon /></Button>
|
||||
</Grid2>
|
||||
<Grid2 display="flex" justifyContent="right">
|
||||
<Button color="inherit" onClick={accessClick}><LanIcon /></Button>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default NavBar
|
69
agent/agentUi/src/NewAccessModal.tsx
Normal file
69
agent/agentUi/src/NewAccessModal.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import {useState} from "react";
|
||||
import {useFormik} from "formik";
|
||||
import {GetAgentApi} from "./model/api.ts";
|
||||
import {Box, Button, Modal, TextField, Typography} from "@mui/material";
|
||||
import {modalStyle} from "./model/theme.ts";
|
||||
import * as React from "react";
|
||||
|
||||
interface NewAccessModalProps {
|
||||
close: () => void;
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
const NewAccessModal = ({ close, isOpen }: NewAccessModalProps) => {
|
||||
const [errorMessage, setErrorMessage] = useState(null as React.JSX.Element);
|
||||
|
||||
const newAccessForm = useFormik({
|
||||
initialValues: {
|
||||
token: "",
|
||||
bindAddress: "",
|
||||
},
|
||||
onSubmit: v => {
|
||||
setErrorMessage(null as React.JSX.Element);
|
||||
GetAgentApi().agentAccessPrivate(v)
|
||||
.then(r => {
|
||||
close();
|
||||
})
|
||||
.catch(e => {
|
||||
e.response.json().then(ex => {
|
||||
setErrorMessage(<span>{ex.message}</span>);
|
||||
console.log(ex.message);
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal open={isOpen} onClose={close}>
|
||||
<Box sx={{...modalStyle}}>
|
||||
<Typography><h2>Access...</h2></Typography>
|
||||
<Typography color="red"><h3>{errorMessage}</h3></Typography>
|
||||
<form onSubmit={newAccessForm.handleSubmit}>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="token"
|
||||
name="token"
|
||||
label="Share Token"
|
||||
value={newAccessForm.values.token}
|
||||
onChange={newAccessForm.handleChange}
|
||||
onBlur={newAccessForm.handleBlur}
|
||||
sx={{mt: 2}}
|
||||
/>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="bindAddress"
|
||||
name="bindAddress"
|
||||
label="Bind Address"
|
||||
value={newAccessForm.values.bindAddress}
|
||||
onChange={newAccessForm.handleChange}
|
||||
onBlur={newAccessForm.handleBlur}
|
||||
sx={{mt: 2}}
|
||||
/>
|
||||
<Button color="primary" variant="contained" type="submit" sx={{mt: 2}}>Create Access</Button>
|
||||
</form>
|
||||
</Box>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default NewAccessModal;
|
146
agent/agentUi/src/NewShareModal.tsx
Normal file
146
agent/agentUi/src/NewShareModal.tsx
Normal file
@ -0,0 +1,146 @@
|
||||
import {useFormik} from "formik";
|
||||
import {GetAgentApi} from "./model/api.ts";
|
||||
import {useState} from "react";
|
||||
import {Box, Button, Checkbox, FormControlLabel, MenuItem, Modal, TextField, Typography} from "@mui/material";
|
||||
import {modalStyle} from "./model/theme.ts";
|
||||
import * as React from "react";
|
||||
|
||||
interface NewShareModalProps {
|
||||
close: () => void;
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
const NewShareModal = ({ close, isOpen }: NewShareModalProps) => {
|
||||
const [errorMessage, setErrorMessage] = useState(null as React.JSX.Element);
|
||||
|
||||
const form = useFormik({
|
||||
initialValues: {
|
||||
shareMode: "public",
|
||||
backendMode: "proxy",
|
||||
target: "",
|
||||
insecure: false,
|
||||
},
|
||||
onSubmit: v => {
|
||||
setErrorMessage(null as React.JSX.Element);
|
||||
switch(v.shareMode) {
|
||||
case "public":
|
||||
GetAgentApi().agentSharePublic(v)
|
||||
.then(r => {
|
||||
close();
|
||||
})
|
||||
.catch(e => {
|
||||
e.response.json().then(ex => {
|
||||
setErrorMessage(<span>{ex.message}</span>);
|
||||
console.log(ex.message);
|
||||
})
|
||||
});
|
||||
break;
|
||||
|
||||
case "private":
|
||||
GetAgentApi().agentSharePrivate(v)
|
||||
.then(r => {
|
||||
close();
|
||||
})
|
||||
.catch(e => {
|
||||
e.response().json().then(ex => {
|
||||
setErrorMessage(<span>{ex.message}</span>);
|
||||
console.log(ex.message);
|
||||
})
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal open={isOpen} onClose={close}>
|
||||
<Box sx={{ ...modalStyle }}>
|
||||
<Typography><h2>Share...</h2></Typography>
|
||||
<Typography color="red"><h3>{errorMessage}</h3></Typography>
|
||||
<form onSubmit={form.handleSubmit}>
|
||||
<TextField
|
||||
fullWidth
|
||||
select
|
||||
id="shareMode"
|
||||
name="shareMode"
|
||||
label="Share Mode"
|
||||
value={form.values.shareMode}
|
||||
onChange={form.handleChange}
|
||||
onBlur={form.handleBlur}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
<MenuItem value="public">public</MenuItem>
|
||||
<MenuItem value="private">private</MenuItem>
|
||||
</TextField>
|
||||
{form.values.shareMode === "public" && (
|
||||
<TextField
|
||||
fullWidth select
|
||||
id="backendMode"
|
||||
name="backendMode"
|
||||
label="Backend Mode"
|
||||
value={form.values.backendMode}
|
||||
onChange={form.handleChange}
|
||||
onBlur={form.handleBlur}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
<MenuItem value="proxy">proxy</MenuItem>
|
||||
<MenuItem value="web">web</MenuItem>
|
||||
<MenuItem value="caddy">caddy</MenuItem>
|
||||
<MenuItem value="drive">drive</MenuItem>
|
||||
</TextField>
|
||||
)}
|
||||
{form.values.shareMode === "private" && (
|
||||
<TextField
|
||||
fullWidth select
|
||||
id="backendMode"
|
||||
name="backendMode"
|
||||
label="Backend Mode"
|
||||
value={form.values.backendMode}
|
||||
onChange={form.handleChange}
|
||||
onBlur={form.handleBlur}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
<MenuItem value="proxy">proxy</MenuItem>
|
||||
<MenuItem value="web">web</MenuItem>
|
||||
<MenuItem value="tcpTunnel">tcpTunnel</MenuItem>
|
||||
<MenuItem value="udpTunnel">udpTunnel</MenuItem>
|
||||
<MenuItem value="caddy">caddy</MenuItem>
|
||||
<MenuItem value="drive">drive</MenuItem>
|
||||
<MenuItem value="socks">socks</MenuItem>
|
||||
<MenuItem value="vpn">vpn</MenuItem>
|
||||
</TextField>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
id="target"
|
||||
name="target"
|
||||
label="Target"
|
||||
value={form.values.target}
|
||||
onChange={form.handleChange}
|
||||
onBlur={form.handleBlur}
|
||||
sx={{ mt: 2 }}
|
||||
/>
|
||||
{form.values.backendMode === "proxy" && (
|
||||
<Box>
|
||||
<FormControlLabel
|
||||
control={<Checkbox
|
||||
id="insecure"
|
||||
name="insecure"
|
||||
label="Insecure"
|
||||
checked={form.values.insecure}
|
||||
onChange={form.handleChange}
|
||||
onBlur={form.handleBlur}
|
||||
/>}
|
||||
label="Insecure"
|
||||
sx={{ mt: 2 }}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<Button color="primary" variant="contained" type="submit" sx={{ mt: 2 }}>Create Share</Button>
|
||||
</form>
|
||||
</Box>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default NewShareModal;
|
47
agent/agentUi/src/Overview.tsx
Normal file
47
agent/agentUi/src/Overview.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import {AgentObject} from "./model/overview.ts";
|
||||
import {Box, Card, Grid2, Typography} from "@mui/material";
|
||||
import ShareIcon from "@mui/icons-material/Share";
|
||||
import LanIcon from "@mui/icons-material/Lan";
|
||||
import ShareCard from "./ShareCard.tsx";
|
||||
import AccessCard from "./AccessCard.tsx";
|
||||
|
||||
interface OverviewProps {
|
||||
overview: Array<AgentObject>;
|
||||
shareClick: () => void;
|
||||
accessClick: () => void;
|
||||
}
|
||||
|
||||
const Overview = ({ overview, shareClick, accessClick }: OverviewProps) => {
|
||||
let cards = [];
|
||||
if(overview.length > 0) {
|
||||
overview.forEach(row => {
|
||||
switch(row.type) {
|
||||
case "access":
|
||||
cards.push(<Grid2 size={{ xs: 12, md: 6 }}><AccessCard accessObject={row} /></Grid2>);
|
||||
break;
|
||||
|
||||
case "share":
|
||||
cards.push(<Grid2 size={{ xs: 12, md: 6 }}><ShareCard shareObject={row} /></Grid2>);
|
||||
break;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cards.push(<Grid2 size={{ xs: 12 }}>
|
||||
<Card key="empty">
|
||||
<Box sx={{ p: 2, textAlign: "center" }}>
|
||||
<Typography variant="h6" component="div">
|
||||
zrok Agent is empty! Add a <a href={"#"} onClick={shareClick}>share <ShareIcon/></a> or <a
|
||||
href={"#"} onClick={accessClick}>access <LanIcon/></a> share to get started.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Card>
|
||||
</Grid2>);
|
||||
}
|
||||
return (
|
||||
<Grid2 container spacing={2}>
|
||||
{cards}
|
||||
</Grid2>
|
||||
);
|
||||
}
|
||||
|
||||
export default Overview;
|
59
agent/agentUi/src/ShareCard.tsx
Normal file
59
agent/agentUi/src/ShareCard.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import * as React from "react";
|
||||
import {AgentObject} from "./model/overview.ts";
|
||||
import {ShareDetail} from "./api";
|
||||
import {AppBar, Box, Button, Card, Chip, Grid2, Toolbar, Typography} from "@mui/material";
|
||||
import ShareIcon from "@mui/icons-material/Share";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import {GetAgentApi} from "./model/api.ts";
|
||||
|
||||
interface ShareCardProps {
|
||||
shareObject: AgentObject;
|
||||
}
|
||||
|
||||
const ShareCard = ({ shareObject }: ShareCardProps) => {
|
||||
let frontends = new Array<React.JSX.Element>();
|
||||
let share = (shareObject.v as ShareDetail);
|
||||
share.frontendEndpoint!.map(fe => {
|
||||
frontends.push(<a key={share.token} href={fe} target="_">{fe}</a>);
|
||||
});
|
||||
|
||||
const releaseShare = () => {
|
||||
GetAgentApi().agentReleaseShare({token: share.token})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<AppBar position="sticky">
|
||||
<Toolbar variant="dense">
|
||||
<ShareIcon />
|
||||
<Grid2 container sx={{ flexGrow: 1 }}>
|
||||
<Grid2 display="flex" justifyContent="center" size="grow">
|
||||
<Typography variant="h6" component="div" style={{ color: "#9bf316" }}>{share.token}</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
<Grid2 container>
|
||||
<Grid2 display="flex" justifyContent="right">
|
||||
<Chip label={share.shareMode} size="small" style={{ backgroundColor: "#9bf316" }} sx={{ mr: 1}} />
|
||||
<Chip label={share.backendMode} size="small" style={{ backgroundColor: "#9bf316" }} />
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box sx={{ p: 2, textAlign: "center" }}>
|
||||
<Typography variant="h6" component="div">
|
||||
{share.backendEndpoint} → {frontends} <br/>
|
||||
</Typography>
|
||||
</Box>
|
||||
<Grid2 container sx={{ flexGrow: 1 }}>
|
||||
<Grid2 display="flex" justifyContent="right" size="grow">
|
||||
<Button variant="contained" onClick={releaseShare}><DeleteIcon /></Button>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default ShareCard;
|
@ -21,4 +21,3 @@
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
||||
git_push.sh
|
16
agent/agentUi/src/api/.openapi-generator/FILES
Normal file
16
agent/agentUi/src/api/.openapi-generator/FILES
Normal file
@ -0,0 +1,16 @@
|
||||
.openapi-generator-ignore
|
||||
apis/AgentApi.ts
|
||||
apis/index.ts
|
||||
index.ts
|
||||
models/AccessDetail.ts
|
||||
models/AccessPrivateResponse.ts
|
||||
models/ProtobufAny.ts
|
||||
models/RpcStatus.ts
|
||||
models/ShareDetail.ts
|
||||
models/SharePrivateResponse.ts
|
||||
models/SharePublicResponse.ts
|
||||
models/ShareReservedResponse.ts
|
||||
models/StatusResponse.ts
|
||||
models/VersionResponse.ts
|
||||
models/index.ts
|
||||
runtime.ts
|
1
agent/agentUi/src/api/.openapi-generator/VERSION
Normal file
1
agent/agentUi/src/api/.openapi-generator/VERSION
Normal file
@ -0,0 +1 @@
|
||||
7.12.0
|
348
agent/agentUi/src/api/apis/AgentApi.ts
Normal file
348
agent/agentUi/src/api/apis/AgentApi.ts
Normal file
@ -0,0 +1,348 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
AccessPrivateResponse,
|
||||
RpcStatus,
|
||||
SharePrivateResponse,
|
||||
SharePublicResponse,
|
||||
StatusResponse,
|
||||
VersionResponse,
|
||||
} from '../models/index';
|
||||
import {
|
||||
AccessPrivateResponseFromJSON,
|
||||
AccessPrivateResponseToJSON,
|
||||
RpcStatusFromJSON,
|
||||
RpcStatusToJSON,
|
||||
SharePrivateResponseFromJSON,
|
||||
SharePrivateResponseToJSON,
|
||||
SharePublicResponseFromJSON,
|
||||
SharePublicResponseToJSON,
|
||||
StatusResponseFromJSON,
|
||||
StatusResponseToJSON,
|
||||
VersionResponseFromJSON,
|
||||
VersionResponseToJSON,
|
||||
} from '../models/index';
|
||||
|
||||
export interface AgentAccessPrivateRequest {
|
||||
token?: string;
|
||||
bindAddress?: string;
|
||||
autoMode?: boolean;
|
||||
autoAddress?: string;
|
||||
autoStartPort?: number;
|
||||
autoEndPort?: number;
|
||||
responseHeaders?: Array<string>;
|
||||
}
|
||||
|
||||
export interface AgentReleaseAccessRequest {
|
||||
frontendToken?: string;
|
||||
}
|
||||
|
||||
export interface AgentReleaseShareRequest {
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface AgentSharePrivateRequest {
|
||||
target?: string;
|
||||
backendMode?: string;
|
||||
insecure?: boolean;
|
||||
closed?: boolean;
|
||||
accessGrants?: Array<string>;
|
||||
}
|
||||
|
||||
export interface AgentSharePublicRequest {
|
||||
target?: string;
|
||||
basicAuth?: Array<string>;
|
||||
frontendSelection?: Array<string>;
|
||||
backendMode?: string;
|
||||
insecure?: boolean;
|
||||
oauthProvider?: string;
|
||||
oauthEmailAddressPatterns?: Array<string>;
|
||||
oauthCheckInterval?: string;
|
||||
closed?: boolean;
|
||||
accessGrants?: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export class AgentApi extends runtime.BaseAPI {
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentAccessPrivateRaw(requestParameters: AgentAccessPrivateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AccessPrivateResponse>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['token'] != null) {
|
||||
queryParameters['token'] = requestParameters['token'];
|
||||
}
|
||||
|
||||
if (requestParameters['bindAddress'] != null) {
|
||||
queryParameters['bindAddress'] = requestParameters['bindAddress'];
|
||||
}
|
||||
|
||||
if (requestParameters['autoMode'] != null) {
|
||||
queryParameters['autoMode'] = requestParameters['autoMode'];
|
||||
}
|
||||
|
||||
if (requestParameters['autoAddress'] != null) {
|
||||
queryParameters['autoAddress'] = requestParameters['autoAddress'];
|
||||
}
|
||||
|
||||
if (requestParameters['autoStartPort'] != null) {
|
||||
queryParameters['autoStartPort'] = requestParameters['autoStartPort'];
|
||||
}
|
||||
|
||||
if (requestParameters['autoEndPort'] != null) {
|
||||
queryParameters['autoEndPort'] = requestParameters['autoEndPort'];
|
||||
}
|
||||
|
||||
if (requestParameters['responseHeaders'] != null) {
|
||||
queryParameters['responseHeaders'] = requestParameters['responseHeaders'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/accessPrivate`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => AccessPrivateResponseFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentAccessPrivate(requestParameters: AgentAccessPrivateRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AccessPrivateResponse> {
|
||||
const response = await this.agentAccessPrivateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentReleaseAccessRaw(requestParameters: AgentReleaseAccessRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<object>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['frontendToken'] != null) {
|
||||
queryParameters['frontendToken'] = requestParameters['frontendToken'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/releaseAccess`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse<any>(response);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentReleaseAccess(requestParameters: AgentReleaseAccessRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<object> {
|
||||
const response = await this.agentReleaseAccessRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentReleaseShareRaw(requestParameters: AgentReleaseShareRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<object>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['token'] != null) {
|
||||
queryParameters['token'] = requestParameters['token'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/releaseShare`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse<any>(response);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentReleaseShare(requestParameters: AgentReleaseShareRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<object> {
|
||||
const response = await this.agentReleaseShareRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentSharePrivateRaw(requestParameters: AgentSharePrivateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SharePrivateResponse>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['target'] != null) {
|
||||
queryParameters['target'] = requestParameters['target'];
|
||||
}
|
||||
|
||||
if (requestParameters['backendMode'] != null) {
|
||||
queryParameters['backendMode'] = requestParameters['backendMode'];
|
||||
}
|
||||
|
||||
if (requestParameters['insecure'] != null) {
|
||||
queryParameters['insecure'] = requestParameters['insecure'];
|
||||
}
|
||||
|
||||
if (requestParameters['closed'] != null) {
|
||||
queryParameters['closed'] = requestParameters['closed'];
|
||||
}
|
||||
|
||||
if (requestParameters['accessGrants'] != null) {
|
||||
queryParameters['accessGrants'] = requestParameters['accessGrants'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/sharePrivate`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => SharePrivateResponseFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentSharePrivate(requestParameters: AgentSharePrivateRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SharePrivateResponse> {
|
||||
const response = await this.agentSharePrivateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentSharePublicRaw(requestParameters: AgentSharePublicRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SharePublicResponse>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['target'] != null) {
|
||||
queryParameters['target'] = requestParameters['target'];
|
||||
}
|
||||
|
||||
if (requestParameters['basicAuth'] != null) {
|
||||
queryParameters['basicAuth'] = requestParameters['basicAuth'];
|
||||
}
|
||||
|
||||
if (requestParameters['frontendSelection'] != null) {
|
||||
queryParameters['frontendSelection'] = requestParameters['frontendSelection'];
|
||||
}
|
||||
|
||||
if (requestParameters['backendMode'] != null) {
|
||||
queryParameters['backendMode'] = requestParameters['backendMode'];
|
||||
}
|
||||
|
||||
if (requestParameters['insecure'] != null) {
|
||||
queryParameters['insecure'] = requestParameters['insecure'];
|
||||
}
|
||||
|
||||
if (requestParameters['oauthProvider'] != null) {
|
||||
queryParameters['oauthProvider'] = requestParameters['oauthProvider'];
|
||||
}
|
||||
|
||||
if (requestParameters['oauthEmailAddressPatterns'] != null) {
|
||||
queryParameters['oauthEmailAddressPatterns'] = requestParameters['oauthEmailAddressPatterns'];
|
||||
}
|
||||
|
||||
if (requestParameters['oauthCheckInterval'] != null) {
|
||||
queryParameters['oauthCheckInterval'] = requestParameters['oauthCheckInterval'];
|
||||
}
|
||||
|
||||
if (requestParameters['closed'] != null) {
|
||||
queryParameters['closed'] = requestParameters['closed'];
|
||||
}
|
||||
|
||||
if (requestParameters['accessGrants'] != null) {
|
||||
queryParameters['accessGrants'] = requestParameters['accessGrants'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/sharePublic`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => SharePublicResponseFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentSharePublic(requestParameters: AgentSharePublicRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SharePublicResponse> {
|
||||
const response = await this.agentSharePublicRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentStatusRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<StatusResponse>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/status`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => StatusResponseFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentStatus(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<StatusResponse> {
|
||||
const response = await this.agentStatusRaw(initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentVersionRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<VersionResponse>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
const response = await this.request({
|
||||
path: `/v1/agent/version`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => VersionResponseFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
async agentVersion(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<VersionResponse> {
|
||||
const response = await this.agentVersionRaw(initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
}
|
3
agent/agentUi/src/api/apis/index.ts
Normal file
3
agent/agentUi/src/api/apis/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './AgentApi';
|
89
agent/agentUi/src/api/models/AccessDetail.ts
Normal file
89
agent/agentUi/src/api/models/AccessDetail.ts
Normal file
@ -0,0 +1,89 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface AccessDetail
|
||||
*/
|
||||
export interface AccessDetail {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AccessDetail
|
||||
*/
|
||||
frontendToken?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AccessDetail
|
||||
*/
|
||||
token?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AccessDetail
|
||||
*/
|
||||
bindAddress?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof AccessDetail
|
||||
*/
|
||||
responseHeaders?: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the AccessDetail interface.
|
||||
*/
|
||||
export function instanceOfAccessDetail(value: object): value is AccessDetail {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AccessDetailFromJSON(json: any): AccessDetail {
|
||||
return AccessDetailFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AccessDetailFromJSONTyped(json: any, ignoreDiscriminator: boolean): AccessDetail {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'frontendToken': json['frontendToken'] == null ? undefined : json['frontendToken'],
|
||||
'token': json['token'] == null ? undefined : json['token'],
|
||||
'bindAddress': json['bindAddress'] == null ? undefined : json['bindAddress'],
|
||||
'responseHeaders': json['responseHeaders'] == null ? undefined : json['responseHeaders'],
|
||||
};
|
||||
}
|
||||
|
||||
export function AccessDetailToJSON(json: any): AccessDetail {
|
||||
return AccessDetailToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AccessDetailToJSONTyped(value?: AccessDetail | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'frontendToken': value['frontendToken'],
|
||||
'token': value['token'],
|
||||
'bindAddress': value['bindAddress'],
|
||||
'responseHeaders': value['responseHeaders'],
|
||||
};
|
||||
}
|
||||
|
65
agent/agentUi/src/api/models/AccessPrivateResponse.ts
Normal file
65
agent/agentUi/src/api/models/AccessPrivateResponse.ts
Normal file
@ -0,0 +1,65 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface AccessPrivateResponse
|
||||
*/
|
||||
export interface AccessPrivateResponse {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AccessPrivateResponse
|
||||
*/
|
||||
frontendToken?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the AccessPrivateResponse interface.
|
||||
*/
|
||||
export function instanceOfAccessPrivateResponse(value: object): value is AccessPrivateResponse {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AccessPrivateResponseFromJSON(json: any): AccessPrivateResponse {
|
||||
return AccessPrivateResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AccessPrivateResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AccessPrivateResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'frontendToken': json['frontendToken'] == null ? undefined : json['frontendToken'],
|
||||
};
|
||||
}
|
||||
|
||||
export function AccessPrivateResponseToJSON(json: any): AccessPrivateResponse {
|
||||
return AccessPrivateResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AccessPrivateResponseToJSONTyped(value?: AccessPrivateResponse | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'frontendToken': value['frontendToken'],
|
||||
};
|
||||
}
|
||||
|
68
agent/agentUi/src/api/models/ProtobufAny.ts
Normal file
68
agent/agentUi/src/api/models/ProtobufAny.ts
Normal file
@ -0,0 +1,68 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ProtobufAny
|
||||
*/
|
||||
export interface ProtobufAny {
|
||||
[key: string]: object | any;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ProtobufAny
|
||||
*/
|
||||
type?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ProtobufAny interface.
|
||||
*/
|
||||
export function instanceOfProtobufAny(value: object): value is ProtobufAny {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ProtobufAnyFromJSON(json: any): ProtobufAny {
|
||||
return ProtobufAnyFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ProtobufAnyFromJSONTyped(json: any, ignoreDiscriminator: boolean): ProtobufAny {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
...json,
|
||||
'type': json['@type'] == null ? undefined : json['@type'],
|
||||
};
|
||||
}
|
||||
|
||||
export function ProtobufAnyToJSON(json: any): ProtobufAny {
|
||||
return ProtobufAnyToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ProtobufAnyToJSONTyped(value?: ProtobufAny | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
...value,
|
||||
'@type': value['type'],
|
||||
};
|
||||
}
|
||||
|
89
agent/agentUi/src/api/models/RpcStatus.ts
Normal file
89
agent/agentUi/src/api/models/RpcStatus.ts
Normal file
@ -0,0 +1,89 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { ProtobufAny } from './ProtobufAny';
|
||||
import {
|
||||
ProtobufAnyFromJSON,
|
||||
ProtobufAnyFromJSONTyped,
|
||||
ProtobufAnyToJSON,
|
||||
ProtobufAnyToJSONTyped,
|
||||
} from './ProtobufAny';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface RpcStatus
|
||||
*/
|
||||
export interface RpcStatus {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof RpcStatus
|
||||
*/
|
||||
code?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof RpcStatus
|
||||
*/
|
||||
message?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<ProtobufAny>}
|
||||
* @memberof RpcStatus
|
||||
*/
|
||||
details?: Array<ProtobufAny>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the RpcStatus interface.
|
||||
*/
|
||||
export function instanceOfRpcStatus(value: object): value is RpcStatus {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function RpcStatusFromJSON(json: any): RpcStatus {
|
||||
return RpcStatusFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function RpcStatusFromJSONTyped(json: any, ignoreDiscriminator: boolean): RpcStatus {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'code': json['code'] == null ? undefined : json['code'],
|
||||
'message': json['message'] == null ? undefined : json['message'],
|
||||
'details': json['details'] == null ? undefined : ((json['details'] as Array<any>).map(ProtobufAnyFromJSON)),
|
||||
};
|
||||
}
|
||||
|
||||
export function RpcStatusToJSON(json: any): RpcStatus {
|
||||
return RpcStatusToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function RpcStatusToJSONTyped(value?: RpcStatus | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'code': value['code'],
|
||||
'message': value['message'],
|
||||
'details': value['details'] == null ? undefined : ((value['details'] as Array<any>).map(ProtobufAnyToJSON)),
|
||||
};
|
||||
}
|
||||
|
121
agent/agentUi/src/api/models/ShareDetail.ts
Normal file
121
agent/agentUi/src/api/models/ShareDetail.ts
Normal file
@ -0,0 +1,121 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ShareDetail
|
||||
*/
|
||||
export interface ShareDetail {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
token?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
shareMode?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
backendMode?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
reserved?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
frontendEndpoint?: Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
backendEndpoint?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
closed?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareDetail
|
||||
*/
|
||||
status?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ShareDetail interface.
|
||||
*/
|
||||
export function instanceOfShareDetail(value: object): value is ShareDetail {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ShareDetailFromJSON(json: any): ShareDetail {
|
||||
return ShareDetailFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ShareDetailFromJSONTyped(json: any, ignoreDiscriminator: boolean): ShareDetail {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'token': json['token'] == null ? undefined : json['token'],
|
||||
'shareMode': json['shareMode'] == null ? undefined : json['shareMode'],
|
||||
'backendMode': json['backendMode'] == null ? undefined : json['backendMode'],
|
||||
'reserved': json['reserved'] == null ? undefined : json['reserved'],
|
||||
'frontendEndpoint': json['frontendEndpoint'] == null ? undefined : json['frontendEndpoint'],
|
||||
'backendEndpoint': json['backendEndpoint'] == null ? undefined : json['backendEndpoint'],
|
||||
'closed': json['closed'] == null ? undefined : json['closed'],
|
||||
'status': json['status'] == null ? undefined : json['status'],
|
||||
};
|
||||
}
|
||||
|
||||
export function ShareDetailToJSON(json: any): ShareDetail {
|
||||
return ShareDetailToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ShareDetailToJSONTyped(value?: ShareDetail | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'token': value['token'],
|
||||
'shareMode': value['shareMode'],
|
||||
'backendMode': value['backendMode'],
|
||||
'reserved': value['reserved'],
|
||||
'frontendEndpoint': value['frontendEndpoint'],
|
||||
'backendEndpoint': value['backendEndpoint'],
|
||||
'closed': value['closed'],
|
||||
'status': value['status'],
|
||||
};
|
||||
}
|
||||
|
65
agent/agentUi/src/api/models/SharePrivateResponse.ts
Normal file
65
agent/agentUi/src/api/models/SharePrivateResponse.ts
Normal file
@ -0,0 +1,65 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface SharePrivateResponse
|
||||
*/
|
||||
export interface SharePrivateResponse {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SharePrivateResponse
|
||||
*/
|
||||
token?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the SharePrivateResponse interface.
|
||||
*/
|
||||
export function instanceOfSharePrivateResponse(value: object): value is SharePrivateResponse {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function SharePrivateResponseFromJSON(json: any): SharePrivateResponse {
|
||||
return SharePrivateResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function SharePrivateResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): SharePrivateResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'token': json['token'] == null ? undefined : json['token'],
|
||||
};
|
||||
}
|
||||
|
||||
export function SharePrivateResponseToJSON(json: any): SharePrivateResponse {
|
||||
return SharePrivateResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function SharePrivateResponseToJSONTyped(value?: SharePrivateResponse | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'token': value['token'],
|
||||
};
|
||||
}
|
||||
|
73
agent/agentUi/src/api/models/SharePublicResponse.ts
Normal file
73
agent/agentUi/src/api/models/SharePublicResponse.ts
Normal file
@ -0,0 +1,73 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface SharePublicResponse
|
||||
*/
|
||||
export interface SharePublicResponse {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SharePublicResponse
|
||||
*/
|
||||
token?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof SharePublicResponse
|
||||
*/
|
||||
frontendEndpoints?: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the SharePublicResponse interface.
|
||||
*/
|
||||
export function instanceOfSharePublicResponse(value: object): value is SharePublicResponse {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function SharePublicResponseFromJSON(json: any): SharePublicResponse {
|
||||
return SharePublicResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function SharePublicResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): SharePublicResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'token': json['token'] == null ? undefined : json['token'],
|
||||
'frontendEndpoints': json['frontendEndpoints'] == null ? undefined : json['frontendEndpoints'],
|
||||
};
|
||||
}
|
||||
|
||||
export function SharePublicResponseToJSON(json: any): SharePublicResponse {
|
||||
return SharePublicResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function SharePublicResponseToJSONTyped(value?: SharePublicResponse | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'token': value['token'],
|
||||
'frontendEndpoints': value['frontendEndpoints'],
|
||||
};
|
||||
}
|
||||
|
97
agent/agentUi/src/api/models/ShareReservedResponse.ts
Normal file
97
agent/agentUi/src/api/models/ShareReservedResponse.ts
Normal file
@ -0,0 +1,97 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ShareReservedResponse
|
||||
*/
|
||||
export interface ShareReservedResponse {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareReservedResponse
|
||||
*/
|
||||
token?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareReservedResponse
|
||||
*/
|
||||
backendMode?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareReservedResponse
|
||||
*/
|
||||
shareMode?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof ShareReservedResponse
|
||||
*/
|
||||
frontendEndpoints?: Array<string>;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ShareReservedResponse
|
||||
*/
|
||||
target?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the ShareReservedResponse interface.
|
||||
*/
|
||||
export function instanceOfShareReservedResponse(value: object): value is ShareReservedResponse {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function ShareReservedResponseFromJSON(json: any): ShareReservedResponse {
|
||||
return ShareReservedResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ShareReservedResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ShareReservedResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'token': json['token'] == null ? undefined : json['token'],
|
||||
'backendMode': json['backendMode'] == null ? undefined : json['backendMode'],
|
||||
'shareMode': json['shareMode'] == null ? undefined : json['shareMode'],
|
||||
'frontendEndpoints': json['frontendEndpoints'] == null ? undefined : json['frontendEndpoints'],
|
||||
'target': json['target'] == null ? undefined : json['target'],
|
||||
};
|
||||
}
|
||||
|
||||
export function ShareReservedResponseToJSON(json: any): ShareReservedResponse {
|
||||
return ShareReservedResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function ShareReservedResponseToJSONTyped(value?: ShareReservedResponse | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'token': value['token'],
|
||||
'backendMode': value['backendMode'],
|
||||
'shareMode': value['shareMode'],
|
||||
'frontendEndpoints': value['frontendEndpoints'],
|
||||
'target': value['target'],
|
||||
};
|
||||
}
|
||||
|
88
agent/agentUi/src/api/models/StatusResponse.ts
Normal file
88
agent/agentUi/src/api/models/StatusResponse.ts
Normal file
@ -0,0 +1,88 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AccessDetail } from './AccessDetail';
|
||||
import {
|
||||
AccessDetailFromJSON,
|
||||
AccessDetailFromJSONTyped,
|
||||
AccessDetailToJSON,
|
||||
AccessDetailToJSONTyped,
|
||||
} from './AccessDetail';
|
||||
import type { ShareDetail } from './ShareDetail';
|
||||
import {
|
||||
ShareDetailFromJSON,
|
||||
ShareDetailFromJSONTyped,
|
||||
ShareDetailToJSON,
|
||||
ShareDetailToJSONTyped,
|
||||
} from './ShareDetail';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface StatusResponse
|
||||
*/
|
||||
export interface StatusResponse {
|
||||
/**
|
||||
*
|
||||
* @type {Array<AccessDetail>}
|
||||
* @memberof StatusResponse
|
||||
*/
|
||||
accesses?: Array<AccessDetail>;
|
||||
/**
|
||||
*
|
||||
* @type {Array<ShareDetail>}
|
||||
* @memberof StatusResponse
|
||||
*/
|
||||
shares?: Array<ShareDetail>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the StatusResponse interface.
|
||||
*/
|
||||
export function instanceOfStatusResponse(value: object): value is StatusResponse {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function StatusResponseFromJSON(json: any): StatusResponse {
|
||||
return StatusResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function StatusResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): StatusResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'accesses': json['accesses'] == null ? undefined : ((json['accesses'] as Array<any>).map(AccessDetailFromJSON)),
|
||||
'shares': json['shares'] == null ? undefined : ((json['shares'] as Array<any>).map(ShareDetailFromJSON)),
|
||||
};
|
||||
}
|
||||
|
||||
export function StatusResponseToJSON(json: any): StatusResponse {
|
||||
return StatusResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function StatusResponseToJSONTyped(value?: StatusResponse | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'accesses': value['accesses'] == null ? undefined : ((value['accesses'] as Array<any>).map(AccessDetailToJSON)),
|
||||
'shares': value['shares'] == null ? undefined : ((value['shares'] as Array<any>).map(ShareDetailToJSON)),
|
||||
};
|
||||
}
|
||||
|
73
agent/agentUi/src/api/models/VersionResponse.ts
Normal file
73
agent/agentUi/src/api/models/VersionResponse.ts
Normal file
@ -0,0 +1,73 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface VersionResponse
|
||||
*/
|
||||
export interface VersionResponse {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof VersionResponse
|
||||
*/
|
||||
v?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof VersionResponse
|
||||
*/
|
||||
consoleEndpoint?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the VersionResponse interface.
|
||||
*/
|
||||
export function instanceOfVersionResponse(value: object): value is VersionResponse {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function VersionResponseFromJSON(json: any): VersionResponse {
|
||||
return VersionResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function VersionResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): VersionResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'v': json['v'] == null ? undefined : json['v'],
|
||||
'consoleEndpoint': json['consoleEndpoint'] == null ? undefined : json['consoleEndpoint'],
|
||||
};
|
||||
}
|
||||
|
||||
export function VersionResponseToJSON(json: any): VersionResponse {
|
||||
return VersionResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function VersionResponseToJSONTyped(value?: VersionResponse | null, ignoreDiscriminator: boolean = false): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
'v': value['v'],
|
||||
'consoleEndpoint': value['consoleEndpoint'],
|
||||
};
|
||||
}
|
||||
|
12
agent/agentUi/src/api/models/index.ts
Normal file
12
agent/agentUi/src/api/models/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './AccessDetail';
|
||||
export * from './AccessPrivateResponse';
|
||||
export * from './ProtobufAny';
|
||||
export * from './RpcStatus';
|
||||
export * from './ShareDetail';
|
||||
export * from './SharePrivateResponse';
|
||||
export * from './SharePublicResponse';
|
||||
export * from './ShareReservedResponse';
|
||||
export * from './StatusResponse';
|
||||
export * from './VersionResponse';
|
431
agent/agentUi/src/api/runtime.ts
Normal file
431
agent/agentUi/src/api/runtime.ts
Normal file
@ -0,0 +1,431 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* agent/agentGrpc/agent.proto
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: version not set
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export const BASE_PATH = "http://localhost".replace(/\/+$/, "");
|
||||
|
||||
export interface ConfigurationParameters {
|
||||
basePath?: string; // override base path
|
||||
fetchApi?: FetchAPI; // override for fetch implementation
|
||||
middleware?: Middleware[]; // middleware to apply before/after fetch requests
|
||||
queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings
|
||||
username?: string; // parameter for basic security
|
||||
password?: string; // parameter for basic security
|
||||
apiKey?: string | Promise<string> | ((name: string) => string | Promise<string>); // parameter for apiKey security
|
||||
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string | Promise<string>); // parameter for oauth2 security
|
||||
headers?: HTTPHeaders; //header params we want to use on every request
|
||||
credentials?: RequestCredentials; //value for the credentials param we want to use on each request
|
||||
}
|
||||
|
||||
export class Configuration {
|
||||
constructor(private configuration: ConfigurationParameters = {}) {}
|
||||
|
||||
set config(configuration: Configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
get basePath(): string {
|
||||
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
||||
}
|
||||
|
||||
get fetchApi(): FetchAPI | undefined {
|
||||
return this.configuration.fetchApi;
|
||||
}
|
||||
|
||||
get middleware(): Middleware[] {
|
||||
return this.configuration.middleware || [];
|
||||
}
|
||||
|
||||
get queryParamsStringify(): (params: HTTPQuery) => string {
|
||||
return this.configuration.queryParamsStringify || querystring;
|
||||
}
|
||||
|
||||
get username(): string | undefined {
|
||||
return this.configuration.username;
|
||||
}
|
||||
|
||||
get password(): string | undefined {
|
||||
return this.configuration.password;
|
||||
}
|
||||
|
||||
get apiKey(): ((name: string) => string | Promise<string>) | undefined {
|
||||
const apiKey = this.configuration.apiKey;
|
||||
if (apiKey) {
|
||||
return typeof apiKey === 'function' ? apiKey : () => apiKey;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get accessToken(): ((name?: string, scopes?: string[]) => string | Promise<string>) | undefined {
|
||||
const accessToken = this.configuration.accessToken;
|
||||
if (accessToken) {
|
||||
return typeof accessToken === 'function' ? accessToken : async () => accessToken;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get headers(): HTTPHeaders | undefined {
|
||||
return this.configuration.headers;
|
||||
}
|
||||
|
||||
get credentials(): RequestCredentials | undefined {
|
||||
return this.configuration.credentials;
|
||||
}
|
||||
}
|
||||
|
||||
export const DefaultConfig = new Configuration();
|
||||
|
||||
/**
|
||||
* This is the base class for all generated API classes.
|
||||
*/
|
||||
export class BaseAPI {
|
||||
|
||||
private static readonly jsonRegex = new RegExp('^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$', 'i');
|
||||
private middleware: Middleware[];
|
||||
|
||||
constructor(protected configuration = DefaultConfig) {
|
||||
this.middleware = configuration.middleware;
|
||||
}
|
||||
|
||||
withMiddleware<T extends BaseAPI>(this: T, ...middlewares: Middleware[]) {
|
||||
const next = this.clone<T>();
|
||||
next.middleware = next.middleware.concat(...middlewares);
|
||||
return next;
|
||||
}
|
||||
|
||||
withPreMiddleware<T extends BaseAPI>(this: T, ...preMiddlewares: Array<Middleware['pre']>) {
|
||||
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
||||
return this.withMiddleware<T>(...middlewares);
|
||||
}
|
||||
|
||||
withPostMiddleware<T extends BaseAPI>(this: T, ...postMiddlewares: Array<Middleware['post']>) {
|
||||
const middlewares = postMiddlewares.map((post) => ({ post }));
|
||||
return this.withMiddleware<T>(...middlewares);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given MIME is a JSON MIME.
|
||||
* JSON MIME examples:
|
||||
* application/json
|
||||
* application/json; charset=UTF8
|
||||
* APPLICATION/JSON
|
||||
* application/vnd.company+json
|
||||
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
||||
* @return True if the given MIME is JSON, false otherwise.
|
||||
*/
|
||||
protected isJsonMime(mime: string | null | undefined): boolean {
|
||||
if (!mime) {
|
||||
return false;
|
||||
}
|
||||
return BaseAPI.jsonRegex.test(mime);
|
||||
}
|
||||
|
||||
protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise<Response> {
|
||||
const { url, init } = await this.createFetchParams(context, initOverrides);
|
||||
const response = await this.fetchApi(url, init);
|
||||
if (response && (response.status >= 200 && response.status < 300)) {
|
||||
return response;
|
||||
}
|
||||
throw new ResponseError(response, 'Response returned an error code');
|
||||
}
|
||||
|
||||
private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) {
|
||||
let url = this.configuration.basePath + context.path;
|
||||
if (context.query !== undefined && Object.keys(context.query).length !== 0) {
|
||||
// only add the querystring to the URL if there are query parameters.
|
||||
// this is done to avoid urls ending with a "?" character which buggy webservers
|
||||
// do not handle correctly sometimes.
|
||||
url += '?' + this.configuration.queryParamsStringify(context.query);
|
||||
}
|
||||
|
||||
const headers = Object.assign({}, this.configuration.headers, context.headers);
|
||||
Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {});
|
||||
|
||||
const initOverrideFn =
|
||||
typeof initOverrides === "function"
|
||||
? initOverrides
|
||||
: async () => initOverrides;
|
||||
|
||||
const initParams = {
|
||||
method: context.method,
|
||||
headers,
|
||||
body: context.body,
|
||||
credentials: this.configuration.credentials,
|
||||
};
|
||||
|
||||
const overriddenInit: RequestInit = {
|
||||
...initParams,
|
||||
...(await initOverrideFn({
|
||||
init: initParams,
|
||||
context,
|
||||
}))
|
||||
};
|
||||
|
||||
let body: any;
|
||||
if (isFormData(overriddenInit.body)
|
||||
|| (overriddenInit.body instanceof URLSearchParams)
|
||||
|| isBlob(overriddenInit.body)) {
|
||||
body = overriddenInit.body;
|
||||
} else if (this.isJsonMime(headers['Content-Type'])) {
|
||||
body = JSON.stringify(overriddenInit.body);
|
||||
} else {
|
||||
body = overriddenInit.body;
|
||||
}
|
||||
|
||||
const init: RequestInit = {
|
||||
...overriddenInit,
|
||||
body
|
||||
};
|
||||
|
||||
return { url, init };
|
||||
}
|
||||
|
||||
private fetchApi = async (url: string, init: RequestInit) => {
|
||||
let fetchParams = { url, init };
|
||||
for (const middleware of this.middleware) {
|
||||
if (middleware.pre) {
|
||||
fetchParams = await middleware.pre({
|
||||
fetch: this.fetchApi,
|
||||
...fetchParams,
|
||||
}) || fetchParams;
|
||||
}
|
||||
}
|
||||
let response: Response | undefined = undefined;
|
||||
try {
|
||||
response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init);
|
||||
} catch (e) {
|
||||
for (const middleware of this.middleware) {
|
||||
if (middleware.onError) {
|
||||
response = await middleware.onError({
|
||||
fetch: this.fetchApi,
|
||||
url: fetchParams.url,
|
||||
init: fetchParams.init,
|
||||
error: e,
|
||||
response: response ? response.clone() : undefined,
|
||||
}) || response;
|
||||
}
|
||||
}
|
||||
if (response === undefined) {
|
||||
if (e instanceof Error) {
|
||||
throw new FetchError(e, 'The request failed and the interceptors did not return an alternative response');
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const middleware of this.middleware) {
|
||||
if (middleware.post) {
|
||||
response = await middleware.post({
|
||||
fetch: this.fetchApi,
|
||||
url: fetchParams.url,
|
||||
init: fetchParams.init,
|
||||
response: response.clone(),
|
||||
}) || response;
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shallow clone of `this` by constructing a new instance
|
||||
* and then shallow cloning data members.
|
||||
*/
|
||||
private clone<T extends BaseAPI>(this: T): T {
|
||||
const constructor = this.constructor as any;
|
||||
const next = new constructor(this.configuration);
|
||||
next.middleware = this.middleware.slice();
|
||||
return next;
|
||||
}
|
||||
};
|
||||
|
||||
function isBlob(value: any): value is Blob {
|
||||
return typeof Blob !== 'undefined' && value instanceof Blob;
|
||||
}
|
||||
|
||||
function isFormData(value: any): value is FormData {
|
||||
return typeof FormData !== "undefined" && value instanceof FormData;
|
||||
}
|
||||
|
||||
export class ResponseError extends Error {
|
||||
override name: "ResponseError" = "ResponseError";
|
||||
constructor(public response: Response, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export class FetchError extends Error {
|
||||
override name: "FetchError" = "FetchError";
|
||||
constructor(public cause: Error, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export class RequiredError extends Error {
|
||||
override name: "RequiredError" = "RequiredError";
|
||||
constructor(public field: string, msg?: string) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export const COLLECTION_FORMATS = {
|
||||
csv: ",",
|
||||
ssv: " ",
|
||||
tsv: "\t",
|
||||
pipes: "|",
|
||||
};
|
||||
|
||||
export type FetchAPI = WindowOrWorkerGlobalScope['fetch'];
|
||||
|
||||
export type Json = any;
|
||||
export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
|
||||
export type HTTPHeaders = { [key: string]: string };
|
||||
export type HTTPQuery = { [key: string]: string | number | null | boolean | Array<string | number | null | boolean> | Set<string | number | null | boolean> | HTTPQuery };
|
||||
export type HTTPBody = Json | FormData | URLSearchParams;
|
||||
export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody };
|
||||
export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original';
|
||||
|
||||
export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise<RequestInit>
|
||||
|
||||
export interface FetchParams {
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
}
|
||||
|
||||
export interface RequestOpts {
|
||||
path: string;
|
||||
method: HTTPMethod;
|
||||
headers: HTTPHeaders;
|
||||
query?: HTTPQuery;
|
||||
body?: HTTPBody;
|
||||
}
|
||||
|
||||
export function querystring(params: HTTPQuery, prefix: string = ''): string {
|
||||
return Object.keys(params)
|
||||
.map(key => querystringSingleKey(key, params[key], prefix))
|
||||
.filter(part => part.length > 0)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array<string | number | null | boolean> | Set<string | number | null | boolean> | HTTPQuery, keyPrefix: string = ''): string {
|
||||
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
||||
if (value instanceof Array) {
|
||||
const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue)))
|
||||
.join(`&${encodeURIComponent(fullKey)}=`);
|
||||
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
||||
}
|
||||
if (value instanceof Set) {
|
||||
const valueAsArray = Array.from(value);
|
||||
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
||||
}
|
||||
if (value instanceof Object) {
|
||||
return querystring(value as HTTPQuery, fullKey);
|
||||
}
|
||||
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
||||
}
|
||||
|
||||
export function exists(json: any, key: string) {
|
||||
const value = json[key];
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
export function mapValues(data: any, fn: (item: any) => any) {
|
||||
return Object.keys(data).reduce(
|
||||
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
export function canConsumeForm(consumes: Consume[]): boolean {
|
||||
for (const consume of consumes) {
|
||||
if ('multipart/form-data' === consume.contentType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export interface Consume {
|
||||
contentType: string;
|
||||
}
|
||||
|
||||
export interface RequestContext {
|
||||
fetch: FetchAPI;
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
}
|
||||
|
||||
export interface ResponseContext {
|
||||
fetch: FetchAPI;
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
response: Response;
|
||||
}
|
||||
|
||||
export interface ErrorContext {
|
||||
fetch: FetchAPI;
|
||||
url: string;
|
||||
init: RequestInit;
|
||||
error: unknown;
|
||||
response?: Response;
|
||||
}
|
||||
|
||||
export interface Middleware {
|
||||
pre?(context: RequestContext): Promise<FetchParams | void>;
|
||||
post?(context: ResponseContext): Promise<Response | void>;
|
||||
onError?(context: ErrorContext): Promise<Response | void>;
|
||||
}
|
||||
|
||||
export interface ApiResponse<T> {
|
||||
raw: Response;
|
||||
value(): Promise<T>;
|
||||
}
|
||||
|
||||
export interface ResponseTransformer<T> {
|
||||
(json: any): T;
|
||||
}
|
||||
|
||||
export class JSONApiResponse<T> {
|
||||
constructor(public raw: Response, private transformer: ResponseTransformer<T> = (jsonValue: any) => jsonValue) {}
|
||||
|
||||
async value(): Promise<T> {
|
||||
return this.transformer(await this.raw.json());
|
||||
}
|
||||
}
|
||||
|
||||
export class VoidApiResponse {
|
||||
constructor(public raw: Response) {}
|
||||
|
||||
async value(): Promise<void> {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class BlobApiResponse {
|
||||
constructor(public raw: Response) {}
|
||||
|
||||
async value(): Promise<Blob> {
|
||||
return await this.raw.blob();
|
||||
};
|
||||
}
|
||||
|
||||
export class TextApiResponse {
|
||||
constructor(public raw: Response) {}
|
||||
|
||||
async value(): Promise<string> {
|
||||
return await this.raw.text();
|
||||
};
|
||||
}
|
53
agent/agentUi/src/assets/zrok-1.0.0-rocket-green.svg
Normal file
53
agent/agentUi/src/assets/zrok-1.0.0-rocket-green.svg
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="125.797mm"
|
||||
height="166.26598mm"
|
||||
viewBox="0 0 125.797 166.26598"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4 (e7c3feb, 2024-10-09)"
|
||||
sodipodi:docname="zrok-1.0.0-rocket-white.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showguides="false"
|
||||
inkscape:zoom="0.85634716"
|
||||
inkscape:cx="560.52034"
|
||||
inkscape:cy="509.72318"
|
||||
inkscape:window-width="1952"
|
||||
inkscape:window-height="1304"
|
||||
inkscape:window-x="1311"
|
||||
inkscape:window-y="48"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1"><inkscape:page
|
||||
x="0"
|
||||
y="-4.4822158e-22"
|
||||
width="125.797"
|
||||
height="166.26598"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0" /></sodipodi:namedview><defs
|
||||
id="defs1" /><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-41.620475,-64.027978)"><path
|
||||
id="path2"
|
||||
style="fill:#9bf316;fill-opacity:1;stroke-width:0.865487"
|
||||
d="m 104.52059,64.027974 c 0,0 -12.300998,16.684095 -17.163248,24.964306 -4.8623,8.28022 -7.86765,12.84754 -10.59501,26.3339 -2.72736,13.48636 -1.27406,42.21319 -1.27406,42.21319 l -18.58752,20.04004 -15.280273,49.9615 40.422833,-6.79427 a 22.714797,11.567473 0 0 0 22.320548,9.54731 22.714797,11.567473 0 0 0 22.32712,-9.55945 l 40.72649,6.84277 -15.28027,-49.95979 -18.58916,-20.04001 c 0,0 1.45496,-28.72857 -1.2724,-42.21493 -2.72736,-13.48636 -5.73437,-18.05368 -10.59667,-26.3339 -4.8608,-8.277646 -17.14905,-24.947062 -17.15668,-24.957378 z m -0.0151,14.741718 c 0.52421,0.860497 14.76063,18.300498 18.34492,32.586238 3.65093,14.55125 3.25036,30.16797 2.29067,46.75483 -0.68395,11.82081 -5.48912,37.13724 -8.2384,50.97445 a 22.714797,11.567473 0 0 0 -12.54073,-1.9254 22.714797,11.567473 0 0 0 -12.237098,1.84921 c -2.75047,-13.84452 -7.55003,-39.12307 -8.23343,-50.93462 -0.95969,-16.58687 -1.36026,-32.20531 2.29067,-46.75656 3.57561,-14.25109 17.733538,-31.579359 18.323398,-32.548148 z m -27.999198,95.069708 6.36686,35.53319 -30.30472,9.08328 10.94985,-35.7998 z m 56.021568,0.0351 12.988,8.81667 10.9482,35.80155 -30.30311,-9.08504 z"
|
||||
inkscape:export-filename="zrok-1.0.0-rocket-white.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96" /></g></svg>
|
After Width: | Height: | Size: 2.8 KiB |
55
agent/agentUi/src/index.css
Normal file
55
agent/agentUi/src/index.css
Normal file
@ -0,0 +1,55 @@
|
||||
body {
|
||||
margin: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
padding-bottom: 15px;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: 'JetBrains Mono', sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #241775;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #9bf316;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
#root {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
#footer {
|
||||
text-align: center;
|
||||
}
|
14
agent/agentUi/src/main.tsx
Normal file
14
agent/agentUi/src/main.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import "./index.css";
|
||||
import {StrictMode} from "react";
|
||||
import {createRoot} from "react-dom/client";
|
||||
import {ThemeProvider} from "@mui/material";
|
||||
import {theme} from "./model/theme.ts";
|
||||
import AgentUi from "./AgentUi.tsx";
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<ThemeProvider theme={theme}>
|
||||
<AgentUi />
|
||||
</ThemeProvider>
|
||||
</StrictMode>
|
||||
);
|
5
agent/agentUi/src/model/api.ts
Normal file
5
agent/agentUi/src/model/api.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import {AgentApi, Configuration} from "../api";
|
||||
|
||||
export const GetAgentApi = () => {
|
||||
return new AgentApi(new Configuration({basePath: window.location.origin}));
|
||||
}
|
36
agent/agentUi/src/model/overview.ts
Normal file
36
agent/agentUi/src/model/overview.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import {AccessDetail, ShareDetail, StatusResponse} from "../api";
|
||||
|
||||
export class AgentObject {
|
||||
type: string;
|
||||
id: string;
|
||||
v: (ShareDetail|AccessDetail);
|
||||
}
|
||||
|
||||
export function buildOverview(status: StatusResponse): Array<AgentObject> {
|
||||
let out = new Array<AgentObject>();
|
||||
if(status) {
|
||||
if(status.accesses) {
|
||||
status.accesses.forEach(acc => {
|
||||
let accObj = new AgentObject();
|
||||
accObj.type = "access";
|
||||
accObj.id = acc.frontendToken!;
|
||||
accObj.v = acc;
|
||||
out.push(accObj);
|
||||
});
|
||||
}
|
||||
if(status.shares) {
|
||||
status.shares.forEach(shr => {
|
||||
let shrObj = new AgentObject();
|
||||
shrObj.type = "share";
|
||||
shrObj.id = shr.token!;
|
||||
shrObj.v = shr;
|
||||
out.push(shrObj);
|
||||
});
|
||||
}
|
||||
out.sort((a, b) => {
|
||||
if(a.id < b.id) return -1;
|
||||
if(a.id > b.id) return 1;
|
||||
});
|
||||
}
|
||||
return out;
|
||||
}
|
47
agent/agentUi/src/model/theme.ts
Normal file
47
agent/agentUi/src/model/theme.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import {createTheme} from "@mui/material";
|
||||
|
||||
const componentOptions = {
|
||||
MuiCard: {
|
||||
styleOverrides: {
|
||||
root: ({theme}) => theme.unstable_sx({
|
||||
mt: 5,
|
||||
p: 1,
|
||||
borderRadius: 3,
|
||||
}),
|
||||
}
|
||||
},
|
||||
MuiAppBar: {
|
||||
styleOverrides: {
|
||||
root : ({theme}) => theme.unstable_sx({
|
||||
borderRadius: 3,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const theme = createTheme({
|
||||
components: componentOptions,
|
||||
palette: {
|
||||
mode: 'light',
|
||||
primary: {
|
||||
main: '#241775',
|
||||
},
|
||||
secondary: {
|
||||
main: '#9bf316',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: 'Poppins',
|
||||
},
|
||||
})
|
||||
|
||||
export const modalStyle = {
|
||||
position: 'absolute',
|
||||
top: '25%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 600,
|
||||
bgcolor: 'background.paper',
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
};
|
1
agent/agentUi/src/vite-env.d.ts
vendored
Normal file
1
agent/agentUi/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
26
agent/agentUi/tsconfig.app.json
Normal file
26
agent/agentUi/tsconfig.app.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "Bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
7
agent/agentUi/tsconfig.json
Normal file
7
agent/agentUi/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
24
agent/agentUi/tsconfig.node.json
Normal file
24
agent/agentUi/tsconfig.node.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "Bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
15
agent/agentUi/vite.config.ts
Normal file
15
agent/agentUi/vite.config.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
proxy: {
|
||||
'/v1': {
|
||||
target: 'http://localhost:8888',
|
||||
changeOrigin: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
15
agent/config.go
Normal file
15
agent/config.go
Normal file
@ -0,0 +1,15 @@
|
||||
package agent
|
||||
|
||||
type AgentConfig struct {
|
||||
ConsoleAddress string
|
||||
ConsoleStartPort uint16
|
||||
ConsoleEndPort uint16
|
||||
}
|
||||
|
||||
func DefaultConfig() *AgentConfig {
|
||||
return &AgentConfig{
|
||||
ConsoleAddress: "127.0.0.1",
|
||||
ConsoleStartPort: 8080,
|
||||
ConsoleEndPort: 8181,
|
||||
}
|
||||
}
|
59
agent/proctree/impl_posix.go
Normal file
59
agent/proctree/impl_posix.go
Normal file
@ -0,0 +1,59 @@
|
||||
//go:build !windows
|
||||
|
||||
package proctree
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func Init(_ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartChild(tail TailFunction, args ...string) (*Child, error) {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
|
||||
cld := &Child{
|
||||
TailFunction: tail,
|
||||
cmd: cmd,
|
||||
outStream: make(chan []byte),
|
||||
errStream: make(chan []byte),
|
||||
wg: new(sync.WaitGroup),
|
||||
}
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cld.wg.Add(3)
|
||||
go reader(stdout, cld.outStream, cld.wg)
|
||||
go reader(stderr, cld.errStream, cld.wg)
|
||||
go cld.combiner(cld.wg)
|
||||
|
||||
return cld, nil
|
||||
}
|
||||
|
||||
func WaitChild(c *Child) error {
|
||||
c.wg.Wait()
|
||||
if err := c.cmd.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StopChild(c *Child) error {
|
||||
if err := c.cmd.Process.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
79
agent/proctree/impl_windows.go
Executable file
79
agent/proctree/impl_windows.go
Executable file
@ -0,0 +1,79 @@
|
||||
//go:build windows
|
||||
|
||||
package proctree
|
||||
|
||||
import (
|
||||
"github.com/kolesnikovae/go-winjob"
|
||||
"golang.org/x/sys/windows"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var job *winjob.JobObject
|
||||
|
||||
func Init(name string) error {
|
||||
var err error
|
||||
if job == nil {
|
||||
job, err = winjob.Create(name, winjob.LimitKillOnJobClose, winjob.LimitBreakawayOK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartChild(tail TailFunction, args ...string) (*Child, error) {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.SysProcAttr = &windows.SysProcAttr{CreationFlags: windows.CREATE_SUSPENDED}
|
||||
|
||||
cld := &Child{
|
||||
TailFunction: tail,
|
||||
cmd: cmd,
|
||||
outStream: make(chan []byte),
|
||||
errStream: make(chan []byte),
|
||||
wg: new(sync.WaitGroup),
|
||||
}
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := job.Assign(cmd.Process); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := winjob.ResumeProcess(cmd.Process.Pid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cld.wg.Add(3)
|
||||
go reader(stdout, cld.outStream, cld.wg)
|
||||
go reader(stderr, cld.errStream, cld.wg)
|
||||
go cld.combiner(cld.wg)
|
||||
|
||||
return cld, nil
|
||||
}
|
||||
|
||||
func WaitChild(c *Child) error {
|
||||
c.wg.Wait()
|
||||
if err := c.cmd.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StopChild(c *Child) error {
|
||||
if err := c.cmd.Process.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
67
agent/proctree/proctree.go
Executable file
67
agent/proctree/proctree.go
Executable file
@ -0,0 +1,67 @@
|
||||
package proctree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
_ "github.com/kolesnikovae/go-winjob"
|
||||
"io"
|
||||
"os/exec"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Child struct {
|
||||
TailFunction TailFunction
|
||||
cmd *exec.Cmd
|
||||
outStream chan []byte
|
||||
errStream chan []byte
|
||||
wg *sync.WaitGroup
|
||||
}
|
||||
|
||||
type TailFunction func(data []byte)
|
||||
|
||||
func (c *Child) combiner(wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
outDone := false
|
||||
errDone := false
|
||||
for {
|
||||
select {
|
||||
case data := <-c.outStream:
|
||||
if data != nil {
|
||||
if c.TailFunction != nil {
|
||||
c.TailFunction(data)
|
||||
}
|
||||
} else {
|
||||
outDone = true
|
||||
}
|
||||
case data := <-c.errStream:
|
||||
if data != nil {
|
||||
if c.TailFunction != nil {
|
||||
c.TailFunction(data)
|
||||
}
|
||||
} else {
|
||||
errDone = true
|
||||
}
|
||||
}
|
||||
if outDone && errDone {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func reader(r io.ReadCloser, o chan []byte, wg *sync.WaitGroup) {
|
||||
defer close(o)
|
||||
defer wg.Done()
|
||||
|
||||
buf := make([]byte, 64*1024)
|
||||
for {
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
fmt.Printf("error reading: %v", err)
|
||||
return
|
||||
}
|
||||
o <- buf[:n]
|
||||
}
|
||||
}
|
19
agent/releaseAccess.go
Normal file
19
agent/releaseAccess.go
Normal file
@ -0,0 +1,19 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) ReleaseAccess(_ context.Context, req *agentGrpc.ReleaseAccessRequest) (*agentGrpc.ReleaseAccessResponse, error) {
|
||||
if acc, found := i.agent.accesses[req.FrontendToken]; found {
|
||||
i.agent.rmAccess <- acc
|
||||
logrus.Infof("released access '%v'", acc.frontendToken)
|
||||
|
||||
} else {
|
||||
return nil, errors.Errorf("agent has no access with frontend token '%v'", req.FrontendToken)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
19
agent/releaseShare.go
Executable file
19
agent/releaseShare.go
Executable file
@ -0,0 +1,19 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) ReleaseShare(_ context.Context, req *agentGrpc.ReleaseShareRequest) (*agentGrpc.ReleaseShareResponse, error) {
|
||||
if shr, found := i.agent.shares[req.Token]; found {
|
||||
i.agent.rmShare <- shr
|
||||
logrus.Infof("released share '%v'", shr.token)
|
||||
|
||||
} else {
|
||||
return nil, errors.Errorf("agent has no share with token '%v'", req.Token)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
83
agent/share.go
Normal file
83
agent/share.go
Normal file
@ -0,0 +1,83 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"time"
|
||||
)
|
||||
|
||||
type share struct {
|
||||
token string
|
||||
frontendEndpoints []string
|
||||
target string
|
||||
basicAuth []string
|
||||
frontendSelection []string
|
||||
shareMode sdk.ShareMode
|
||||
backendMode sdk.BackendMode
|
||||
reserved bool
|
||||
insecure bool
|
||||
oauthProvider string
|
||||
oauthEmailAddressPatterns []string
|
||||
oauthCheckInterval time.Duration
|
||||
closed bool
|
||||
accessGrants []string
|
||||
|
||||
process *proctree.Child
|
||||
sub *subordinate.MessageHandler
|
||||
|
||||
agent *Agent
|
||||
}
|
||||
|
||||
func (s *share) monitor() {
|
||||
if err := proctree.WaitChild(s.process); err != nil {
|
||||
pfxlog.ChannelLogger(s.token).Error(err)
|
||||
}
|
||||
s.agent.rmShare <- s
|
||||
}
|
||||
|
||||
func (s *share) bootHandler(msgType string, msg subordinate.Message) error {
|
||||
switch msgType {
|
||||
case subordinate.BootMessage:
|
||||
if v, found := msg["token"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.token = str
|
||||
}
|
||||
}
|
||||
if v, found := msg["backend_mode"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.backendMode = sdk.BackendMode(str)
|
||||
}
|
||||
}
|
||||
if v, found := msg["share_mode"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.shareMode = sdk.ShareMode(str)
|
||||
}
|
||||
}
|
||||
if v, found := msg["frontend_endpoints"]; found {
|
||||
if vArr, ok := v.([]interface{}); ok {
|
||||
for _, v := range vArr {
|
||||
if str, ok := v.(string); ok {
|
||||
s.frontendEndpoints = append(s.frontendEndpoints, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if v, found := msg["target"]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
s.target = str
|
||||
}
|
||||
}
|
||||
|
||||
case subordinate.ErrorMessage:
|
||||
if v, found := msg[subordinate.ErrorMessage]; found {
|
||||
if str, ok := v.(string); ok {
|
||||
return errors.New(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
82
agent/sharePrivate.go
Normal file
82
agent/sharePrivate.go
Normal file
@ -0,0 +1,82 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) SharePrivate(_ context.Context, req *agentGrpc.SharePrivateRequest) (*agentGrpc.SharePrivateResponse, error) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
|
||||
}
|
||||
|
||||
shrCmd := []string{os.Args[0], "share", "private", "--subordinate", "-b", req.BackendMode}
|
||||
shr := &share{
|
||||
shareMode: sdk.PrivateShareMode,
|
||||
backendMode: sdk.BackendMode(req.BackendMode),
|
||||
sub: subordinate.NewMessageHandler(),
|
||||
agent: i.agent,
|
||||
}
|
||||
shr.sub.MessageHandler = func(msg subordinate.Message) {
|
||||
logrus.Info(msg)
|
||||
}
|
||||
var bootErr error
|
||||
shr.sub.BootHandler = func(msgType string, msg subordinate.Message) {
|
||||
bootErr = shr.bootHandler(msgType, msg)
|
||||
}
|
||||
shr.sub.MalformedHandler = func(msg subordinate.Message) {
|
||||
logrus.Error(msg)
|
||||
}
|
||||
|
||||
if req.Insecure {
|
||||
shrCmd = append(shrCmd, "--insecure")
|
||||
}
|
||||
shr.insecure = req.Insecure
|
||||
|
||||
if req.Closed {
|
||||
shrCmd = append(shrCmd, "--closed")
|
||||
}
|
||||
shr.closed = req.Closed
|
||||
|
||||
for _, grant := range req.AccessGrants {
|
||||
shrCmd = append(shrCmd, "--access-grant", grant)
|
||||
}
|
||||
shr.accessGrants = req.AccessGrants
|
||||
|
||||
shrCmd = append(shrCmd, req.Target)
|
||||
shr.target = req.Target
|
||||
|
||||
logrus.Infof("executing '%v'", shrCmd)
|
||||
|
||||
shr.process, err = proctree.StartChild(shr.sub.Tail, shrCmd...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
<-shr.sub.BootComplete
|
||||
|
||||
if bootErr == nil {
|
||||
go shr.monitor()
|
||||
i.agent.addShare <- shr
|
||||
return &agentGrpc.SharePrivateResponse{Token: shr.token}, nil
|
||||
|
||||
} else {
|
||||
if err := proctree.WaitChild(shr.process); err != nil {
|
||||
logrus.Errorf("error joining: %v", err)
|
||||
}
|
||||
return nil, fmt.Errorf("unable to start share: %v", bootErr)
|
||||
}
|
||||
}
|
109
agent/sharePublic.go
Normal file
109
agent/sharePublic.go
Normal file
@ -0,0 +1,109 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) SharePublic(_ context.Context, req *agentGrpc.SharePublicRequest) (*agentGrpc.SharePublicResponse, error) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
|
||||
}
|
||||
|
||||
shrCmd := []string{os.Args[0], "share", "public", "--subordinate", "-b", req.BackendMode}
|
||||
shr := &share{
|
||||
shareMode: sdk.PublicShareMode,
|
||||
backendMode: sdk.BackendMode(req.BackendMode),
|
||||
sub: subordinate.NewMessageHandler(),
|
||||
agent: i.agent,
|
||||
}
|
||||
shr.sub.MessageHandler = func(msg subordinate.Message) {
|
||||
logrus.Info(msg)
|
||||
}
|
||||
var bootErr error
|
||||
shr.sub.BootHandler = func(msgType string, msg subordinate.Message) {
|
||||
bootErr = shr.bootHandler(msgType, msg)
|
||||
}
|
||||
shr.sub.MalformedHandler = func(msg subordinate.Message) {
|
||||
logrus.Error(msg)
|
||||
}
|
||||
|
||||
for _, basicAuth := range req.BasicAuth {
|
||||
shrCmd = append(shrCmd, "--basic-auth", basicAuth)
|
||||
}
|
||||
shr.basicAuth = req.BasicAuth
|
||||
|
||||
for _, frontendSelection := range req.FrontendSelection {
|
||||
shrCmd = append(shrCmd, "--frontend", frontendSelection)
|
||||
}
|
||||
shr.frontendSelection = req.FrontendSelection
|
||||
|
||||
if req.Insecure {
|
||||
shrCmd = append(shrCmd, "--insecure")
|
||||
}
|
||||
shr.insecure = req.Insecure
|
||||
|
||||
if req.OauthProvider != "" {
|
||||
shrCmd = append(shrCmd, "--oauth-provider", req.OauthProvider)
|
||||
}
|
||||
shr.oauthProvider = req.OauthProvider
|
||||
|
||||
for _, pattern := range req.OauthEmailAddressPatterns {
|
||||
shrCmd = append(shrCmd, "--oauth-email-address-patterns", pattern)
|
||||
}
|
||||
shr.oauthEmailAddressPatterns = req.OauthEmailAddressPatterns
|
||||
|
||||
if req.OauthCheckInterval != "" {
|
||||
shrCmd = append(shrCmd, "--oauth-check-interval", req.OauthCheckInterval)
|
||||
}
|
||||
|
||||
if req.Closed {
|
||||
shrCmd = append(shrCmd, "--closed")
|
||||
}
|
||||
shr.closed = req.Closed
|
||||
|
||||
for _, grant := range req.AccessGrants {
|
||||
shrCmd = append(shrCmd, "--access-grant", grant)
|
||||
}
|
||||
shr.accessGrants = req.AccessGrants
|
||||
|
||||
shrCmd = append(shrCmd, req.Target)
|
||||
shr.target = req.Target
|
||||
|
||||
logrus.Infof("executing '%v'", shrCmd)
|
||||
|
||||
shr.process, err = proctree.StartChild(shr.sub.Tail, shrCmd...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
<-shr.sub.BootComplete
|
||||
|
||||
if bootErr == nil {
|
||||
go shr.monitor()
|
||||
i.agent.addShare <- shr
|
||||
return &agentGrpc.SharePublicResponse{
|
||||
Token: shr.token,
|
||||
FrontendEndpoints: shr.frontendEndpoints,
|
||||
}, nil
|
||||
|
||||
} else {
|
||||
if err := proctree.WaitChild(shr.process); err != nil {
|
||||
logrus.Errorf("error joining: %v", err)
|
||||
}
|
||||
return nil, fmt.Errorf("unable to start share: %v", bootErr)
|
||||
}
|
||||
}
|
78
agent/shareReserved.go
Normal file
78
agent/shareReserved.go
Normal file
@ -0,0 +1,78 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/agent/proctree"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) ShareReserved(_ context.Context, req *agentGrpc.ShareReservedRequest) (*agentGrpc.ShareReservedResponse, error) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
return nil, errors.New("unable to load environment; did you 'zrok enable'?")
|
||||
}
|
||||
|
||||
shrCmd := []string{os.Args[0], "share", "reserved", "--subordinate"}
|
||||
shr := &share{
|
||||
reserved: true,
|
||||
sub: subordinate.NewMessageHandler(),
|
||||
agent: i.agent,
|
||||
}
|
||||
shr.sub.MessageHandler = func(msg subordinate.Message) {
|
||||
logrus.Info(msg)
|
||||
}
|
||||
var bootErr error
|
||||
shr.sub.BootHandler = func(msgType string, msg subordinate.Message) {
|
||||
bootErr = shr.bootHandler(msgType, msg)
|
||||
}
|
||||
shr.sub.MalformedHandler = func(msg subordinate.Message) {
|
||||
logrus.Error(msg)
|
||||
}
|
||||
|
||||
if req.OverrideEndpoint != "" {
|
||||
shrCmd = append(shrCmd, "--override-endpoint", req.OverrideEndpoint)
|
||||
}
|
||||
|
||||
if req.Insecure {
|
||||
shrCmd = append(shrCmd, "--insecure")
|
||||
}
|
||||
shr.insecure = req.Insecure
|
||||
|
||||
shrCmd = append(shrCmd, req.Token)
|
||||
shr.token = req.Token
|
||||
|
||||
shr.process, err = proctree.StartChild(shr.sub.Tail, shrCmd...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
<-shr.sub.BootComplete
|
||||
|
||||
if bootErr == nil {
|
||||
go shr.monitor()
|
||||
i.agent.addShare <- shr
|
||||
return &agentGrpc.ShareReservedResponse{
|
||||
Token: shr.token,
|
||||
BackendMode: string(shr.backendMode),
|
||||
ShareMode: string(shr.shareMode),
|
||||
FrontendEndpoints: shr.frontendEndpoints,
|
||||
Target: shr.target,
|
||||
}, nil
|
||||
|
||||
} else {
|
||||
if err := proctree.WaitChild(shr.process); err != nil {
|
||||
logrus.Errorf("error joining: %v", err)
|
||||
}
|
||||
return nil, fmt.Errorf("unable to start share: %v", bootErr)
|
||||
}
|
||||
}
|
40
agent/status.go
Normal file
40
agent/status.go
Normal file
@ -0,0 +1,40 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) Status(_ context.Context, _ *agentGrpc.StatusRequest) (*agentGrpc.StatusResponse, error) {
|
||||
var accesses []*agentGrpc.AccessDetail
|
||||
for feToken, acc := range i.agent.accesses {
|
||||
accesses = append(accesses, &agentGrpc.AccessDetail{
|
||||
FrontendToken: feToken,
|
||||
Token: acc.token,
|
||||
BindAddress: acc.bindAddress,
|
||||
ResponseHeaders: acc.responseHeaders,
|
||||
})
|
||||
}
|
||||
sort.Slice(accesses, func(i, j int) bool {
|
||||
return accesses[i].FrontendToken < accesses[j].FrontendToken
|
||||
})
|
||||
|
||||
var shares []*agentGrpc.ShareDetail
|
||||
for token, shr := range i.agent.shares {
|
||||
shares = append(shares, &agentGrpc.ShareDetail{
|
||||
Token: token,
|
||||
ShareMode: string(shr.shareMode),
|
||||
BackendMode: string(shr.backendMode),
|
||||
Reserved: shr.reserved,
|
||||
FrontendEndpoint: shr.frontendEndpoints,
|
||||
BackendEndpoint: shr.target,
|
||||
Closed: shr.closed,
|
||||
})
|
||||
}
|
||||
sort.Slice(shares, func(i, j int) bool {
|
||||
return shares[i].Token < shares[j].Token
|
||||
})
|
||||
|
||||
return &agentGrpc.StatusResponse{Accesses: accesses, Shares: shares}, nil
|
||||
}
|
17
agent/version.go
Normal file
17
agent/version.go
Normal file
@ -0,0 +1,17 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/build"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (i *agentGrpcImpl) Version(_ context.Context, _ *agentGrpc.VersionRequest) (*agentGrpc.VersionResponse, error) {
|
||||
v := build.String()
|
||||
logrus.Debugf("responding to version inquiry with '%v'", v)
|
||||
return &agentGrpc.VersionResponse{
|
||||
V: v,
|
||||
ConsoleEndpoint: i.agent.httpEndpoint,
|
||||
}, nil
|
||||
}
|
14
bin/generate_pb.sh
Executable file
14
bin/generate_pb.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
go install \
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
|
||||
google.golang.org/protobuf/cmd/protoc-gen-go \
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||
|
||||
protoc --go_out=. --go_opt=paths=source_relative \
|
||||
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
|
||||
--grpc-gateway_out=. --grpc-gateway_opt=paths=source_relative \
|
||||
--openapiv2_out=. \
|
||||
agent/agentGrpc/agent.proto
|
||||
|
@ -2,39 +2,41 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
command -v swagger >/dev/null 2>&1 || {
|
||||
command -v swagger &>/dev/null || {
|
||||
echo >&2 "command 'swagger' not installed. see: https://github.com/go-swagger/go-swagger for installation"
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v openapi >/dev/null 2>&1 || {
|
||||
echo >&2 "command 'openapi' not installed. see: https://www.npmjs.com/package/openapi-client for installation"
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v swagger-codegen 2>&1 || {
|
||||
command -v swagger-codegen &>/dev/null || {
|
||||
echo >&2 "command 'swagger-codegen' not installed. see: https://github.com/swagger-api/swagger-codegen for installation"
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v openapi-generator-cli 2>&1 || {
|
||||
command -v openapi-generator-cli &>/dev/null || {
|
||||
echo >&2 "command 'openapi-generator-cli' not installed. see: https://www.npmjs.com/package/@openapitools/openapi-generator-cli for installation"
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v realpath 2>&1 || {
|
||||
command -v realpath &>/dev/null || {
|
||||
echo >&2 "command 'realpath' not installed. see: https://www.npmjs.com/package/realpath for installation"
|
||||
exit 1
|
||||
}
|
||||
|
||||
scriptPath=$(realpath $0)
|
||||
scriptPath=$(realpath "$0")
|
||||
scriptDir=$(dirname "$scriptPath")
|
||||
|
||||
zrokDir=$(realpath "$scriptDir/..")
|
||||
|
||||
zrokSpec=$(realpath "$zrokDir/specs/zrok.yml")
|
||||
|
||||
pythonConfig=$(realpath "$zrokDir/bin/python_config.json")
|
||||
# anti-oops in case user runs this script from somewhere else
|
||||
if [[ "$(realpath "$zrokDir")" != "$(realpath "$(pwd)")" ]]
|
||||
then
|
||||
echo "ERROR: must be run from zrok root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "...clean generate zrok server/client"
|
||||
rm -rf ./rest_client_zrok ./rest_server_zrok ./rest_model_zrok
|
||||
|
||||
echo "...generating zrok server"
|
||||
swagger generate server -P rest_model_zrok.Principal -f "$zrokSpec" -s rest_server_zrok -t "$zrokDir" -m "rest_model_zrok" --exclude-main
|
||||
@ -42,13 +44,22 @@ swagger generate server -P rest_model_zrok.Principal -f "$zrokSpec" -s rest_serv
|
||||
echo "...generating zrok client"
|
||||
swagger generate client -P rest_model_zrok.Principal -f "$zrokSpec" -c rest_client_zrok -t "$zrokDir" -m "rest_model_zrok"
|
||||
|
||||
echo "...generating js client"
|
||||
openapi -s specs/zrok.yml -o ui/src/api -l js
|
||||
echo "...generating api console ts client"
|
||||
rm -rf ui/src/api
|
||||
openapi-generator-cli generate -i "$zrokSpec" -o ui/src/api -g typescript-fetch
|
||||
|
||||
echo "...generating ts client"
|
||||
openapi-generator-cli generate -i specs/zrok.yml -o sdk/nodejs/sdk/src/zrok/api -g typescript-node
|
||||
echo "...generating agent console ts client"
|
||||
rm -rf agent/agentUi/src/api
|
||||
openapi-generator-cli generate -i agent/agentGrpc/agent.swagger.json -o agent/agentUi/src/api -g typescript-fetch
|
||||
|
||||
echo "...generating python client"
|
||||
swagger-codegen generate -i specs/zrok.yml -o sdk/python/sdk/zrok -c $pythonConfig -l python
|
||||
echo "...generating nodejs sdk ts client"
|
||||
rm -rf sdk/nodejs/sdk/src/api
|
||||
openapi-generator-cli generate -i "$zrokSpec" -o sdk/nodejs/sdk/src/api -g typescript-fetch
|
||||
|
||||
echo "...generating python sdk client"
|
||||
pyMod="./sdk/python/src"
|
||||
rm -rf "$pyMod"/{zrok_api,docs,test,.gitignore,README.md,requirements.txt}
|
||||
openapi-generator-cli generate -i "$zrokSpec" -o "$pyMod" -g python \
|
||||
--package-name zrok_api --additional-properties projectName=zrok
|
||||
|
||||
git checkout rest_server_zrok/configure_zrok.go
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"packageName":"zrok_api",
|
||||
"projectName":"zrok_sdk"
|
||||
}
|
@ -5,7 +5,7 @@ import "fmt"
|
||||
var Version string
|
||||
var Hash string
|
||||
|
||||
const Series = "v0.4"
|
||||
const Series = "v1.0"
|
||||
|
||||
func String() string {
|
||||
if Version != "" {
|
||||
|
47
canary/looper.go
Normal file
47
canary/looper.go
Normal file
@ -0,0 +1,47 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LooperOptions struct {
|
||||
Iterations uint
|
||||
StatusInterval uint
|
||||
Timeout time.Duration
|
||||
MinPayload uint64
|
||||
MaxPayload uint64
|
||||
MinDwell time.Duration
|
||||
MaxDwell time.Duration
|
||||
MinPacing time.Duration
|
||||
MaxPacing time.Duration
|
||||
}
|
||||
|
||||
type LooperResults struct {
|
||||
StartTime time.Time
|
||||
StopTime time.Time
|
||||
Loops uint
|
||||
Errors uint
|
||||
Mismatches uint
|
||||
Bytes uint64
|
||||
}
|
||||
|
||||
func ReportLooperResults(results []*LooperResults) {
|
||||
totalBytes := uint64(0)
|
||||
totalXferRate := uint64(0)
|
||||
totalErrors := uint(0)
|
||||
totalMismatches := uint(0)
|
||||
totalLoops := uint(0)
|
||||
for i, result := range results {
|
||||
totalBytes += result.Bytes
|
||||
deltaSeconds := result.StopTime.Sub(result.StartTime).Seconds()
|
||||
xferRate := uint64(float64(result.Bytes) / deltaSeconds)
|
||||
totalXferRate += xferRate
|
||||
totalErrors += result.Errors
|
||||
totalMismatches += result.Mismatches
|
||||
totalLoops += result.Loops
|
||||
logrus.Infof("looper #%d: %d loops, %v, %d errors, %d mismatches, %s/sec", i, result.Loops, util.BytesToSize(int64(result.Bytes)), result.Errors, result.Mismatches, util.BytesToSize(int64(xferRate)))
|
||||
}
|
||||
logrus.Infof("total: %d loops, %v, %d errors, %d mismatches, %s/sec", totalLoops, util.BytesToSize(int64(totalBytes)), totalErrors, totalMismatches, util.BytesToSize(int64(totalXferRate)))
|
||||
}
|
236
canary/privateHttpLooper.go
Normal file
236
canary/privateHttpLooper.go
Normal file
@ -0,0 +1,236 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
cryptorand "crypto/rand"
|
||||
"encoding/base64"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PrivateHttpLooper struct {
|
||||
id uint
|
||||
acc *sdk.Access
|
||||
opt *LooperOptions
|
||||
root env_core.Root
|
||||
shr *sdk.Share
|
||||
listener edge.Listener
|
||||
abort bool
|
||||
done chan struct{}
|
||||
results *LooperResults
|
||||
}
|
||||
|
||||
func NewPrivateHttpLooper(id uint, opt *LooperOptions, root env_core.Root) *PrivateHttpLooper {
|
||||
return &PrivateHttpLooper{
|
||||
id: id,
|
||||
opt: opt,
|
||||
root: root,
|
||||
done: make(chan struct{}),
|
||||
results: &LooperResults{},
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) Run() {
|
||||
defer close(l.done)
|
||||
defer logrus.Infof("#%d stopping", l.id)
|
||||
defer l.shutdown()
|
||||
logrus.Infof("#%d starting", l.id)
|
||||
|
||||
if err := l.startup(); err != nil {
|
||||
logrus.Fatalf("#%d error starting: %v", l.id, err)
|
||||
}
|
||||
|
||||
if err := l.bind(); err != nil {
|
||||
logrus.Fatalf("#%d error binding: %v", l.id, err)
|
||||
}
|
||||
|
||||
l.dwell()
|
||||
|
||||
l.iterate()
|
||||
|
||||
logrus.Infof("#%d completed", l.id)
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) Abort() {
|
||||
l.abort = true
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) Done() <-chan struct{} {
|
||||
return l.done
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) Results() *LooperResults {
|
||||
return l.results
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) startup() error {
|
||||
shr, err := sdk.CreateShare(l.root, &sdk.ShareRequest{
|
||||
ShareMode: sdk.PrivateShareMode,
|
||||
BackendMode: sdk.ProxyBackendMode,
|
||||
Target: "canary.PrivateHttpLooper",
|
||||
PermissionMode: sdk.ClosedPermissionMode,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.shr = shr
|
||||
|
||||
acc, err := sdk.CreateAccess(l.root, &sdk.AccessRequest{
|
||||
ShareToken: shr.Token,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.acc = acc
|
||||
|
||||
logrus.Infof("#%d allocated share '%v', allocated frontend '%v'", l.id, shr.Token, acc.Token)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) bind() error {
|
||||
zif, err := l.root.ZitiIdentityNamed(l.root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "#%d error getting identity", l.id)
|
||||
}
|
||||
zcfg, err := ziti.NewConfigFromFile(zif)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "#%d error loading ziti config", l.id)
|
||||
}
|
||||
options := ziti.ListenOptions{
|
||||
ConnectTimeout: 5 * time.Minute,
|
||||
WaitForNEstablishedListeners: 1,
|
||||
}
|
||||
zctx, err := ziti.NewContext(zcfg)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "#%d error creating ziti context", l.id)
|
||||
}
|
||||
|
||||
if l.listener, err = zctx.ListenWithOptions(l.shr.Token, &options); err != nil {
|
||||
return errors.Wrapf(err, "#%d error binding listener", l.id)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := http.Serve(l.listener, l); err != nil {
|
||||
logrus.Errorf("#%d error in http listener: %v", l.id, err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
buf := new(bytes.Buffer)
|
||||
io.Copy(buf, r.Body)
|
||||
w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) dwell() {
|
||||
dwell := l.opt.MinDwell.Milliseconds()
|
||||
dwelta := l.opt.MaxDwell.Milliseconds() - l.opt.MinDwell.Milliseconds()
|
||||
if dwelta > 0 {
|
||||
dwell = int64(rand.Intn(int(dwelta)) + int(l.opt.MinDwell.Milliseconds()))
|
||||
}
|
||||
time.Sleep(time.Duration(dwell) * time.Millisecond)
|
||||
}
|
||||
|
||||
type connDialer struct {
|
||||
c net.Conn
|
||||
}
|
||||
|
||||
func (cd connDialer) Dial(_ context.Context, network, addr string) (net.Conn, error) {
|
||||
return cd.c, nil
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) iterate() {
|
||||
l.results.StartTime = time.Now()
|
||||
defer func() { l.results.StopTime = time.Now() }()
|
||||
|
||||
for i := uint(0); i < l.opt.Iterations; i++ {
|
||||
if i > 0 && i%l.opt.StatusInterval == 0 {
|
||||
logrus.Infof("#%d: iteration %d", l.id, i)
|
||||
}
|
||||
|
||||
conn, err := sdk.NewDialer(l.shr.Token, l.root)
|
||||
if err != nil {
|
||||
logrus.Errorf("#%d: error dialing: %v", l.id, err)
|
||||
l.results.Errors++
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
payloadSize := l.opt.MaxPayload
|
||||
payloadRange := l.opt.MaxPayload - l.opt.MinPayload
|
||||
if payloadRange > 0 {
|
||||
payloadSize = (rand.Uint64() % payloadRange) + l.opt.MinPayload
|
||||
}
|
||||
outPayload := make([]byte, payloadSize)
|
||||
cryptorand.Read(outPayload)
|
||||
outBase64 := base64.StdEncoding.EncodeToString(outPayload)
|
||||
|
||||
if req, err := http.NewRequest("POST", "http://"+l.shr.Token, bytes.NewBufferString(outBase64)); err == nil {
|
||||
client := &http.Client{Timeout: l.opt.Timeout, Transport: &http.Transport{DialContext: connDialer{conn}.Dial}}
|
||||
if resp, err := client.Do(req); err == nil {
|
||||
if resp.StatusCode != 200 {
|
||||
logrus.Errorf("#%d: unexpected status code: %v", l.id, resp.StatusCode)
|
||||
l.results.Errors++
|
||||
}
|
||||
inPayload := new(bytes.Buffer)
|
||||
io.Copy(inPayload, resp.Body)
|
||||
inBase64 := inPayload.String()
|
||||
if inBase64 != outBase64 {
|
||||
logrus.Errorf("#%d: payload mismatch", l.id)
|
||||
l.results.Mismatches++
|
||||
} else {
|
||||
l.results.Bytes += uint64(len(outBase64))
|
||||
logrus.Debugf("#%d: payload match", l.id)
|
||||
}
|
||||
} else {
|
||||
logrus.Errorf("#%d: error: %v", l.id, err)
|
||||
l.results.Errors++
|
||||
}
|
||||
} else {
|
||||
logrus.Errorf("#%d: error creating request: %v", l.id, err)
|
||||
l.results.Errors++
|
||||
}
|
||||
|
||||
if err := conn.Close(); err != nil {
|
||||
logrus.Errorf("#%d: error closing connection: %v", l.id, err)
|
||||
}
|
||||
|
||||
pacingMs := l.opt.MaxPacing.Milliseconds()
|
||||
pacingDelta := l.opt.MaxPacing.Milliseconds() - l.opt.MinPacing.Milliseconds()
|
||||
if pacingDelta > 0 {
|
||||
pacingMs = (rand.Int63() % pacingDelta) + l.opt.MinPacing.Milliseconds()
|
||||
time.Sleep(time.Duration(pacingMs) * time.Millisecond)
|
||||
}
|
||||
|
||||
l.results.Loops++
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PrivateHttpLooper) shutdown() {
|
||||
if l.listener != nil {
|
||||
if err := l.listener.Close(); err != nil {
|
||||
logrus.Errorf("#%d error closing listener: %v", l.id, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := sdk.DeleteAccess(l.root, l.acc); err != nil {
|
||||
logrus.Errorf("#%d error deleting access '%v': %v", l.id, l.acc.Token, err)
|
||||
}
|
||||
|
||||
if err := sdk.DeleteShare(l.root, l.shr); err != nil {
|
||||
logrus.Errorf("#%d error deleting share '%v': %v", l.id, l.shr.Token, err)
|
||||
}
|
||||
}
|
204
canary/publicHttpLooper.go
Normal file
204
canary/publicHttpLooper.go
Normal file
@ -0,0 +1,204 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
cryptorand "crypto/rand"
|
||||
"encoding/base64"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/edge"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PublicHttpLooper struct {
|
||||
id uint
|
||||
frontend string
|
||||
opt *LooperOptions
|
||||
root env_core.Root
|
||||
shr *sdk.Share
|
||||
listener edge.Listener
|
||||
abort bool
|
||||
done chan struct{}
|
||||
results *LooperResults
|
||||
}
|
||||
|
||||
func NewPublicHttpLooper(id uint, frontend string, opt *LooperOptions, root env_core.Root) *PublicHttpLooper {
|
||||
return &PublicHttpLooper{
|
||||
id: id,
|
||||
frontend: frontend,
|
||||
opt: opt,
|
||||
root: root,
|
||||
done: make(chan struct{}),
|
||||
results: &LooperResults{},
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) Run() {
|
||||
defer close(l.done)
|
||||
defer logrus.Infof("#%d stopping", l.id)
|
||||
defer l.shutdown()
|
||||
logrus.Infof("#%d starting", l.id)
|
||||
|
||||
if err := l.startup(); err != nil {
|
||||
logrus.Fatalf("#%d error starting: %v", l.id, err)
|
||||
}
|
||||
|
||||
if err := l.bind(); err != nil {
|
||||
logrus.Fatalf("#%d error binding: %v", l.id, err)
|
||||
}
|
||||
|
||||
l.dwell()
|
||||
|
||||
l.iterate()
|
||||
|
||||
logrus.Infof("#%d completed", l.id)
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) Abort() {
|
||||
l.abort = true
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) Done() <-chan struct{} {
|
||||
return l.done
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) Results() *LooperResults {
|
||||
return l.results
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) startup() error {
|
||||
shr, err := sdk.CreateShare(l.root, &sdk.ShareRequest{
|
||||
ShareMode: sdk.PublicShareMode,
|
||||
BackendMode: sdk.ProxyBackendMode,
|
||||
Target: "canary.PublicHttpLooper",
|
||||
Frontends: []string{l.frontend},
|
||||
PermissionMode: sdk.ClosedPermissionMode,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.shr = shr
|
||||
|
||||
logrus.Infof("#%d allocated share '%v'", l.id, l.shr.Token)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) bind() error {
|
||||
zif, err := l.root.ZitiIdentityNamed(l.root.EnvironmentIdentityName())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "#%d error getting identity", l.id)
|
||||
}
|
||||
zcfg, err := ziti.NewConfigFromFile(zif)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "#%d error loading ziti config", l.id)
|
||||
}
|
||||
options := ziti.ListenOptions{
|
||||
ConnectTimeout: 5 * time.Minute,
|
||||
WaitForNEstablishedListeners: 1,
|
||||
}
|
||||
zctx, err := ziti.NewContext(zcfg)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "#%d error creating ziti context", l.id)
|
||||
}
|
||||
|
||||
if l.listener, err = zctx.ListenWithOptions(l.shr.Token, &options); err != nil {
|
||||
return errors.Wrapf(err, "#%d error binding listener", l.id)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := http.Serve(l.listener, l); err != nil {
|
||||
logrus.Errorf("#%d error in http listener: %v", l.id, err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
buf := new(bytes.Buffer)
|
||||
io.Copy(buf, r.Body)
|
||||
w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) dwell() {
|
||||
dwell := l.opt.MinDwell.Milliseconds()
|
||||
dwelta := l.opt.MaxDwell.Milliseconds() - l.opt.MinDwell.Milliseconds()
|
||||
if dwelta > 0 {
|
||||
dwell = int64(rand.Intn(int(dwelta)) + int(l.opt.MinDwell.Milliseconds()))
|
||||
}
|
||||
time.Sleep(time.Duration(dwell) * time.Millisecond)
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) iterate() {
|
||||
l.results.StartTime = time.Now()
|
||||
defer func() { l.results.StopTime = time.Now() }()
|
||||
|
||||
for i := uint(0); i < l.opt.Iterations && !l.abort; i++ {
|
||||
if i > 0 && i%l.opt.StatusInterval == 0 {
|
||||
logrus.Infof("#%d: iteration %d", l.id, i)
|
||||
}
|
||||
|
||||
payloadSize := l.opt.MaxPayload
|
||||
payloadRange := l.opt.MaxPayload - l.opt.MinPayload
|
||||
if payloadRange > 0 {
|
||||
payloadSize = (rand.Uint64() % payloadRange) + l.opt.MinPayload
|
||||
}
|
||||
outPayload := make([]byte, payloadSize)
|
||||
cryptorand.Read(outPayload)
|
||||
outBase64 := base64.StdEncoding.EncodeToString(outPayload)
|
||||
|
||||
if req, err := http.NewRequest("POST", l.shr.FrontendEndpoints[0], bytes.NewBufferString(outBase64)); err == nil {
|
||||
client := &http.Client{Timeout: l.opt.Timeout}
|
||||
if resp, err := client.Do(req); err == nil {
|
||||
if resp.StatusCode != 200 {
|
||||
logrus.Errorf("#%d: unexpected status code: %v", l.id, resp.StatusCode)
|
||||
l.results.Errors++
|
||||
}
|
||||
inPayload := new(bytes.Buffer)
|
||||
io.Copy(inPayload, resp.Body)
|
||||
inBase64 := inPayload.String()
|
||||
if inBase64 != outBase64 {
|
||||
logrus.Errorf("#%d: payload mismatch", l.id)
|
||||
l.results.Mismatches++
|
||||
} else {
|
||||
l.results.Bytes += uint64(len(outBase64))
|
||||
logrus.Debugf("#%d: payload match", l.id)
|
||||
}
|
||||
} else {
|
||||
logrus.Errorf("#%d: error: %v", l.id, err)
|
||||
l.results.Errors++
|
||||
}
|
||||
} else {
|
||||
logrus.Errorf("#%d: error creating request: %v", l.id, err)
|
||||
l.results.Errors++
|
||||
}
|
||||
|
||||
pacingMs := l.opt.MaxPacing.Milliseconds()
|
||||
pacingDelta := l.opt.MaxPacing.Milliseconds() - l.opt.MinPacing.Milliseconds()
|
||||
if pacingDelta > 0 {
|
||||
pacingMs = (rand.Int63() % pacingDelta) + l.opt.MinPacing.Milliseconds()
|
||||
time.Sleep(time.Duration(pacingMs) * time.Millisecond)
|
||||
}
|
||||
|
||||
l.results.Loops++
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PublicHttpLooper) shutdown() {
|
||||
if l.listener != nil {
|
||||
if err := l.listener.Close(); err != nil {
|
||||
logrus.Errorf("#%d error closing listener: %v", l.id, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := sdk.DeleteShare(l.root, l.shr); err != nil {
|
||||
logrus.Errorf("#%d error deleting share '%v': %v", l.id, l.shr.Token, err)
|
||||
}
|
||||
}
|
@ -1,19 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/agent/agentClient"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/cmd/zrok/subordinate"
|
||||
"github.com/openziti/zrok/endpoints"
|
||||
"github.com/openziti/zrok/endpoints/proxy"
|
||||
"github.com/openziti/zrok/endpoints/tcpTunnel"
|
||||
"github.com/openziti/zrok/endpoints/udpTunnel"
|
||||
"github.com/openziti/zrok/endpoints/vpn"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/rest_client_zrok"
|
||||
"github.com/openziti/zrok/rest_client_zrok/share"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"net/url"
|
||||
@ -29,7 +37,14 @@ func init() {
|
||||
|
||||
type accessPrivateCommand struct {
|
||||
bindAddress string
|
||||
autoMode bool
|
||||
autoAddress string
|
||||
autoStartPort uint16
|
||||
autoEndPort uint16
|
||||
headless bool
|
||||
subordinate bool
|
||||
forceLocal bool
|
||||
forceAgent bool
|
||||
responseHeaders []string
|
||||
cmd *cobra.Command
|
||||
}
|
||||
@ -41,47 +56,98 @@ func newAccessPrivateCommand() *accessPrivateCommand {
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
command := &accessPrivateCommand{cmd: cmd}
|
||||
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
|
||||
cmd.Flags().StringVarP(&command.bindAddress, "bind", "b", "127.0.0.1:9191", "The address to bind the private frontend")
|
||||
headless := false
|
||||
if root, err := environment.LoadRoot(); err == nil {
|
||||
headless, _ = root.Headless()
|
||||
}
|
||||
cmd.Flags().BoolVar(&command.headless, "headless", headless, "Disable TUI and run headless")
|
||||
cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable subordinate mode")
|
||||
cmd.MarkFlagsMutuallyExclusive("headless", "subordinate")
|
||||
cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode")
|
||||
cmd.Flags().BoolVar(&command.forceAgent, "force-agent", false, "Skip agent detection and force agent mode")
|
||||
cmd.MarkFlagsMutuallyExclusive("force-local", "force-agent")
|
||||
cmd.Flags().StringVarP(&command.bindAddress, "bind", "b", "127.0.0.1:9191", "The address to bind the private frontend (ignored when using '--auto')")
|
||||
cmd.Flags().BoolVar(&command.autoMode, "auto", false, "Enable automatic port detection")
|
||||
cmd.Flags().StringVar(&command.autoAddress, "auto-address", "127.0.0.1", "The address to use for automatic port detection")
|
||||
cmd.Flags().Uint16Var(&command.autoStartPort, "auto-start-port", 8080, "The starting port to use for automatic port detection")
|
||||
cmd.Flags().Uint16Var(&command.autoEndPort, "auto-end-port", 8888, "The ending port to use for automatic port detection")
|
||||
cmd.Flags().StringArrayVar(&command.responseHeaders, "response-header", []string{}, "Add a response header ('key:value')")
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
shrToken := args[0]
|
||||
|
||||
env, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading environment", err)
|
||||
if cmd.subordinate {
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{TimestampFormat: time.RFC3339Nano})
|
||||
}
|
||||
|
||||
if !env.IsEnabled() {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
cmd.error(err)
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
zrok, err := env.Client()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create zrok client", err)
|
||||
if cmd.subordinate || cmd.forceLocal {
|
||||
cmd.accessLocal(args, root)
|
||||
} else {
|
||||
agent := cmd.forceAgent
|
||||
if !cmd.forceAgent {
|
||||
agent, err = agentClient.IsAgentRunning(root)
|
||||
if err != nil {
|
||||
tui.Error("error checking if agent is running", err)
|
||||
}
|
||||
}
|
||||
panic(err)
|
||||
if agent {
|
||||
cmd.accessAgent(args, root)
|
||||
} else {
|
||||
cmd.accessLocal(args, root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *accessPrivateCommand) accessLocal(args []string, root env_core.Root) {
|
||||
shrToken := args[0]
|
||||
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
cmd.error(err)
|
||||
}
|
||||
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", env.Environment().Token)
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().AccountToken)
|
||||
req := share.NewAccessParams()
|
||||
req.Body = &rest_model_zrok.AccessRequest{
|
||||
ShrToken: shrToken,
|
||||
EnvZID: env.Environment().ZitiIdentity,
|
||||
}
|
||||
req.Body.ShareToken = shrToken
|
||||
req.Body.EnvZID = root.Environment().ZitiIdentity
|
||||
|
||||
accessResp, err := zrok.Share.Access(req, auth)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.error(err)
|
||||
}
|
||||
|
||||
bindAddress := cmd.bindAddress
|
||||
if cmd.autoMode {
|
||||
if accessResp.Payload.BackendMode == "udpTunnel" {
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(errors.New("auto-addressing is not compatible with the 'udpTunnel' backend mode"))
|
||||
}
|
||||
autoAddress, err := util.AutoListenerAddress("tcp", cmd.autoAddress, cmd.autoStartPort, cmd.autoEndPort)
|
||||
if err != nil {
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
bindAddress = autoAddress
|
||||
}
|
||||
|
||||
upReq := share.NewUpdateAccessParams()
|
||||
upReq.Body.FrontendToken = accessResp.Payload.FrontendToken
|
||||
upReq.Body.BindAddress = bindAddress
|
||||
_, err = zrok.Share.UpdateAccess(upReq, auth)
|
||||
if err != nil {
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
logrus.Infof("allocated frontend '%v'", accessResp.Payload.FrontendToken)
|
||||
|
||||
protocol := "http://"
|
||||
switch accessResp.Payload.BackendMode {
|
||||
@ -91,80 +157,66 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
protocol = "udp://"
|
||||
}
|
||||
|
||||
endpointUrl, err := url.Parse(protocol + cmd.bindAddress)
|
||||
endpointUrl, err := url.Parse(protocol + bindAddress)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("invalid endpoint address", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
|
||||
requests := make(chan *endpoints.Request, 1024)
|
||||
switch accessResp.Payload.BackendMode {
|
||||
case "tcpTunnel":
|
||||
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
|
||||
BindAddress: cmd.bindAddress,
|
||||
IdentityName: env.EnvironmentIdentityName(),
|
||||
BindAddress: bindAddress,
|
||||
IdentityName: root.EnvironmentIdentityName(),
|
||||
ShrToken: args[0],
|
||||
RequestsChan: requests,
|
||||
})
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
go func() {
|
||||
if err := fe.Run(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error starting access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "udpTunnel":
|
||||
fe, err := udpTunnel.NewFrontend(&udpTunnel.FrontendConfig{
|
||||
BindAddress: cmd.bindAddress,
|
||||
IdentityName: env.EnvironmentIdentityName(),
|
||||
IdentityName: root.EnvironmentIdentityName(),
|
||||
ShrToken: args[0],
|
||||
RequestsChan: requests,
|
||||
IdleTime: time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private frontend", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
go func() {
|
||||
if err := fe.Run(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error starting frontend", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
case "socks":
|
||||
fe, err := tcpTunnel.NewFrontend(&tcpTunnel.FrontendConfig{
|
||||
BindAddress: cmd.bindAddress,
|
||||
IdentityName: env.EnvironmentIdentityName(),
|
||||
BindAddress: bindAddress,
|
||||
IdentityName: root.EnvironmentIdentityName(),
|
||||
ShrToken: args[0],
|
||||
RequestsChan: requests,
|
||||
})
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
go func() {
|
||||
if err := fe.Run(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error starting access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -173,55 +225,60 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
Scheme: "VPN",
|
||||
}
|
||||
fe, err := vpn.NewFrontend(&vpn.FrontendConfig{
|
||||
IdentityName: env.EnvironmentIdentityName(),
|
||||
IdentityName: root.EnvironmentIdentityName(),
|
||||
ShrToken: args[0],
|
||||
RequestsChan: requests,
|
||||
})
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
go func() {
|
||||
if err := fe.Run(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("error starting access", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
default:
|
||||
cfg := proxy.DefaultFrontendConfig(env.EnvironmentIdentityName())
|
||||
cfg := proxy.DefaultFrontendConfig(root.EnvironmentIdentityName())
|
||||
cfg.ShrToken = shrToken
|
||||
cfg.Address = cmd.bindAddress
|
||||
cfg.Address = bindAddress
|
||||
cfg.ResponseHeaders = cmd.responseHeaders
|
||||
cfg.RequestsChan = requests
|
||||
fe, err := proxy.NewFrontend(cfg)
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private frontend", err)
|
||||
}
|
||||
panic(err)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
go func() {
|
||||
if err := fe.Run(); err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to run frontend", err)
|
||||
}
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.error(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT)
|
||||
go func() {
|
||||
<-c
|
||||
cmd.destroy(accessResp.Payload.FrontendToken, env.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
if cmd.subordinate {
|
||||
data := make(map[string]interface{})
|
||||
data[subordinate.MessageKey] = subordinate.BootMessage
|
||||
data["frontend_token"] = accessResp.Payload.FrontendToken
|
||||
data["bind_address"] = bindAddress
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
subordinateError(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
|
||||
if cmd.headless {
|
||||
logrus.Infof("access the zrok share at the following endpoint: %v", endpointUrl.String())
|
||||
for {
|
||||
@ -230,7 +287,22 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
logrus.Infof("%v -> %v %v", req.RemoteAddr, req.Method, req.Path)
|
||||
}
|
||||
}
|
||||
|
||||
} else if cmd.subordinate {
|
||||
for {
|
||||
select {
|
||||
case req := <-requests:
|
||||
data := make(map[string]interface{})
|
||||
data[subordinate.MessageKey] = "access"
|
||||
data["remote-address"] = req.RemoteAddr
|
||||
data["method"] = req.Method
|
||||
data["path"] = req.Path
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mdl := newAccessModel(shrToken, endpointUrl.String())
|
||||
logrus.SetOutput(mdl)
|
||||
@ -253,21 +325,56 @@ func (cmd *accessPrivateCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
close(requests)
|
||||
cmd.destroy(accessResp.Payload.FrontendToken, env.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
cmd.shutdown(accessResp.Payload.FrontendToken, root.Environment().ZitiIdentity, shrToken, zrok, auth)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *accessPrivateCommand) destroy(frontendName, envZId, shrToken string, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) {
|
||||
logrus.Debugf("shutting down '%v'", shrToken)
|
||||
req := share.NewUnaccessParams()
|
||||
req.Body = &rest_model_zrok.UnaccessRequest{
|
||||
FrontendToken: frontendName,
|
||||
ShrToken: shrToken,
|
||||
EnvZID: envZId,
|
||||
func (cmd *accessPrivateCommand) error(err error) {
|
||||
if cmd.subordinate {
|
||||
subordinateError(err)
|
||||
}
|
||||
if !panicInstead {
|
||||
tui.Error("unable to create private access", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func (cmd *accessPrivateCommand) shutdown(frontendToken, envZId, shrToken string, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) {
|
||||
logrus.Infof("shutting down '%v'", shrToken)
|
||||
req := share.NewUnaccessParams()
|
||||
req.Body.FrontendToken = frontendToken
|
||||
req.Body.ShareToken = shrToken
|
||||
req.Body.EnvZID = envZId
|
||||
if _, err := zrok.Share.Unaccess(req, auth); err == nil {
|
||||
logrus.Debugf("shutdown complete")
|
||||
} else {
|
||||
logrus.Errorf("error shutting down: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *accessPrivateCommand) accessAgent(args []string, root env_core.Root) {
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
req := &agentGrpc.AccessPrivateRequest{
|
||||
Token: args[0],
|
||||
BindAddress: cmd.bindAddress,
|
||||
ResponseHeaders: cmd.responseHeaders,
|
||||
}
|
||||
if cmd.autoMode {
|
||||
req.AutoMode = true
|
||||
req.AutoAddress = cmd.autoAddress
|
||||
req.AutoStartPort = uint32(cmd.autoStartPort)
|
||||
req.AutoEndPort = uint32(cmd.autoEndPort)
|
||||
}
|
||||
|
||||
acc, err := client.AccessPrivate(context.Background(), req)
|
||||
if err != nil {
|
||||
tui.Error("error creating access", err)
|
||||
}
|
||||
|
||||
fmt.Println(acc)
|
||||
}
|
||||
|
@ -46,5 +46,5 @@ func (cmd *adminCreateAccount) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(resp.GetPayload().Token)
|
||||
fmt.Println(resp.GetPayload().AccountToken)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -52,12 +51,10 @@ func (cmd *adminCreateFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
permissionMode = sdk.ClosedPermissionMode
|
||||
}
|
||||
req := admin.NewCreateFrontendParams()
|
||||
req.Body = &rest_model_zrok.CreateFrontendRequest{
|
||||
ZID: zId,
|
||||
PublicName: publicName,
|
||||
URLTemplate: urlTemplate,
|
||||
PermissionMode: string(permissionMode),
|
||||
}
|
||||
req.Body.ZID = zId
|
||||
req.Body.PublicName = publicName
|
||||
req.Body.URLTemplate = urlTemplate
|
||||
req.Body.PermissionMode = string(permissionMode)
|
||||
|
||||
resp, err := zrok.Admin.CreateFrontend(req, mustGetAdminAuth())
|
||||
if err != nil {
|
||||
@ -71,5 +68,5 @@ func (cmd *adminCreateFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Infof("created global public frontend '%v'", resp.Payload.Token)
|
||||
logrus.Infof("created global public frontend '%v'", resp.Payload.FrontendToken)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func (cmd *adminCreateOrgMemberCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
req := admin.NewAddOrganizationMemberParams()
|
||||
req.Body.Token = args[0]
|
||||
req.Body.OrganizationToken = args[0]
|
||||
req.Body.Email = args[1]
|
||||
req.Body.Admin = cmd.admin
|
||||
|
||||
|
@ -48,5 +48,5 @@ func (cmd *adminCreateOrganizationCommand) run(_ *cobra.Command, _ []string) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logrus.Infof("created new organization with token '%v'", resp.Payload.Token)
|
||||
logrus.Infof("created new organization with organization token '%v'", resp.Payload.OrganizationToken)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -41,7 +40,7 @@ func (cmd *adminDeleteFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
req := admin.NewDeleteFrontendParams()
|
||||
req.Body = &rest_model_zrok.DeleteFrontendRequest{FrontendToken: feToken}
|
||||
req.Body.FrontendToken = feToken
|
||||
|
||||
_, err = zrok.Admin.DeleteFrontend(req, mustGetAdminAuth())
|
||||
if err != nil {
|
||||
|
@ -39,7 +39,7 @@ func (cmd *adminDeleteOrgMemberCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
req := admin.NewRemoveOrganizationMemberParams()
|
||||
req.Body.Token = args[0]
|
||||
req.Body.OrganizationToken = args[0]
|
||||
req.Body.Email = args[1]
|
||||
|
||||
_, err = zrok.Admin.RemoveOrganizationMember(req, mustGetAdminAuth())
|
||||
|
@ -39,7 +39,7 @@ func (cmd *adminDeleteOrganizationCommand) run(_ *cobra.Command, args []string)
|
||||
}
|
||||
|
||||
req := admin.NewDeleteOrganizationParams()
|
||||
req.Body.Token = args[0]
|
||||
req.Body.OrganizationToken = args[0]
|
||||
|
||||
_, err = zrok.Admin.DeleteOrganization(req, mustGetAdminAuth())
|
||||
if err != nil {
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"github.com/jaevor/go-nanoid"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -54,9 +53,8 @@ func (cmd *adminGenerateCommand) run(_ *cobra.Command, args []string) {
|
||||
panic(err)
|
||||
}
|
||||
req := admin.NewInviteTokenGenerateParams()
|
||||
req.Body = &rest_model_zrok.InviteTokenGenerateRequest{
|
||||
Tokens: tokens,
|
||||
}
|
||||
req.Body.InviteTokens = tokens
|
||||
|
||||
_, err = zrok.Admin.InviteTokenGenerate(req, mustGetAdminAuth())
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
|
@ -54,7 +54,7 @@ func (cmd *adminListFrontendsCommand) run(_ *cobra.Command, _ []string) {
|
||||
t.AppendHeader(table.Row{"Token", "zId", "Public Name", "Url Template", "Created At", "Updated At"})
|
||||
for _, pfe := range resp.Payload {
|
||||
t.AppendRow(table.Row{
|
||||
pfe.Token,
|
||||
pfe.FrontendToken,
|
||||
pfe.ZID,
|
||||
pfe.PublicName,
|
||||
pfe.URLTemplate,
|
||||
|
@ -41,7 +41,7 @@ func (cmd *adminListOrgMembersCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
req := admin.NewListOrganizationMembersParams()
|
||||
req.Body.Token = args[0]
|
||||
req.Body.OrganizationToken = args[0]
|
||||
|
||||
resp, err := zrok.Admin.ListOrganizationMembers(req, mustGetAdminAuth())
|
||||
if err != nil {
|
||||
|
@ -52,7 +52,7 @@ func (c *adminListOrganizationsCommand) run(_ *cobra.Command, _ []string) {
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Organization Token", "Description"})
|
||||
for _, org := range resp.Payload.Organizations {
|
||||
t.AppendRow(table.Row{org.Token, org.Description})
|
||||
t.AppendRow(table.Row{org.OrganizationToken, org.Description})
|
||||
}
|
||||
t.Render()
|
||||
fmt.Println()
|
||||
|
@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||
"github.com/openziti/zrok/rest_model_zrok"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -49,11 +48,9 @@ func (cmd *adminUpdateFrontendCommand) run(_ *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
req := admin.NewUpdateFrontendParams()
|
||||
req.Body = &rest_model_zrok.UpdateFrontendRequest{
|
||||
FrontendToken: feToken,
|
||||
PublicName: cmd.newPublicName,
|
||||
URLTemplate: cmd.newUrlTemplate,
|
||||
}
|
||||
req.Body.FrontendToken = feToken
|
||||
req.Body.PublicName = cmd.newPublicName
|
||||
req.Body.URLTemplate = cmd.newUrlTemplate
|
||||
|
||||
_, err = zrok.Admin.UpdateFrontend(req, mustGetAdminAuth())
|
||||
if err != nil {
|
||||
|
52
cmd/zrok/agentConsole.go
Normal file
52
cmd/zrok/agentConsole.go
Normal file
@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentClient"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentCmd.AddCommand(newAgentConsoleCommand().cmd)
|
||||
}
|
||||
|
||||
type agentConsoleCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentConsoleCommand() *agentConsoleCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "console",
|
||||
Short: "Open the Agent console",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &agentConsoleCommand{cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentConsoleCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
v, err := client.Version(context.Background(), &agentGrpc.VersionRequest{})
|
||||
if err != nil {
|
||||
tui.Error("error getting agent version", err)
|
||||
}
|
||||
|
||||
if err := openBrowser("http://" + v.ConsoleEndpoint); err != nil {
|
||||
tui.Error(fmt.Sprintf("unable to open agent console at 'http://%v'", v.ConsoleEndpoint), err)
|
||||
}
|
||||
}
|
55
cmd/zrok/agentReleaseAccess.go
Normal file
55
cmd/zrok/agentReleaseAccess.go
Normal file
@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentClient"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentReleaseCmd.AddCommand(newAgentReleaseAccessCommand().cmd)
|
||||
}
|
||||
|
||||
type agentReleaseAccessCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentReleaseAccessCommand() *agentReleaseAccessCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "access <frontendToken>",
|
||||
Short: "Unbind an access from the zrok Agent",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
command := &agentReleaseAccessCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentReleaseAccessCommand) run(_ *cobra.Command, args []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = client.ReleaseAccess(context.Background(), &agentGrpc.ReleaseAccessRequest{
|
||||
FrontendToken: args[0],
|
||||
})
|
||||
if err != nil {
|
||||
tui.Error("error releasing access", err)
|
||||
}
|
||||
|
||||
fmt.Println("success.")
|
||||
}
|
55
cmd/zrok/agentReleaseShare.go
Executable file
55
cmd/zrok/agentReleaseShare.go
Executable file
@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/agent/agentClient"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentReleaseCmd.AddCommand(newAgentReleaseShareCommand().cmd)
|
||||
}
|
||||
|
||||
type agentReleaseShareCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentReleaseShareCommand() *agentReleaseShareCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "share <token>",
|
||||
Short: "Release a share from the zrok Agent",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
command := &agentReleaseShareCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentReleaseShareCommand) run(_ *cobra.Command, args []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
if !panicInstead {
|
||||
tui.Error("unable to load environment", err)
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = client.ReleaseShare(context.Background(), &agentGrpc.ReleaseShareRequest{
|
||||
Token: args[0],
|
||||
})
|
||||
if err != nil {
|
||||
tui.Error("error releasing share", err)
|
||||
}
|
||||
|
||||
fmt.Println("success.")
|
||||
}
|
72
cmd/zrok/agentStart.go
Normal file
72
cmd/zrok/agentStart.go
Normal file
@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/agent"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentCmd.AddCommand(newAgentStartCommand().cmd)
|
||||
}
|
||||
|
||||
type agentStartCommand struct {
|
||||
cmd *cobra.Command
|
||||
consoleAddress string
|
||||
consoleStartPort uint16
|
||||
consoleEndPort uint16
|
||||
}
|
||||
|
||||
func newAgentStartCommand() *agentStartCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start a zrok agent",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &agentStartCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
cmd.Flags().StringVar(&command.consoleAddress, "console-address", "127.0.0.1", "gRPC gateway address")
|
||||
cmd.Flags().Uint16Var(&command.consoleStartPort, "console-start-port", 8888, "gRPC gateway starting port")
|
||||
cmd.Flags().Uint16Var(&command.consoleEndPort, "console-end-port", 8988, "gRPC gateway ending port")
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentStartCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
|
||||
if !root.IsEnabled() {
|
||||
tui.Error("unable to load environment; did you 'zrok enable'?", nil)
|
||||
}
|
||||
|
||||
cfg := agent.DefaultConfig()
|
||||
cfg.ConsoleAddress = cmd.consoleAddress
|
||||
cfg.ConsoleStartPort = cmd.consoleStartPort
|
||||
cfg.ConsoleEndPort = cmd.consoleEndPort
|
||||
a, err := agent.NewAgent(cfg, root)
|
||||
if err != nil {
|
||||
tui.Error("error creating agent", err)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
cmd.shutdown(a)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
if err := a.Run(); err != nil {
|
||||
tui.Error("agent aborted", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *agentStartCommand) shutdown(a *agent.Agent) {
|
||||
a.Shutdown()
|
||||
}
|
74
cmd/zrok/agentStatus.go
Normal file
74
cmd/zrok/agentStatus.go
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/openziti/zrok/agent/agentClient"
|
||||
"github.com/openziti/zrok/agent/agentGrpc"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/openziti/zrok/tui"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
func init() {
|
||||
agentCmd.AddCommand(newAgentStatusCommand().cmd)
|
||||
}
|
||||
|
||||
type agentStatusCommand struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAgentStatusCommand() *agentStatusCommand {
|
||||
cmd := &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "Show the status of the running zrok Agent",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &agentStatusCommand{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *agentStatusCommand) run(_ *cobra.Command, _ []string) {
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
tui.Error("error loading zrokdir", err)
|
||||
}
|
||||
|
||||
client, conn, err := agentClient.NewClient(root)
|
||||
if err != nil {
|
||||
tui.Error("error connecting to agent", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
status, err := client.Status(context.Background(), &agentGrpc.StatusRequest{})
|
||||
if err != nil {
|
||||
tui.Error("error getting status", err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
t := table.NewWriter()
|
||||
t.SetOutputMirror(os.Stdout)
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Frontend Token", "Token", "Bind Address"})
|
||||
for _, access := range status.GetAccesses() {
|
||||
t.AppendRow(table.Row{access.FrontendToken, access.Token, access.BindAddress})
|
||||
}
|
||||
t.Render()
|
||||
fmt.Printf("%d accesses in agent\n", len(status.GetAccesses()))
|
||||
|
||||
fmt.Println()
|
||||
t = table.NewWriter()
|
||||
t.SetOutputMirror(os.Stdout)
|
||||
t.SetStyle(table.StyleColoredDark)
|
||||
t.AppendHeader(table.Row{"Token", "Reserved", "Share Mode", "Backend Mode", "Target"})
|
||||
for _, share := range status.GetShares() {
|
||||
t.AppendRow(table.Row{share.Token, share.Reserved, share.ShareMode, share.BackendMode, share.BackendEndpoint})
|
||||
}
|
||||
t.Render()
|
||||
fmt.Printf("%d shares in agent\n", len(status.GetShares()))
|
||||
|
||||
fmt.Println()
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user