mirror of
https://github.com/openziti/zrok.git
synced 2025-06-19 17:27:54 +02:00
Merge branch 'main' into v1.next_canary
This commit is contained in:
commit
c3dd6ac116
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@
|
||||
*.db
|
||||
/automated-release-build/
|
||||
etc/dev.yml
|
||||
etc/dev-canary.yml
|
||||
etc/dev-frontend.yml
|
||||
|
||||
# Dependencies
|
||||
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,5 +1,25 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v1.0.3
|
||||
|
||||
FEATURE: New `zrok admin unbootstrap` to remove zrok resources from the underlying OpenZiti instance (https://github.com/openziti/zrok/issues/935)
|
||||
|
||||
FEATURE: New InfluxDB metrics capture infrastructure for `zrok test canary` framework (https://github.com/openziti/zrok/issues/948)
|
||||
|
||||
FEATURE: New `zrok test canary enabler` to validate `enable`/`disable` operations and gather performance metrics around how those paths are operating (https://github.com/openziti/zrok/issues/771)
|
||||
|
||||
CHANGE: New _guard_ to prevent users from running potentially dangerous `zrok test canary` commands inadvertently without understanding what they do (https://github.com/openziti/zrok/issues/947)
|
||||
|
||||
## v1.0.2
|
||||
|
||||
FEATURE: "Auto-rebase" for enabled environments where the `apiEndpoint` is set to `https://api.zrok.io`. This will automatically migrate existing environments to the new `apiEndpoint` for the `v1.0.x` series (https://github.com/openziti/zrok/issues/936)
|
||||
|
||||
FEATURE: New `admin/new_account_link` configuration option to allow the insertion of "how do I register for an account?" links into the login form (https://github.com/openziti/zrok/issues/552)
|
||||
|
||||
CHANGE: The release environment, share, and access modals in the API console now have a better message letting the user know they will still need to clean up their `zrok` processes (https://github.com/openziti/zrok/issues/910)
|
||||
|
||||
CHANGE: The openziti/zrok Docker image has been updated to use the latest version of the ziti CLI, 1.4.3 (https://github.com/openziti/zrok/pull/917)
|
||||
|
||||
## v1.0.1
|
||||
|
||||
FEATURE: The zrok Agent now persists private accesses and reserved shares between executions. Any `zrok access private` instances or `zrok share reserved` instances created using the agent are now persisted to a registry stored in `${HOME}/.zrok`. When restarting the agent these accesses and reserved shares are re-created from the data in this registry (https://github.com/openziti/zrok/pull/922)
|
||||
|
31
canary/config.go
Normal file
31
canary/config.go
Normal file
@ -0,0 +1,31 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"github.com/michaelquigley/cf"
|
||||
"github.com/openziti/zrok/controller/metrics"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const ConfigVersion = 1
|
||||
|
||||
type Config struct {
|
||||
V int
|
||||
Influx *metrics.InfluxConfig
|
||||
}
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{}
|
||||
}
|
||||
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
cfg := DefaultConfig()
|
||||
if err := cf.BindYaml(cfg, path, cf.DefaultOptions()); err != nil {
|
||||
return nil, errors.Wrapf(err, "error loading canary configuration '%v'", path)
|
||||
}
|
||||
if cfg.V != ConfigVersion {
|
||||
return nil, errors.Errorf("expecting canary configuration version '%v', got '%v'", ConfigVersion, cfg.V)
|
||||
}
|
||||
logrus.Info(cf.Dump(cfg, cf.DefaultOptions()))
|
||||
return cfg, nil
|
||||
}
|
13
canary/dangerous.go
Normal file
13
canary/dangerous.go
Normal file
@ -0,0 +1,13 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func AcknowledgeDangerousCanary() error {
|
||||
if _, ok := os.LookupEnv("ZROK_DANGEROUS_CANARY"); !ok {
|
||||
return fmt.Errorf("this is a dangerous canary; see canary docs for details on enabling")
|
||||
}
|
||||
return nil
|
||||
}
|
92
canary/disabler.go
Normal file
92
canary/disabler.go
Normal file
@ -0,0 +1,92 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DisablerOptions struct {
|
||||
Environments chan *sdk.Environment
|
||||
MinDwell time.Duration
|
||||
MaxDwell time.Duration
|
||||
MinPacing time.Duration
|
||||
MaxPacing time.Duration
|
||||
SnapshotQueue chan *Snapshot
|
||||
}
|
||||
|
||||
type Disabler struct {
|
||||
Id uint
|
||||
Done chan struct{}
|
||||
opt *DisablerOptions
|
||||
root env_core.Root
|
||||
}
|
||||
|
||||
func NewDisabler(id uint, opt *DisablerOptions, root env_core.Root) *Disabler {
|
||||
return &Disabler{
|
||||
Id: id,
|
||||
Done: make(chan struct{}),
|
||||
opt: opt,
|
||||
root: root,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Disabler) Run() {
|
||||
defer logrus.Infof("#%d stopping", d.Id)
|
||||
defer close(d.Done)
|
||||
d.dwell()
|
||||
d.iterate()
|
||||
}
|
||||
|
||||
func (d *Disabler) dwell() {
|
||||
dwell := d.opt.MinDwell.Milliseconds()
|
||||
dwelta := d.opt.MaxDwell.Milliseconds() - d.opt.MinDwell.Milliseconds()
|
||||
if dwelta > 0 {
|
||||
dwell = int64(rand.Intn(int(dwelta)) + int(d.opt.MinDwell.Milliseconds()))
|
||||
}
|
||||
time.Sleep(time.Duration(dwell) * time.Millisecond)
|
||||
}
|
||||
|
||||
func (d *Disabler) iterate() {
|
||||
iteration := uint64(0)
|
||||
for {
|
||||
select {
|
||||
case env, ok := <-d.opt.Environments:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
snapshot := NewSnapshot("disable", d.Id, iteration)
|
||||
iteration++
|
||||
|
||||
if err := sdk.DisableEnvironment(env, d.root); err == nil {
|
||||
snapshot.Completed = time.Now()
|
||||
snapshot.Ok = true
|
||||
|
||||
logrus.Infof("#%d disabled environment '%v'", d.Id, env.ZitiIdentity)
|
||||
|
||||
} else {
|
||||
snapshot.Completed = time.Now()
|
||||
snapshot.Ok = false
|
||||
snapshot.Error = err
|
||||
|
||||
logrus.Errorf("error disabling canary (#%d) environment '%v': %v", d.Id, env.ZitiIdentity, err)
|
||||
}
|
||||
|
||||
if d.opt.SnapshotQueue != nil {
|
||||
d.opt.SnapshotQueue <- snapshot
|
||||
} else {
|
||||
logrus.Info(snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
pacingMs := d.opt.MaxPacing.Milliseconds()
|
||||
pacingDelta := d.opt.MaxPacing.Milliseconds() - d.opt.MinPacing.Milliseconds()
|
||||
if pacingDelta > 0 {
|
||||
pacingMs = (rand.Int63() % pacingDelta) + d.opt.MinPacing.Milliseconds()
|
||||
time.Sleep(time.Duration(pacingMs) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
93
canary/enabler.go
Normal file
93
canary/enabler.go
Normal file
@ -0,0 +1,93 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type EnablerOptions struct {
|
||||
Iterations uint
|
||||
MinDwell time.Duration
|
||||
MaxDwell time.Duration
|
||||
MinPacing time.Duration
|
||||
MaxPacing time.Duration
|
||||
SnapshotQueue chan *Snapshot
|
||||
}
|
||||
|
||||
type Enabler struct {
|
||||
Id uint
|
||||
Done chan struct{}
|
||||
opt *EnablerOptions
|
||||
root env_core.Root
|
||||
Environments chan *sdk.Environment
|
||||
}
|
||||
|
||||
func NewEnabler(id uint, opt *EnablerOptions, root env_core.Root) *Enabler {
|
||||
return &Enabler{
|
||||
Id: id,
|
||||
Done: make(chan struct{}),
|
||||
opt: opt,
|
||||
root: root,
|
||||
Environments: make(chan *sdk.Environment, opt.Iterations),
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Enabler) Run() {
|
||||
defer close(e.Environments)
|
||||
defer close(e.Done)
|
||||
defer logrus.Infof("#%d stopping", e.Id)
|
||||
e.dwell()
|
||||
e.iterate()
|
||||
}
|
||||
|
||||
func (e *Enabler) dwell() {
|
||||
dwell := e.opt.MinDwell.Milliseconds()
|
||||
dwelta := e.opt.MaxDwell.Milliseconds() - e.opt.MinDwell.Milliseconds()
|
||||
if dwelta > 0 {
|
||||
dwell = int64(rand.Intn(int(dwelta)) + int(e.opt.MinDwell.Milliseconds()))
|
||||
}
|
||||
time.Sleep(time.Duration(dwell) * time.Millisecond)
|
||||
}
|
||||
|
||||
func (e *Enabler) iterate() {
|
||||
defer logrus.Info("done")
|
||||
for i := uint(0); i < e.opt.Iterations; i++ {
|
||||
snapshot := NewSnapshot("enable", e.Id, uint64(i))
|
||||
|
||||
env, err := sdk.EnableEnvironment(e.root, &sdk.EnableRequest{
|
||||
Host: fmt.Sprintf("canary_%d_%d", e.Id, i),
|
||||
Description: "canary.Enabler",
|
||||
})
|
||||
if err == nil {
|
||||
snapshot.Completed = time.Now()
|
||||
snapshot.Ok = true
|
||||
|
||||
e.Environments <- env
|
||||
logrus.Infof("#%d enabled environment '%v'", e.Id, env.ZitiIdentity)
|
||||
|
||||
} else {
|
||||
snapshot.Completed = time.Now()
|
||||
snapshot.Ok = false
|
||||
snapshot.Error = err
|
||||
|
||||
logrus.Errorf("error creating canary (#%d) environment: %v", e.Id, err)
|
||||
}
|
||||
|
||||
if e.opt.SnapshotQueue != nil {
|
||||
e.opt.SnapshotQueue <- snapshot
|
||||
} else {
|
||||
logrus.Info(snapshot)
|
||||
}
|
||||
|
||||
pacingMs := e.opt.MaxPacing.Milliseconds()
|
||||
pacingDelta := e.opt.MaxPacing.Milliseconds() - e.opt.MinPacing.Milliseconds()
|
||||
if pacingDelta > 0 {
|
||||
pacingMs = (rand.Int63() % pacingDelta) + e.opt.MinPacing.Milliseconds()
|
||||
time.Sleep(time.Duration(pacingMs) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
102
canary/metrics.go
Normal file
102
canary/metrics.go
Normal file
@ -0,0 +1,102 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
|
||||
"github.com/openziti/zrok/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"slices"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Snapshot struct {
|
||||
Operation string
|
||||
Instance uint
|
||||
Iteration uint64
|
||||
Started time.Time
|
||||
Completed time.Time
|
||||
Ok bool
|
||||
Error error
|
||||
Size uint64
|
||||
}
|
||||
|
||||
func NewSnapshot(operation string, instance uint, iteration uint64) *Snapshot {
|
||||
return &Snapshot{Operation: operation, Instance: instance, Iteration: iteration, Started: time.Now()}
|
||||
}
|
||||
|
||||
func (s *Snapshot) String() string {
|
||||
if s.Ok {
|
||||
return fmt.Sprintf("[%v, %d, %d] (ok) %v, %v", s.Operation, s.Instance, s.Iteration, s.Completed.Sub(s.Started), util.BytesToSize(int64(s.Size)))
|
||||
} else {
|
||||
return fmt.Sprintf("[%v, %d, %d] (err) %v, %v, (%v)", s.Operation, s.Instance, s.Iteration, s.Completed.Sub(s.Started), util.BytesToSize(int64(s.Size)), s.Error)
|
||||
}
|
||||
}
|
||||
|
||||
type SnapshotCollector struct {
|
||||
InputQueue chan *Snapshot
|
||||
Closed chan struct{}
|
||||
ctx context.Context
|
||||
cfg *Config
|
||||
snapshots map[string][]*Snapshot
|
||||
}
|
||||
|
||||
func NewSnapshotCollector(ctx context.Context, cfg *Config) *SnapshotCollector {
|
||||
return &SnapshotCollector{
|
||||
InputQueue: make(chan *Snapshot),
|
||||
Closed: make(chan struct{}),
|
||||
ctx: ctx,
|
||||
cfg: cfg,
|
||||
snapshots: make(map[string][]*Snapshot),
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *SnapshotCollector) Run() {
|
||||
defer close(sc.Closed)
|
||||
defer logrus.Info("stopping")
|
||||
logrus.Info("starting")
|
||||
for {
|
||||
select {
|
||||
case <-sc.ctx.Done():
|
||||
return
|
||||
|
||||
case snapshot := <-sc.InputQueue:
|
||||
var snapshots []*Snapshot
|
||||
if v, ok := sc.snapshots[snapshot.Operation]; ok {
|
||||
snapshots = v
|
||||
}
|
||||
i := sort.Search(len(snapshots), func(i int) bool { return snapshots[i].Completed.After(snapshot.Started) })
|
||||
snapshots = slices.Insert(snapshots, i, snapshot)
|
||||
sc.snapshots[snapshot.Operation] = snapshots
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *SnapshotCollector) Store() error {
|
||||
idb := influxdb2.NewClient(sc.cfg.Influx.Url, sc.cfg.Influx.Token)
|
||||
writeApi := idb.WriteAPIBlocking(sc.cfg.Influx.Org, sc.cfg.Influx.Bucket)
|
||||
for key, arr := range sc.snapshots {
|
||||
for _, snapshot := range arr {
|
||||
tags := map[string]string{
|
||||
"instance": fmt.Sprintf("%d", snapshot.Instance),
|
||||
"iteration": fmt.Sprintf("%d", snapshot.Iteration),
|
||||
"ok": fmt.Sprintf("%t", snapshot.Ok),
|
||||
}
|
||||
if snapshot.Error != nil {
|
||||
tags["error"] = snapshot.Error.Error()
|
||||
}
|
||||
pt := influxdb2.NewPoint(snapshot.Operation, tags, map[string]interface{}{
|
||||
"duration": snapshot.Completed.Sub(snapshot.Started).Milliseconds(),
|
||||
"size": snapshot.Size,
|
||||
}, snapshot.Started)
|
||||
if err := writeApi.WritePoint(context.Background(), pt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
logrus.Infof("wrote '%v' points for '%v'", len(arr), key)
|
||||
}
|
||||
idb.Close()
|
||||
logrus.Infof("complete")
|
||||
return nil
|
||||
}
|
40
cmd/zrok/adminUnbootstrap.go
Normal file
40
cmd/zrok/adminUnbootstrap.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/michaelquigley/cf"
|
||||
"github.com/openziti/zrok/controller"
|
||||
"github.com/openziti/zrok/controller/config"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
adminCmd.AddCommand(newAdminUnbootstrap().cmd)
|
||||
}
|
||||
|
||||
type adminUnbootstrap struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func newAdminUnbootstrap() *adminUnbootstrap {
|
||||
cmd := &cobra.Command{
|
||||
Use: "unbootstrap <configPath>",
|
||||
Short: "Unbootstrap the underlying Ziti network from zrok",
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
command := &adminUnbootstrap{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *adminUnbootstrap) run(_ *cobra.Command, args []string) {
|
||||
cfg, err := config.LoadConfig(args[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infof(cf.Dump(cfg, cf.DefaultOptions()))
|
||||
if err := controller.Unbootstrap(cfg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infof("unbootstrap complete!")
|
||||
}
|
143
cmd/zrok/testCanaryEnabler.go
Normal file
143
cmd/zrok/testCanaryEnabler.go
Normal file
@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openziti/zrok/canary"
|
||||
"github.com/openziti/zrok/environment"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testCanaryCmd.AddCommand(newTestCanaryEnabler().cmd)
|
||||
}
|
||||
|
||||
type testCanaryEnabler struct {
|
||||
cmd *cobra.Command
|
||||
enablers uint
|
||||
iterations uint
|
||||
minPreDelay time.Duration
|
||||
maxPreDelay time.Duration
|
||||
minDwell time.Duration
|
||||
maxDwell time.Duration
|
||||
minPacing time.Duration
|
||||
maxPacing time.Duration
|
||||
skipDisable bool
|
||||
canaryConfig string
|
||||
}
|
||||
|
||||
func newTestCanaryEnabler() *testCanaryEnabler {
|
||||
cmd := &cobra.Command{
|
||||
Use: "enabler",
|
||||
Short: "Enable a canary enabling environments",
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
command := &testCanaryEnabler{cmd: cmd}
|
||||
cmd.Run = command.run
|
||||
cmd.Flags().UintVarP(&command.enablers, "enablers", "e", 1, "Number of concurrent enablers to start")
|
||||
cmd.Flags().UintVarP(&command.iterations, "iterations", "i", 1, "Number of iterations")
|
||||
cmd.Flags().DurationVar(&command.minDwell, "min-dwell", 0, "Minimum dwell time")
|
||||
cmd.Flags().DurationVar(&command.maxDwell, "max-dwell", 0, "Maximum dwell time")
|
||||
cmd.Flags().DurationVar(&command.minPacing, "min-pacing", 0, "Minimum pacing time")
|
||||
cmd.Flags().DurationVar(&command.maxPacing, "max-pacing", 0, "Maximum pacing time")
|
||||
cmd.Flags().BoolVar(&command.skipDisable, "skip-disable", false, "Disable (clean up) enabled environments")
|
||||
cmd.Flags().StringVar(&command.canaryConfig, "canary-config", "", "Path to canary configuration file")
|
||||
return command
|
||||
}
|
||||
|
||||
func (cmd *testCanaryEnabler) run(_ *cobra.Command, _ []string) {
|
||||
if err := canary.AcknowledgeDangerousCanary(); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
root, err := environment.LoadRoot()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var sc *canary.SnapshotCollector
|
||||
var scCtx context.Context
|
||||
var scCancel context.CancelFunc
|
||||
if cmd.canaryConfig != "" {
|
||||
cfg, err := canary.LoadConfig(cmd.canaryConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
scCtx, scCancel = context.WithCancel(context.Background())
|
||||
sc = canary.NewSnapshotCollector(scCtx, cfg)
|
||||
go sc.Run()
|
||||
}
|
||||
|
||||
var enablers []*canary.Enabler
|
||||
for i := uint(0); i < cmd.enablers; i++ {
|
||||
preDelay := cmd.maxPreDelay.Milliseconds()
|
||||
preDelayDelta := cmd.maxPreDelay.Milliseconds() - cmd.minPreDelay.Milliseconds()
|
||||
if preDelayDelta > 0 {
|
||||
preDelay = int64(rand.Intn(int(preDelayDelta))) + cmd.minPreDelay.Milliseconds()
|
||||
time.Sleep(time.Duration(preDelay) * time.Millisecond)
|
||||
}
|
||||
|
||||
enablerOpts := &canary.EnablerOptions{
|
||||
Iterations: cmd.iterations,
|
||||
MinDwell: cmd.minDwell,
|
||||
MaxDwell: cmd.maxDwell,
|
||||
MinPacing: cmd.minPacing,
|
||||
MaxPacing: cmd.maxPacing,
|
||||
}
|
||||
if sc != nil {
|
||||
enablerOpts.SnapshotQueue = sc.InputQueue
|
||||
}
|
||||
enabler := canary.NewEnabler(i, enablerOpts, root)
|
||||
enablers = append(enablers, enabler)
|
||||
go enabler.Run()
|
||||
}
|
||||
|
||||
if !cmd.skipDisable {
|
||||
var disablers []*canary.Disabler
|
||||
for i := uint(0); i < cmd.enablers; i++ {
|
||||
disablerOpts := &canary.DisablerOptions{
|
||||
Environments: enablers[i].Environments,
|
||||
}
|
||||
if sc != nil {
|
||||
disablerOpts.SnapshotQueue = sc.InputQueue
|
||||
}
|
||||
disabler := canary.NewDisabler(i, disablerOpts, root)
|
||||
disablers = append(disablers, disabler)
|
||||
go disabler.Run()
|
||||
}
|
||||
for _, disabler := range disablers {
|
||||
logrus.Infof("waiting for disabler #%d", disabler.Id)
|
||||
<-disabler.Done
|
||||
}
|
||||
|
||||
} else {
|
||||
for _, enabler := range enablers {
|
||||
enablerLoop:
|
||||
for {
|
||||
select {
|
||||
case env, ok := <-enabler.Environments:
|
||||
if !ok {
|
||||
break enablerLoop
|
||||
}
|
||||
logrus.Infof("enabler #%d: %v", enabler.Id, env.ZitiIdentity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, enabler := range enablers {
|
||||
<-enabler.Done
|
||||
}
|
||||
|
||||
if sc != nil {
|
||||
scCancel()
|
||||
<-sc.Closed
|
||||
if err := sc.Store(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Infof("complete")
|
||||
}
|
@ -38,6 +38,7 @@ type Config struct {
|
||||
type AdminConfig struct {
|
||||
Secrets []string `cf:"+secret"`
|
||||
TouLink string
|
||||
NewAccountLink string
|
||||
ProfileEndpoint string
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ func (ch *configurationHandler) Handle(_ metadata.ConfigurationParams) middlewar
|
||||
}
|
||||
if cfg.Admin != nil {
|
||||
data.TouLink = cfg.Admin.TouLink
|
||||
data.NewAccountLink = cfg.Admin.NewAccountLink
|
||||
}
|
||||
if cfg.Invites != nil {
|
||||
data.InviteTokenContact = cfg.Invites.TokenContact
|
||||
|
284
controller/unbootstrap.go
Normal file
284
controller/unbootstrap.go
Normal file
@ -0,0 +1,284 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openziti/edge-api/rest_management_api_client"
|
||||
apiConfig "github.com/openziti/edge-api/rest_management_api_client/config"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/edge_router_policy"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/identity"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/service"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/service_edge_router_policy"
|
||||
"github.com/openziti/edge-api/rest_management_api_client/service_policy"
|
||||
"github.com/openziti/zrok/controller/config"
|
||||
"github.com/openziti/zrok/controller/zrokEdgeSdk"
|
||||
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Unbootstrap(cfg *config.Config) error {
|
||||
edge, err := zrokEdgeSdk.Client(cfg.Ziti)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := unbootstrapServiceEdgeRouterPolicies(edge); err != nil {
|
||||
logrus.Errorf("error unbootstrapping service edge router policies: %v", err)
|
||||
}
|
||||
if err := unbootstrapServicePolicies(edge); err != nil {
|
||||
logrus.Errorf("error unbootstrapping service policies: %v", err)
|
||||
}
|
||||
if err := unbootstrapConfigs(edge); err != nil {
|
||||
logrus.Errorf("error unbootrapping configs: %v", err)
|
||||
}
|
||||
if err := unbootstrapServices(edge); err != nil {
|
||||
logrus.Errorf("error unbootstrapping services: %v", err)
|
||||
}
|
||||
if err := unbootstrapEdgeRouterPolicies(edge); err != nil {
|
||||
logrus.Errorf("error unbootstrapping edge router policies: %v", err)
|
||||
}
|
||||
if err := unbootstrapIdentities(edge); err != nil {
|
||||
logrus.Errorf("error unbootstrapping identities: %v", err)
|
||||
}
|
||||
if err := unbootstrapConfigType(edge); err != nil {
|
||||
logrus.Errorf("error unbootstrapping config type: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapServiceEdgeRouterPolicies(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := "tags.zrok != null"
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &service_edge_router_policy.ListServiceEdgeRouterPoliciesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.ServiceEdgeRouterPolicy.ListServiceEdgeRouterPolicies(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, serp := range listResp.Payload.Data {
|
||||
delReq := &service_edge_router_policy.DeleteServiceEdgeRouterPolicyParams{
|
||||
ID: *serp.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.ServiceEdgeRouterPolicy.DeleteServiceEdgeRouterPolicy(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted service edge router policy '%v'", *serp.ID)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapServicePolicies(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := "tags.zrok != null"
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &service_policy.ListServicePoliciesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.ServicePolicy.ListServicePolicies(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, sp := range listResp.Payload.Data {
|
||||
delReq := &service_policy.DeleteServicePolicyParams{
|
||||
ID: *sp.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.ServicePolicy.DeleteServicePolicy(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted service policy '%v'", *sp.ID)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapServices(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := "tags.zrok != null"
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &service.ListServicesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.Service.ListServices(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, svc := range listResp.Payload.Data {
|
||||
delReq := &service.DeleteServiceParams{
|
||||
ID: *svc.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.Service.DeleteService(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted service '%v' (%v)", *svc.ID, *svc.Name)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapEdgeRouterPolicies(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := "tags.zrok != null"
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &edge_router_policy.ListEdgeRouterPoliciesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.EdgeRouterPolicy.ListEdgeRouterPolicies(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, erp := range listResp.Payload.Data {
|
||||
delReq := &edge_router_policy.DeleteEdgeRouterPolicyParams{
|
||||
ID: *erp.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.EdgeRouterPolicy.DeleteEdgeRouterPolicy(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted edge router policy '%v'", *erp.ID)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapIdentities(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := "tags.zrok != null"
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &identity.ListIdentitiesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.Identity.ListIdentities(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, i := range listResp.Payload.Data {
|
||||
delReq := &identity.DeleteIdentityParams{
|
||||
ID: *i.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.Identity.DeleteIdentity(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted identity '%v' (%v)", *i.ID, *i.Name)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapConfigs(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := "tags.zrok != null"
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &apiConfig.ListConfigsParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.Config.ListConfigs(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, listCfg := range listResp.Payload.Data {
|
||||
delReq := &apiConfig.DeleteConfigParams{
|
||||
ID: *listCfg.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.Config.DeleteConfig(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted config '%v'", *listCfg.ID)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unbootstrapConfigType(edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||
for {
|
||||
filter := fmt.Sprintf("name = \"%v\"", sdk.ZrokProxyConfig)
|
||||
limit := int64(100)
|
||||
offset := int64(0)
|
||||
listReq := &apiConfig.ListConfigTypesParams{
|
||||
Filter: &filter,
|
||||
Limit: &limit,
|
||||
Offset: &offset,
|
||||
Context: context.Background(),
|
||||
}
|
||||
listResp, err := edge.Config.ListConfigTypes(listReq, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(listResp.Payload.Data) < 1 {
|
||||
break
|
||||
}
|
||||
for _, listCfgType := range listResp.Payload.Data {
|
||||
delReq := &apiConfig.DeleteConfigTypeParams{
|
||||
ID: *listCfgType.ID,
|
||||
Context: context.Background(),
|
||||
}
|
||||
_, err := edge.Config.DeleteConfigType(delReq, nil)
|
||||
if err == nil {
|
||||
logrus.Infof("deleted config type '%v' (%v)", *listCfgType.ID, *listCfgType.Name)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
# this builds docker.io/openziti/zrok
|
||||
FROM docker.io/openziti/ziti-cli:1.3.3
|
||||
FROM docker.io/openziti/ziti-cli:1.4.3
|
||||
|
||||
ARG ARTIFACTS_DIR=./dist
|
||||
ARG DOCKER_BUILD_DIR=.
|
||||
|
@ -1,4 +1,6 @@
|
||||
|
||||
This formula is maintained by the Homebrew community.
|
||||
|
||||
```text
|
||||
brew install zrok
|
||||
```
|
||||
|
@ -19,7 +19,7 @@ import DownloadCardStyles from '@site/src/css/download-card.module.css';
|
||||
<DownloadCard
|
||||
osName="Linux"
|
||||
osLogo="/img/logo-linux.svg"
|
||||
infoText="RPM/DEB or Homebrew"
|
||||
infoText="RPM/DEB/AUR or Homebrew"
|
||||
guideLink="/docs/guides/install/linux"
|
||||
/>
|
||||
</div>
|
||||
|
@ -10,9 +10,9 @@ import AnsibleRepoSetup from './_ansible_repo_setup.yaml'
|
||||
import ConcatenateYamlSnippets from '@site/src/components/cat-yaml.jsx'
|
||||
import Homebrew from './_homebrew.mdx';
|
||||
|
||||
## Install `zrok` from the Repository
|
||||
## Package Repository
|
||||
|
||||
This will configure the system to receive DEB or RPM package updates.
|
||||
The RedHat (RPM) and Debian (DEB) packages are maintained by NetFoundry.
|
||||
|
||||
```text
|
||||
curl -sSf https://get.openziti.io/install.bash | sudo bash -s zrok
|
||||
@ -43,10 +43,6 @@ Check out [zrok frontdoor](/guides/frontdoor.mdx?os=Linux) for running `zrok` as
|
||||
|
||||
</Details>
|
||||
|
||||
## Homebrew
|
||||
|
||||
<Homebrew />
|
||||
|
||||
## Linux Binary
|
||||
|
||||
<AssetsProvider>
|
||||
@ -94,7 +90,7 @@ Download the binary distribution for your Linux distribution's architecture or r
|
||||
/ /| | | (_) | <
|
||||
/___|_| \___/|_|\_\
|
||||
|
||||
v0.4.0 [c889005]
|
||||
v1.0.0 [c889005]
|
||||
```
|
||||
|
||||
</Details>
|
||||
@ -134,3 +130,11 @@ zrok version;
|
||||
```
|
||||
|
||||
</Details>
|
||||
|
||||
## Arch User Repository
|
||||
|
||||
[An Arch User Repository (AUR) package](https://aur.archlinux.org/packages/zrok-bin) is maintained by the Arch community. As of April 2025, the AUR package includes the `zrok` CLI and [the `zrok-agent.service` systemd `--user` service](/guides/agent/linux-service.mdx).
|
||||
|
||||
## Homebrew Formula
|
||||
|
||||
<Homebrew />
|
||||
|
@ -68,7 +68,7 @@ Create a `zrok` controller configuration file in `etc/ctrl.yml`. The controller
|
||||
# /___|_| \___/|_|\_\
|
||||
# controller configuration
|
||||
|
||||
v: 3
|
||||
v: 4
|
||||
|
||||
admin:
|
||||
# generate these admin tokens from a source of randomness, e.g.
|
||||
|
32
docs/myzrok/limits.md
Normal file
32
docs/myzrok/limits.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Limits
|
||||
---
|
||||
|
||||
NetFoundry's public zrok instance implements various limits based on pricing tier,
|
||||
as well as rate limits in order to protect the service for all users.
|
||||
|
||||
### Limits on Shares, Environments, or Bandwidth
|
||||
|
||||
The number of shares, enviroments, or allowed bandwidth is based on the limits outlined within your myzrok subscription.
|
||||
These limits are defined on the [zrok pricing](https://zrok.io/pricing/) page.
|
||||
Bandwidth limitations are based on a rolling 24 hour window. Note that if you exceed the daily bandwidth of your plan,
|
||||
any running shares will be disabled, and the zrok API will prevent any new shares from being created until the bandwidth
|
||||
falls back below the 24 hour limit.
|
||||
|
||||
### Rate Limitations For Public Shares
|
||||
Public shares are subject to API rate limiting, both by IP address, as well as the individual share token.
|
||||
These limits exist to protect the zrok service so that one user does not negatively impact the experience for others.
|
||||
The rate limits for public shares are defined below:
|
||||
|
||||
#### Per IP Address
|
||||
2000 requests per 300 seconds (average of 6.66 requests per second)
|
||||
|
||||
The rate limiter will allow a burst of requests in a shorter timespan up to 2000 requests, but once the rate limit has been exceeded,
|
||||
new requests will be blocked until the request rate falls below the limit of the 300 second window.
|
||||
|
||||
#### Per Share
|
||||
7500 requests per 300 seconds from *any number of IP addresses* (average of 25 requests per second)
|
||||
|
||||
|
||||
|
||||
|
51
docs/myzrok/upgrading.md
Normal file
51
docs/myzrok/upgrading.md
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
title: Upgrading From 0.4 to 1.0
|
||||
---
|
||||
|
||||
## Upgrading an existing 0.4 environment
|
||||
If you have not already, [install the latest 1.x zrok binary](/docs/guides/install) into your environment.
|
||||
|
||||
:::note
|
||||
As of zrok `1.0.2`, the zrok rebase is automatic and the configuration will automatically be updated to the v1 API.
|
||||
No action is necessary.
|
||||
:::
|
||||
|
||||
If you are running version `1.0.0` or `1.0.1`, you can run the following to rebase your environment to use the new versioned API:
|
||||
```
|
||||
zrok rebase apiEndpoint https://api-v1.zrok.io
|
||||
```
|
||||
|
||||
Resume zrok API interactions as normal!
|
||||
|
||||
|
||||
## Trouble after upgrade?
|
||||
|
||||
If you run into any issues after upgrading your environment, first verify your zrok version and review your current zrok configuration:
|
||||
|
||||
```
|
||||
zrok version
|
||||
```
|
||||
Review the `apiEndpoint` configuration, if you are running version `1.0` or later, the `apiEndpoint` should be `https://api-v1.zrok.io`
|
||||
```
|
||||
zrok status
|
||||
```
|
||||
|
||||
If you're still having issues, we recommend you reach out to our community support team at our [zrok discourse](https://openziti.discourse.group/c/zrok/24) forum.
|
||||
|
||||
If you prefer to do a hard reset of your environment, you can also run the commands below:
|
||||
|
||||
:::warning
|
||||
Running `zrok disable` will delete any running environments or shares, and will release any reserved shares
|
||||
:::
|
||||
```
|
||||
zrok disable
|
||||
```
|
||||
|
||||
Reset the config back to the default API endpoint for the binary version
|
||||
```
|
||||
zrok config unset apiEndpoint
|
||||
```
|
||||
Create a fresh environment
|
||||
```
|
||||
zrok enable <your account token>
|
||||
```
|
@ -6,8 +6,10 @@ import (
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
"github.com/openziti/zrok/environment/env_v0_3"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const V = "v0.4"
|
||||
@ -286,6 +288,13 @@ func loadEnvironment() (*env_core.Environment, error) {
|
||||
ZitiIdentity: env.ZId,
|
||||
ApiEndpoint: env.ApiEndpoint,
|
||||
}
|
||||
if strings.HasPrefix(env.ApiEndpoint, "https://api.zrok.io") {
|
||||
out.ApiEndpoint = "https://api-v1.zrok.io"
|
||||
if err := saveEnvironment(out); err != nil {
|
||||
return nil, errors.Wrap(err, "error auto-rebasing apiEndpoint")
|
||||
}
|
||||
logrus.Info("auto-rebased 'apiEndpoint' for v1.0.x")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,15 @@ admin:
|
||||
secrets:
|
||||
- 77623cad-1847-4d6d-8ffe-37defc33c909
|
||||
#
|
||||
# If `tou_link` is present, the frontend will display the "Terms of Use" link on the login and registration forms
|
||||
# If `tou_link` is present, the API console will display the "Terms of Use" link on the login and registration forms
|
||||
#
|
||||
tou_link: '<a href="https://google.com" target="_">Terms and Conditions</a>'
|
||||
#
|
||||
# If `new_account_link` is present, the API console will inject the contents of this setting into the login form; the
|
||||
# intention is that it is used to present a "How do I get an account?" link.
|
||||
#
|
||||
new_account_link: '<a href="https://google.com" target="_">How do I get an account?</a>'
|
||||
#
|
||||
# If `profile_endpoint` is present, the controller will start a `net/http/pprof` endpoint at the specified host:port
|
||||
#
|
||||
#profile_endpoint: localhost:6060
|
||||
|
@ -23,6 +23,9 @@ type Configuration struct {
|
||||
// invites open
|
||||
InvitesOpen bool `json:"invitesOpen,omitempty"`
|
||||
|
||||
// new account link
|
||||
NewAccountLink string `json:"newAccountLink,omitempty"`
|
||||
|
||||
// requires invite token
|
||||
RequiresInviteToken bool `json:"requiresInviteToken,omitempty"`
|
||||
|
||||
|
@ -1985,6 +1985,9 @@ func init() {
|
||||
"invitesOpen": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"newAccountLink": {
|
||||
"type": "string"
|
||||
},
|
||||
"requiresInviteToken": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@ -4298,6 +4301,9 @@ func init() {
|
||||
"invitesOpen": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"newAccountLink": {
|
||||
"type": "string"
|
||||
},
|
||||
"requiresInviteToken": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
50
sdk/golang/sdk/environment.go
Normal file
50
sdk/golang/sdk/environment.go
Normal file
@ -0,0 +1,50 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/openziti/zrok/environment/env_core"
|
||||
restEnvironment "github.com/openziti/zrok/rest_client_zrok/environment"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func EnableEnvironment(root env_core.Root, request *EnableRequest) (*Environment, error) {
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create zrok client")
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().AccountToken)
|
||||
|
||||
req := restEnvironment.NewEnableParams()
|
||||
req.Body.Description = request.Description
|
||||
req.Body.Host = request.Host
|
||||
|
||||
resp, err := zrok.Environment.Enable(req, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Environment{
|
||||
Host: request.Host,
|
||||
Description: request.Description,
|
||||
ZitiIdentity: resp.Payload.Identity,
|
||||
ZitiConfig: resp.Payload.Cfg,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func DisableEnvironment(env *Environment, root env_core.Root) error {
|
||||
zrok, err := root.Client()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not create zrok client")
|
||||
}
|
||||
auth := httptransport.APIKeyAuth("X-TOKEN", "header", root.Environment().AccountToken)
|
||||
|
||||
req := restEnvironment.NewDisableParams()
|
||||
req.Body.Identity = env.ZitiIdentity
|
||||
|
||||
_, err = zrok.Environment.Disable(req, auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -2,6 +2,18 @@ package sdk
|
||||
|
||||
import "time"
|
||||
|
||||
type EnableRequest struct {
|
||||
Host string
|
||||
Description string
|
||||
}
|
||||
|
||||
type Environment struct {
|
||||
Host string
|
||||
Description string
|
||||
ZitiIdentity string
|
||||
ZitiConfig string
|
||||
}
|
||||
|
||||
type BackendMode string
|
||||
|
||||
const (
|
||||
|
@ -31,6 +31,12 @@ export interface ModelConfiguration {
|
||||
* @memberof ModelConfiguration
|
||||
*/
|
||||
touLink?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ModelConfiguration
|
||||
*/
|
||||
newAccountLink?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
@ -70,6 +76,7 @@ export function ModelConfigurationFromJSONTyped(json: any, ignoreDiscriminator:
|
||||
|
||||
'version': json['version'] == null ? undefined : json['version'],
|
||||
'touLink': json['touLink'] == null ? undefined : json['touLink'],
|
||||
'newAccountLink': json['newAccountLink'] == null ? undefined : json['newAccountLink'],
|
||||
'invitesOpen': json['invitesOpen'] == null ? undefined : json['invitesOpen'],
|
||||
'requiresInviteToken': json['requiresInviteToken'] == null ? undefined : json['requiresInviteToken'],
|
||||
'inviteTokenContact': json['inviteTokenContact'] == null ? undefined : json['inviteTokenContact'],
|
||||
@ -89,6 +96,7 @@ export function ModelConfigurationToJSONTyped(value?: ModelConfiguration | null,
|
||||
|
||||
'version': value['version'],
|
||||
'touLink': value['touLink'],
|
||||
'newAccountLink': value['newAccountLink'],
|
||||
'invitesOpen': value['invitesOpen'],
|
||||
'requiresInviteToken': value['requiresInviteToken'],
|
||||
'inviteTokenContact': value['inviteTokenContact'],
|
||||
|
@ -7,6 +7,7 @@ Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**version** | **str** | | [optional]
|
||||
**tou_link** | **str** | | [optional]
|
||||
**new_account_link** | **str** | | [optional]
|
||||
**invites_open** | **bool** | | [optional]
|
||||
**requires_invite_token** | **bool** | | [optional]
|
||||
**invite_token_contact** | **str** | | [optional]
|
||||
|
@ -37,6 +37,7 @@ class TestConfiguration(unittest.TestCase):
|
||||
return Configuration(
|
||||
version = '',
|
||||
tou_link = '',
|
||||
new_account_link = '',
|
||||
invites_open = True,
|
||||
requires_invite_token = True,
|
||||
invite_token_contact = ''
|
||||
|
@ -28,10 +28,11 @@ class Configuration(BaseModel):
|
||||
""" # noqa: E501
|
||||
version: Optional[StrictStr] = None
|
||||
tou_link: Optional[StrictStr] = Field(default=None, alias="touLink")
|
||||
new_account_link: Optional[StrictStr] = Field(default=None, alias="newAccountLink")
|
||||
invites_open: Optional[StrictBool] = Field(default=None, alias="invitesOpen")
|
||||
requires_invite_token: Optional[StrictBool] = Field(default=None, alias="requiresInviteToken")
|
||||
invite_token_contact: Optional[StrictStr] = Field(default=None, alias="inviteTokenContact")
|
||||
__properties: ClassVar[List[str]] = ["version", "touLink", "invitesOpen", "requiresInviteToken", "inviteTokenContact"]
|
||||
__properties: ClassVar[List[str]] = ["version", "touLink", "newAccountLink", "invitesOpen", "requiresInviteToken", "inviteTokenContact"]
|
||||
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@ -86,6 +87,7 @@ class Configuration(BaseModel):
|
||||
_obj = cls.model_validate({
|
||||
"version": obj.get("version"),
|
||||
"touLink": obj.get("touLink"),
|
||||
"newAccountLink": obj.get("newAccountLink"),
|
||||
"invitesOpen": obj.get("invitesOpen"),
|
||||
"requiresInviteToken": obj.get("requiresInviteToken"),
|
||||
"inviteTokenContact": obj.get("inviteTokenContact")
|
||||
|
@ -1229,6 +1229,8 @@ definitions:
|
||||
type: string
|
||||
touLink:
|
||||
type: string
|
||||
newAccountLink:
|
||||
type: string
|
||||
invitesOpen:
|
||||
type: boolean
|
||||
requiresInviteToken:
|
||||
|
@ -13,14 +13,19 @@ const Login = ({ onLogin }: LoginProps) => {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [message, setMessage] = useState("");
|
||||
const [tou, setTou] = useState(null as string);
|
||||
const [tou, setTou] = useState<string>("");
|
||||
const [newAccountLink, setNewAccountLink] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
new MetadataApi()._configuration()
|
||||
.then(d => {
|
||||
console.log("d", d);
|
||||
if(d.touLink && d.touLink.trim() !== "") {
|
||||
setTou(d.touLink);
|
||||
}
|
||||
if(d.newAccountLink && d.newAccountLink.trim() != "") {
|
||||
setNewAccountLink(d.newAccountLink)
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
@ -86,6 +91,9 @@ const Login = ({ onLogin }: LoginProps) => {
|
||||
<Box component="div" style={{ textAlign: "center" }}>
|
||||
<Link to="/forgotPassword">Forgot Password?</Link>
|
||||
</Box>
|
||||
<Box component="div" style={{ textAlign: "center" }}>
|
||||
<div dangerouslySetInnerHTML={{__html: newAccountLink}}></div>
|
||||
</Box>
|
||||
<Box component="div" style={{ textAlign: "center" }}>
|
||||
<div dangerouslySetInnerHTML={{__html: tou}}></div>
|
||||
</Box>
|
||||
|
@ -70,6 +70,9 @@ const ReleaseAccessModal = ({ close, isOpen, user, access, detail }: ReleaseAcce
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<Typography variant="body1">Would you like to release the access <code>{frontendToken}</code> ?</Typography>
|
||||
</Grid2>
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<Typography variant="h6" color="red">WARNING: This operation removes permissions and frees resources, but it does NOT terminate your <code>zrok access</code> process—you must do that manually.</Typography>
|
||||
</Grid2>
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<FormControlLabel control={<Checkbox checked={checked} onChange={toggleChecked} />} label={<p>I confirm the release of <code>{frontendToken}</code></p>} sx={{ mt: 2 }} />
|
||||
</Grid2>
|
||||
|
@ -69,7 +69,7 @@ const ReleaseEnvironmentModal = ({ close, isOpen, user, environment, detail }: R
|
||||
<Typography variant="body1">Would you like to release the environment <code>{description}</code> ?</Typography>
|
||||
</Grid2>
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<Typography variant="body1">Releasing this environment will also release any shares and accesses that are associated with it.</Typography>
|
||||
<Typography variant="h6" color="red">WARNING: Releasing this environment will also release any shares and accesses that are associated with it. This operation removes permissions and frees resources, but it does NOT terminate your <code>zrok share</code> or <code>zrok access</code> processes—you must do that manually.</Typography>
|
||||
</Grid2>
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<FormControlLabel control={<Checkbox checked={checked} onChange={toggleChecked} />} label={<p>I confirm the release of <code>{description}</code></p>} sx={{ mt: 2 }} />
|
||||
|
@ -70,6 +70,9 @@ const ReleaseShareModal = ({ close, isOpen, user, share, detail }: ReleaseShareP
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<Typography variant="body1">Would you like to release the share <code>{shareToken}</code> ?</Typography>
|
||||
</Grid2>
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<Typography variant="h6" color="red">WARNING: This operation removes permissions and frees resources, but it does NOT terminate your <code>zrok share</code> process—you must do that manually.</Typography>
|
||||
</Grid2>
|
||||
<Grid2 container sx={{ flexGrow: 1, p: 1 }} alignItems="center">
|
||||
<FormControlLabel control={<Checkbox checked={checked} onChange={toggleChecked} />} label={<p>I confirm the release of <code>{shareToken}</code></p>} sx={{ mt: 2 }} />
|
||||
</Grid2>
|
||||
|
@ -31,6 +31,12 @@ export interface ModelConfiguration {
|
||||
* @memberof ModelConfiguration
|
||||
*/
|
||||
touLink?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ModelConfiguration
|
||||
*/
|
||||
newAccountLink?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
@ -70,6 +76,7 @@ export function ModelConfigurationFromJSONTyped(json: any, ignoreDiscriminator:
|
||||
|
||||
'version': json['version'] == null ? undefined : json['version'],
|
||||
'touLink': json['touLink'] == null ? undefined : json['touLink'],
|
||||
'newAccountLink': json['newAccountLink'] == null ? undefined : json['newAccountLink'],
|
||||
'invitesOpen': json['invitesOpen'] == null ? undefined : json['invitesOpen'],
|
||||
'requiresInviteToken': json['requiresInviteToken'] == null ? undefined : json['requiresInviteToken'],
|
||||
'inviteTokenContact': json['inviteTokenContact'] == null ? undefined : json['inviteTokenContact'],
|
||||
@ -89,6 +96,7 @@ export function ModelConfigurationToJSONTyped(value?: ModelConfiguration | null,
|
||||
|
||||
'version': value['version'],
|
||||
'touLink': value['touLink'],
|
||||
'newAccountLink': value['newAccountLink'],
|
||||
'invitesOpen': value['invitesOpen'],
|
||||
'requiresInviteToken': value['requiresInviteToken'],
|
||||
'inviteTokenContact': value['inviteTokenContact'],
|
||||
|
4373
website/package-lock.json
generated
4373
website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,9 @@
|
||||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^3.6.0",
|
||||
"@docusaurus/plugin-client-redirects": "^3.6.0",
|
||||
"@docusaurus/preset-classic": "^3.6.0",
|
||||
"@docusaurus/core": "^3.7.0",
|
||||
"@docusaurus/plugin-client-redirects": "^3.7.0",
|
||||
"@docusaurus/preset-classic": "^3.7.0",
|
||||
"@mdx-js/react": "^3.0.1",
|
||||
"clsx": "^1.2.1",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
@ -26,7 +26,7 @@
|
||||
"remark-math": "^5.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^3.6.0",
|
||||
"@docusaurus/module-type-aliases": "^3.7.0",
|
||||
"yaml-loader": "^0.8.0"
|
||||
},
|
||||
"browserslist": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user