Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Agent UI 1 #797

Merged
merged 92 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
6942408
initial grpc-gateway integration (#759)
michaelquigley Oct 1, 2024
0baf1dd
integrated openapi generation (#759)
michaelquigley Oct 1, 2024
c3fafec
next.js skeleton for agent ui (#221)
michaelquigley Oct 1, 2024
b787c6c
rough wiring for the grpc gateway (#221)
michaelquigley Oct 1, 2024
f7746bb
strip of the boilerplate (#221)
michaelquigley Oct 1, 2024
433290d
agent-ui rest client generation; initial version endpoint call (#221)
michaelquigley Oct 2, 2024
eebc6ef
table components and dynamic refresh for mvp (#221)
michaelquigley Oct 2, 2024
f168091
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Oct 3, 2024
24ed2ec
next.js -> vite.js (#221)
michaelquigley Oct 4, 2024
99a0eea
both production and development builds now working with vite.js (#221)
michaelquigley Oct 4, 2024
5d57087
add all share/access overview data (#221)
michaelquigley Oct 4, 2024
3f00bb6
sort shares/accesses in status call (#221)
michaelquigley Oct 4, 2024
8bdf4f0
fix dependency (#221)
michaelquigley Oct 4, 2024
62e75e9
add vite build for agent ui to ci (#221)
michaelquigley Oct 4, 2024
03c2f1e
vite build refactoring (#221)
michaelquigley Oct 4, 2024
5d8da3c
update middleware for agent ui to work properly on windows (#221)
michaelquigley Oct 4, 2024
6bcd569
agent console iteration (#221)
michaelquigley Oct 4, 2024
b0178a0
zrok agent console (#221)
michaelquigley Oct 4, 2024
d3568c0
wired in console endpoint into agent, wired into 'zrok agent console'…
michaelquigley Oct 4, 2024
4749411
logging and other lint
michaelquigley Oct 7, 2024
a67dba0
toolbar (#221)
michaelquigley Oct 8, 2024
c5c5bb0
react router (#221)
michaelquigley Oct 8, 2024
f0cd66d
route parmeters (#221)
michaelquigley Oct 8, 2024
c02b9c2
centralized state (#221)
michaelquigley Oct 9, 2024
6eb60fc
centralized data retrieval (#221)
michaelquigley Oct 9, 2024
258980c
roughed-in cards (#221)
michaelquigley Oct 9, 2024
05aa12e
roughed in share and release through the agent ui (#221)
michaelquigley Oct 10, 2024
c424190
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Oct 11, 2024
a9abb8f
zrok office hours - zrok agent ui development (#221)
michaelquigley Oct 11, 2024
22cd4fa
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Oct 16, 2024
aa24e8b
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Oct 18, 2024
0c52aad
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Oct 18, 2024
aa5810a
initial mui theme customization (#221)
michaelquigley Oct 21, 2024
28e8896
more mui (#221)
michaelquigley Oct 21, 2024
b9609f1
theme component customization (#221)
michaelquigley Oct 21, 2024
7571a38
mui styling (#221)
michaelquigley Oct 21, 2024
b40e692
branding (#221)
michaelquigley Oct 21, 2024
ba34f47
component model refactoring (#221)
michaelquigley Oct 21, 2024
fe97b6d
throwing things at the wall (#221)
michaelquigley Oct 23, 2024
492e53b
more random junk at the wall (#221)
michaelquigley Oct 23, 2024
d2556b2
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Oct 24, 2024
9867067
de-leaked (#221)
michaelquigley Oct 28, 2024
c84b2a3
@mui/material/Grid2 (#221)
michaelquigley Oct 29, 2024
9a12ab4
responsive layout improvements (#221)
michaelquigley Oct 29, 2024
e34e661
handler tweaks (#221)
michaelquigley Oct 29, 2024
0a99e3b
oops (#221)
michaelquigley Oct 29, 2024
2a6ecc6
tweaks (#221)
michaelquigley Oct 29, 2024
472b397
new share form improvements (#221)
michaelquigley Oct 29, 2024
84c1b8c
agent console iteration (#221)
michaelquigley Oct 29, 2024
553c2fe
bigger (#221)
michaelquigley Oct 29, 2024
6f1c8e6
size (#221)
michaelquigley Oct 29, 2024
475c939
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Nov 5, 2024
99a2e66
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Nov 6, 2024
fe08a19
basic ranged auto listener (#779)
michaelquigley Nov 6, 2024
a0b7416
endpoint -> address (#779)
michaelquigley Nov 6, 2024
e7331e8
move autolistener into util (#780)
michaelquigley Nov 7, 2024
bf6f795
'--auto' mode for 'zrok access private' (#780)
michaelquigley Nov 7, 2024
3f8e760
update agent protocol to support auto mode (#780)
michaelquigley Nov 7, 2024
c728ae8
support --auto mode for agent-based private shares (#780)
michaelquigley Nov 7, 2024
f00835d
changelog (#780)
michaelquigley Nov 7, 2024
1face3b
error handing for '--subordinate' in 'zrok access private' (#789)
michaelquigley Nov 8, 2024
662aa59
debugging lint
michaelquigley Nov 8, 2024
35fc32b
error handling dry (#789)
michaelquigley Nov 8, 2024
94cfba7
subordinate mode messaging improvements (#789)
michaelquigley Nov 12, 2024
f5601e3
reworked 'tail' function for subordinate access (#789)
michaelquigley Nov 12, 2024
ef5e654
subordinate protocol update for 'zrok share private' (#789)
michaelquigley Nov 12, 2024
bf3a470
update 'zrok share reserved' to latest subordinate protocol (#789)
michaelquigley Nov 12, 2024
f4fa04e
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Nov 13, 2024
85a2295
refactored 'share.tail' for new subordinate boot protocol (#789)
michaelquigley Nov 13, 2024
6b4dbaa
use json logging when in subordinate mode (#789)
michaelquigley Nov 13, 2024
77eca93
first iteration of work on the subordinate process framework (#789)
michaelquigley Nov 13, 2024
1e89bad
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Nov 14, 2024
a41ed30
tweaks (#789)
michaelquigley Nov 14, 2024
5c4cf9b
migrated the access infrastructure in the agent over to the new 'subo…
michaelquigley Nov 14, 2024
3205b92
port the share infrastructure over to the subordinate framework (#789)
michaelquigley Nov 15, 2024
0bdbc9e
new typescript skeleton for agent ui (#781)
michaelquigley Nov 18, 2024
fe77e69
prune unused dependencies (#781)
michaelquigley Nov 18, 2024
32f661c
package lint (#221)
michaelquigley Nov 18, 2024
6a535a1
exercise the generated api (#781)
michaelquigley Nov 18, 2024
7377b02
skip typescript checking for production builds (for now) (#221)
michaelquigley Nov 18, 2024
c3a6ef1
more typescript porting (#221)
michaelquigley Nov 19, 2024
7f9f610
Merge branch 'v1_0_0' into agent_ui_1
michaelquigley Nov 19, 2024
0f2418e
share and access cards ported (#221)
michaelquigley Nov 19, 2024
7944985
new share modal ported to typescript (#221)
michaelquigley Nov 19, 2024
5298326
everything ported to typescript (#221)
michaelquigley Nov 19, 2024
fe6b861
replaced the old javascript 'agentUi' with the new typescript 'agentU…
michaelquigley Nov 19, 2024
6f674db
idiomatic lint (#221)
michaelquigley Nov 20, 2024
569dfce
typography lint (#221)
michaelquigley Nov 20, 2024
2770090
better idiom (#221)
michaelquigley Nov 20, 2024
7e641a9
error handling lint (#221)
michaelquigley Nov 20, 2024
5a9ed02
changelog for desktop ui (#221)
michaelquigley Nov 20, 2024
786a4e7
last round of generator testing to make sure everything is dialed in …
michaelquigley Nov 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,29 @@ 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
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ MAJOR RELEASE: zrok reaches version 1.0.0!

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)

## v0.4.45

FIX: Update indirect dependency `github.com/golang-jwt/jwt/v4` to version `v4.5.1` (https://github.com/openziti/zrok/issues/794)
Expand Down
60 changes: 7 additions & 53 deletions agent/access.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
package agent

import (
"bytes"
"encoding/json"
"errors"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/zrok/agent/proctree"
"github.com/sirupsen/logrus"
"strings"
"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
readBuffer bytes.Buffer
booted bool
bootComplete chan struct{}
bootErr error
process *proctree.Child
sub *subordinate.MessageHandler

agent *Agent
}
Expand All @@ -31,46 +28,3 @@ func (a *access) monitor() {
}
a.agent.rmAccess <- a
}

func (a *access) tail(data []byte) {
defer func() {
if r := recover(); r != nil {
logrus.Errorf("recovering: %v", r)
}
}()
a.readBuffer.Write(data)
if line, err := a.readBuffer.ReadString('\n'); err == nil {
line = strings.Trim(line, "\n")
if !a.booted {
in := make(map[string]interface{})
if err := json.Unmarshal([]byte(line), &in); err == nil {
if v, found := in["frontend_token"]; found {
if str, ok := v.(string); ok {
a.frontendToken = str
}
}
if v, found := in["bind_address"]; found {
if str, ok := v.(string); ok {
a.bindAddress = str
}
}
a.booted = true
} else {
a.bootErr = errors.New(line)
}
close(a.bootComplete)

} else {
if strings.HasPrefix(line, "{") {
in := make(map[string]interface{})
if err := json.Unmarshal([]byte(line), &in); err == nil {
pfxlog.ChannelLogger(a.token).Info(in)
}
} else {
pfxlog.ChannelLogger(a.token).Info(strings.Trim(line, "\n"))
}
}
} else {
a.readBuffer.WriteString(line)
}
}
59 changes: 52 additions & 7 deletions agent/accessPrivate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ 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"
Expand All @@ -21,28 +23,71 @@ func (i *agentGrpcImpl) AccessPrivate(_ context.Context, req *agentGrpc.AccessPr
}

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,
bootComplete: make(chan struct{}),
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.tail, accCmd...)
acc.process, err = proctree.StartChild(acc.sub.Tail, accCmd...)
if err != nil {
return nil, err
}

go acc.monitor()
<-acc.bootComplete
<-acc.sub.BootComplete

if acc.bootErr == nil {
if bootErr == nil {
go acc.monitor()
i.agent.addAccess <- acc
return &agentGrpc.AccessPrivateResponse{FrontendToken: acc.frontendToken}, nil
}

return nil, acc.bootErr
} 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)
}
}
61 changes: 51 additions & 10 deletions agent/agent.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
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 {
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
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(root env_core.Root) (*Agent, error) {
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),
Expand All @@ -44,7 +53,6 @@ func (a *Agent) Run() error {
if err := proctree.Init("zrok Agent"); err != nil {
return err
}
go a.manager()

agentSocket, err := a.root.AgentSocket()
if err != nil {
Expand All @@ -56,6 +64,9 @@ func (a *Agent) Run() error {
}
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 {
Expand All @@ -81,6 +92,36 @@ func (a *Agent) Shutdown() {
}
}

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")
Expand Down
Loading
Loading