diff --git a/.github/workflows/fablab-db-creation.yml b/.github/workflows/fablab-db-creation.yml
new file mode 100644
index 000000000..3f1cce1e0
--- /dev/null
+++ b/.github/workflows/fablab-db-creation.yml
@@ -0,0 +1,61 @@
+name: fablab db-creation workflow
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+env:
+ GOFLAGS: "-trimpath"
+ GOX_OUTPUT: "release/{{.Arch}}/{{.OS}}/{{.Dir}}"
+ GOX_TEST_OUTPUT: "test/{{.Arch}}/{{.OS}}/bin/{{.Dir}}"
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ AWS_DEFAULT_REGION: "us-east-1"
+ gh_ci_key: ${{ secrets.GH_CI_KEY }}
+ S3_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ S3_SECRET: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+
+jobs:
+ build:
+ name: Build and Run
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout ziti
+ uses: actions/checkout@v3
+ with:
+ path: ziti
+
+ - name: Set up Go
+ uses: actions/setup-go@v3
+ with:
+ go-version: '1.20.x'
+
+ - name: Install Ziti CI
+ uses: openziti/ziti-ci@v1
+
+ - name: Configure Git
+ run: |
+ cd ziti
+ $(go env GOPATH)/bin/ziti-ci configure-git
+
+ - name: Pull ZITI_VERSION and set as $GITHUB_ENV for use with fablab
+ run: |
+ cd ziti
+ version="$($(go env GOPATH)/bin/ziti-ci -q get-current-version)"
+ echo "Ziti Version: $version"
+ echo "ZITI_VERSION=$version" >> $GITHUB_ENV
+
+ - name: Build and Run
+ run: |
+ cd ziti/zititest/models/db-creation
+ go build -o db-creation main.go
+ echo "ZITI_ROOT=$(go env GOPATH)/bin" >> "$GITHUB_ENV"
+ ./db-creation create db-creation
+ ./db-creation up
+
+ - name: Teardown
+ if: always()
+ run: |
+ cd ziti/zititest/models/db-creation
+ ./db-creation dispose
\ No newline at end of file
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 0daefead4..14b8cb154 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -27,3 +27,4 @@ Here's the list of projects using and adopting OpenZiti
| KubeZT - Zero Trust Kubernetes | https://KubeZT.com/ | | KubeZT is an on-demand Kubernetes environment that enables developers to build and deploy highly secure applications for high-compliance organizations. |
| Analytics HQ | https://AnalyticsHQ.com/ | | Analytics HQ is a next-generation unified platform built for modern data management and advanced analytics. |
| PITS Global Data Recovery Services | https://www.pitsdatarecovery.net/ | | PITS Global Data Recovery Services is a data recovery company in the United States that offers services for recovering data from hard drives, SSDs, flash drives, RAID arrays and more. |
+| KEOIC | http://www.keoic.com/ | | KEO International Consultants is a multifaceted AEC firm with a presence across the Middle East and Europe. KEO uses the CloudZiti platform to facilitate zero-trust connections for users, devices, and applications throughout their worldwide network of branch offices and sites. |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81c14be56..5c91da482 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,61 @@
+# Release 0.31.0
+
+## What's New
+
+* Rate limited for model changes
+
+## Rate Limiter for Model Changes
+
+To prevent the controller from being overwhelmed by a flood of changes, a rate limiter
+can be enabled in the configuration file. A maximum number of queued changes can also
+be configured. The rate limited is disabled by default for now. If not specified the
+default number of queued changes is 100.
+
+When the rate limit is hit, an error will be returned. If the request came in from
+the REST API, the response will use HTTP status code 429 (too many requests).
+
+The OpenAPI specs have been updated, so if you're using a generated client to make
+REST calls, it's recommened that you regenerate your client.
+
+
+```
+commandRateLimiter:
+ enabled: true
+ maxQueued: 100
+```
+
+If the rate limiter is enabled, the following metrics will be produced:
+
+* `command.limiter.queued_count` - guage of the current number of queued operations
+* `command.limiter.work_timer` - timer for operations. Includes the following:
+ * A histogram of how long operations take to complete
+ * A meter showing that rate at which operations are executed
+ * A count of how many operations have been executed
+
+## Component Updates and Bug Fixes
+
+* github.com/openziti/agent: [v1.0.15 -> v1.0.16](https://github.com/openziti/agent/compare/v1.0.15...v1.0.16)
+* github.com/openziti/channel/v2: [v2.0.101 -> v2.0.105](https://github.com/openziti/channel/compare/v2.0.101...v2.0.105)
+* github.com/openziti/edge-api: [v0.25.38 -> v0.26.0](https://github.com/openziti/edge-api/compare/v0.25.38...v0.26.0)
+ * [Issue #49](https://github.com/openziti/edge-api/issues/49) - Add 429 responses to allow indicating that the server is too busy
+
+* github.com/openziti/identity: [v1.0.64 -> v1.0.66](https://github.com/openziti/identity/compare/v1.0.64...v1.0.66)
+* github.com/openziti/metrics: [v1.2.36 -> v1.2.37](https://github.com/openziti/metrics/compare/v1.2.36...v1.2.37)
+* github.com/openziti/sdk-golang: [v0.20.122 -> v0.20.129](https://github.com/openziti/sdk-golang/compare/v0.20.122...v0.20.129)
+ * [Issue #443](https://github.com/openziti/sdk-golang/issues/443) - Don't send close in reponse to a close on a listener
+
+* github.com/openziti/secretstream: [v0.1.12 -> v0.1.13](https://github.com/openziti/secretstream/compare/v0.1.12...v0.1.13)
+* github.com/openziti/storage: [v0.2.20 -> v0.2.23](https://github.com/openziti/storage/compare/v0.2.20...v0.2.23)
+* github.com/openziti/transport/v2: [v2.0.109 -> v2.0.113](https://github.com/openziti/transport/compare/v2.0.109...v2.0.113)
+* github.com/openziti/ziti: [v0.30.5 -> v0.31.0](https://github.com/openziti/ziti/compare/v0.30.5...v0.31.0)
+ * [Issue #1471](https://github.com/openziti/ziti/issues/1471) - Router links not resilient to controller crash
+ * [Issue #1468](https://github.com/openziti/ziti/issues/1468) - Quickstart quietly fails if password is < 5 characters long
+ * [Issue #1445](https://github.com/openziti/ziti/issues/1445) - Add controller update guardrail
+ * [Issue #1442](https://github.com/openziti/ziti/issues/1442) - Network watchdog not shutting down when controller shuts down
+ * [Issue #1465](https://github.com/openziti/ziti/issues/1465) - Upgrade functions `getZiti` and `performMigration` were only functional on Mac OS, now they are functional for Linux and Mac OSs.
+ * [Issue #1217](https://github.com/openziti/ziti/issues/1217) - Quickstart was improperly handling special characters in `ZITI_PWD`. Special characters are now supported for `ZITI_PWD` in quickstart functions.
+
+
# Release 0.30.5
## What's New
@@ -11,6 +69,7 @@ Currently only HTTP Connect proxies which don't require authentication are suppo
**Example using `host.v1`**
+```
{
"address": "192.168.2.50",
"port": 1234,
@@ -20,6 +79,7 @@ Currently only HTTP Connect proxies which don't require authentication are suppo
"type": "http"
}
}
+```
## Component Updates and Bug Fixes
diff --git a/common/getziti/github.go b/common/getziti/github.go
index 229c3c445..ae7c6a787 100644
--- a/common/getziti/github.go
+++ b/common/getziti/github.go
@@ -6,6 +6,7 @@ import (
"github.com/blang/semver"
"github.com/go-resty/resty/v2"
"github.com/michaelquigley/pfxlog"
+ "github.com/openziti/foundation/v2/versions"
c "github.com/openziti/ziti/ziti/constants"
"github.com/pkg/errors"
"net/http"
@@ -177,15 +178,21 @@ func DownloadGitHubReleaseAsset(fullUrl string, filepath string) (err error) {
}
func FindVersionAndInstallGitHubRelease(zitiApp string, zitiAppGitHub string, targetOS, targetArch string, binDir string, version string, verbose bool) error {
- if version != "" {
+ releaseVersion := version
+ if version != "" && version != "latest" {
if _, err := semver.Make(strings.TrimPrefix(version, "v")); err != nil {
return err
}
} else {
version = "latest"
+ v, err := GetLatestGitHubReleaseVersion(zitiApp, verbose)
+ if err != nil {
+ return err
+ }
+ releaseVersion = v.String()
}
- release, err := GetLatestGitHubReleaseAsset(zitiApp, zitiAppGitHub, version, verbose)
+ release, err := GetLatestGitHubReleaseAsset(zitiApp, zitiAppGitHub, releaseVersion, verbose)
if err != nil {
return err
}
@@ -247,8 +254,20 @@ func InstallGitHubRelease(zitiApp string, release *GitHubReleasesData, binDir st
if zitiApp == c.ZITI {
count := 0
zitiFileName := "ziti-" + version
+ expectedPath := "ziti"
+ if version != "latest" {
+ semVer, err := versions.ParseSemVer(version)
+ if err != nil {
+ return err
+ }
+
+ pathChangedVersion := versions.MustParseSemVer("0.29.0")
+ if semVer.CompareTo(pathChangedVersion) < 0 {
+ expectedPath = "ziti/ziti"
+ }
+ }
err = UnTarGz(fullPath, binDir, func(path string) (string, bool) {
- if path == "ziti/ziti" {
+ if path == expectedPath {
count++
return zitiFileName, true
}
diff --git a/common/getziti/install_ziti.go b/common/getziti/install_ziti.go
index ecb285c2b..9ab194979 100644
--- a/common/getziti/install_ziti.go
+++ b/common/getziti/install_ziti.go
@@ -2,25 +2,11 @@ package getziti
import (
"fmt"
- "github.com/blang/semver"
c "github.com/openziti/ziti/ziti/constants"
- "strings"
)
func InstallZiti(targetVersion, targetOS, targetArch, binDir string, verbose bool) error {
- var newVersion semver.Version
-
- if targetVersion != "" {
- newVersion = semver.MustParse(strings.TrimPrefix(targetVersion, "v"))
- } else {
- v, err := GetLatestGitHubReleaseVersion(c.ZITI, verbose)
- if err != nil {
- return err
- }
- newVersion = v
- }
-
- fmt.Println("Attempting to install '" + c.ZITI + "' version: v" + newVersion.String())
+ fmt.Println("Attempting to install '" + c.ZITI + "' version: " + targetVersion)
return FindVersionAndInstallGitHubRelease(
- c.ZITI, c.ZITI, targetOS, targetArch, binDir, "v"+newVersion.String(), verbose)
+ c.ZITI, c.ZITI, targetOS, targetArch, binDir, targetVersion, verbose)
}
diff --git a/controller/api_impl/helpers.go b/controller/api_impl/helpers.go
index aef4bea38..3ac4f4ef1 100644
--- a/controller/api_impl/helpers.go
+++ b/controller/api_impl/helpers.go
@@ -4,10 +4,10 @@ import (
"fmt"
openApiErrors "github.com/go-openapi/errors"
"github.com/michaelquigley/pfxlog"
+ "github.com/openziti/foundation/v2/errorz"
"github.com/openziti/ziti/controller/api"
apierror2 "github.com/openziti/ziti/controller/apierror"
"github.com/openziti/ziti/controller/rest_model"
- "github.com/openziti/foundation/v2/errorz"
"net/http"
)
@@ -124,7 +124,7 @@ func ToRestModel(e *errorz.ApiError, requestId string) *rest_model.APIError {
ret.Code = errorz.CouldNotValidateCode
ret.Message = errorz.CouldNotValidateMessage
- } else if genericErr, ok := e.Cause.(apierror2.GenericCauseError); ok {
+ } else if genericErr, ok := e.Cause.(*apierror2.GenericCauseError); ok {
ret.Cause = &rest_model.APIErrorCause{
APIError: rest_model.APIError{
Data: genericErr.DataMap,
diff --git a/controller/apierror/api.go b/controller/apierror/api.go
index ba63676f9..ba04aa35e 100644
--- a/controller/apierror/api.go
+++ b/controller/apierror/api.go
@@ -25,7 +25,7 @@ type GenericCauseError struct {
DataMap map[string]interface{}
}
-func (e GenericCauseError) Error() string {
+func (e *GenericCauseError) Error() string {
return e.Message
}
diff --git a/controller/apierror/helpers.go b/controller/apierror/helpers.go
index 0c5274d8c..8a325b528 100644
--- a/controller/apierror/helpers.go
+++ b/controller/apierror/helpers.go
@@ -375,3 +375,11 @@ func NewEnrollmentExists(enrollmentMethod string) *errorz.ApiError {
AppendCause: true,
}
}
+
+func NewTooManyUpdatesError() *errorz.ApiError {
+ return &errorz.ApiError{
+ Code: ServerTooManyRequestsCode,
+ Message: ServerTooManyRequestsMessage,
+ Status: ServerTooManyRequestsStatus,
+ }
+}
diff --git a/controller/apierror/messages.go b/controller/apierror/messages.go
index b75622569..fdf0b21db 100644
--- a/controller/apierror/messages.go
+++ b/controller/apierror/messages.go
@@ -194,4 +194,8 @@ const (
EnrollmentExistsCode string = "ENROLLMENT_EXISTS"
EnrollmentExistsMessage string = "ENROLLMENT_EXISTS"
EnrollmentExistsStatus int = http.StatusConflict
+
+ ServerTooManyRequestsCode string = "SERVER_TOO_MANY_REQUESTS"
+ ServerTooManyRequestsMessage string = "Too many requests to alter state have been issued. Please slow your request rate or try again later."
+ ServerTooManyRequestsStatus int = http.StatusTooManyRequests
)
diff --git a/controller/command/command.go b/controller/command/command.go
index 832359bbb..c6eb26cb0 100644
--- a/controller/command/command.go
+++ b/controller/command/command.go
@@ -19,9 +19,9 @@ package command
import (
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
- "github.com/openziti/ziti/controller/change"
"github.com/openziti/foundation/v2/debugz"
"github.com/openziti/storage/boltz"
+ "github.com/openziti/ziti/controller/change"
"github.com/sirupsen/logrus"
"reflect"
)
@@ -56,6 +56,7 @@ type Dispatcher interface {
// LocalDispatcher should be used when running a non-clustered system
type LocalDispatcher struct {
EncodeDecodeCommands bool
+ Limiter RateLimiter
}
func (self *LocalDispatcher) IsLeaderOrLeaderless() bool {
@@ -82,7 +83,7 @@ func (self *LocalDispatcher) Dispatch(command Command) error {
if changeCtx == nil {
changeCtx = change.New().SetSourceType("unattributed").SetChangeAuthorType(change.AuthorTypeUnattributed)
}
- ctx := changeCtx.NewMutateContext()
+
if self.EncodeDecodeCommands {
bytes, err := command.Encode()
if err != nil {
@@ -92,10 +93,13 @@ func (self *LocalDispatcher) Dispatch(command Command) error {
if err != nil {
return err
}
- return cmd.Apply(ctx)
+ command = cmd
}
- return command.Apply(ctx)
+ return self.Limiter.RunRateLimited(func() error {
+ ctx := changeCtx.NewMutateContext()
+ return command.Apply(ctx)
+ })
}
// Decoder instances know how to decode encoded commands
diff --git a/controller/command/rate_limiter.go b/controller/command/rate_limiter.go
new file mode 100644
index 000000000..197611c67
--- /dev/null
+++ b/controller/command/rate_limiter.go
@@ -0,0 +1,129 @@
+/*
+ Copyright NetFoundry Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package command
+
+import (
+ "github.com/openziti/metrics"
+ "github.com/openziti/ziti/controller/apierror"
+ "github.com/pkg/errors"
+ "sync/atomic"
+ "time"
+)
+
+const (
+ MetricLimiterCurrentQueuedCount = "command.limiter.queued_count"
+ MetricLimiterWorkTimer = "command.limiter.work_timer"
+
+ DefaultLimiterSize = 100
+ MinLimiterSize = 10
+)
+
+type RateLimiterConfig struct {
+ Enabled bool
+ QueueSize uint32
+}
+
+func NewRateLimiter(config RateLimiterConfig, registry metrics.Registry, closeNotify <-chan struct{}) RateLimiter {
+ if !config.Enabled {
+ return NoOpRateLimiter{}
+ }
+
+ if config.QueueSize < MinLimiterSize {
+ config.QueueSize = MinLimiterSize
+ }
+
+ result := &DefaultRateLimiter{
+ queue: make(chan *rateLimitedWork, config.QueueSize),
+ closeNotify: closeNotify,
+ workRate: registry.Timer(MetricLimiterWorkTimer),
+ }
+
+ if existing := registry.GetGauge(MetricLimiterCurrentQueuedCount); existing != nil {
+ existing.Dispose()
+ }
+
+ registry.FuncGauge(MetricLimiterCurrentQueuedCount, func() int64 {
+ return int64(result.currentSize.Load())
+ })
+
+ go result.run()
+
+ return result
+}
+
+type RateLimiter interface {
+ RunRateLimited(func() error) error
+}
+
+type NoOpRateLimiter struct{}
+
+func (self NoOpRateLimiter) RunRateLimited(f func() error) error {
+ return f()
+}
+
+type rateLimitedWork struct {
+ wrapped func() error
+ result chan error
+}
+
+type DefaultRateLimiter struct {
+ currentSize atomic.Int32
+ queue chan *rateLimitedWork
+ closeNotify <-chan struct{}
+ workRate metrics.Timer
+}
+
+func (self *DefaultRateLimiter) RunRateLimited(f func() error) error {
+ work := &rateLimitedWork{
+ wrapped: f,
+ result: make(chan error, 1),
+ }
+ select {
+ case self.queue <- work:
+ self.currentSize.Add(1)
+ select {
+ case result := <-work.result:
+ return result
+ case <-self.closeNotify:
+ return errors.New("rate limiter shutting down")
+ }
+ case <-self.closeNotify:
+ return errors.New("rate limiter shutting down")
+ default:
+ return apierror.NewTooManyUpdatesError()
+ }
+}
+
+func (self *DefaultRateLimiter) run() {
+ defer self.workRate.Dispose()
+
+ for {
+ select {
+ case work := <-self.queue:
+ self.currentSize.Add(-1)
+ startTime := time.Now()
+ result := work.wrapped()
+ self.workRate.UpdateSince(startTime)
+ if result != nil {
+ work.result <- result
+ }
+ close(work.result)
+ case <-self.closeNotify:
+ return
+ }
+ }
+}
diff --git a/controller/config.go b/controller/config.go
index b3e011b69..43d6b46dc 100644
--- a/controller/config.go
+++ b/controller/config.go
@@ -24,18 +24,20 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
+ "github.com/openziti/identity"
+ "github.com/openziti/storage/boltz"
+ "github.com/openziti/transport/v2"
"github.com/openziti/ziti/common/config"
"github.com/openziti/ziti/common/pb/ctrl_pb"
"github.com/openziti/ziti/common/pb/mgmt_pb"
+ "github.com/openziti/ziti/controller/command"
"github.com/openziti/ziti/controller/db"
"github.com/openziti/ziti/controller/network"
"github.com/openziti/ziti/controller/raft"
"github.com/openziti/ziti/router/xgress"
- "github.com/openziti/identity"
- "github.com/openziti/storage/boltz"
- "github.com/openziti/transport/v2"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
+ "math"
"os"
"strings"
"time"
@@ -78,7 +80,8 @@ type Config struct {
InitialDelay time.Duration
}
}
- src map[interface{}]interface{}
+ CommandRateLimiter command.RateLimiterConfig
+ src map[interface{}]interface{}
}
// CtrlOptions extends channel.Options to include support for additional, non-channel specific options
@@ -459,6 +462,31 @@ func LoadConfig(path string) (*Config, error) {
}
}
+ controllerConfig.CommandRateLimiter.QueueSize = command.DefaultLimiterSize
+
+ if value, found := cfgmap["commandRateLimiter"]; found {
+ if submap, ok := value.(map[interface{}]interface{}); ok {
+ if value, found := submap["enabled"]; found {
+ controllerConfig.CommandRateLimiter.Enabled = strings.EqualFold("true", fmt.Sprintf("%v", value))
+ }
+
+ if value, found := submap["maxQueued"]; found {
+ if intVal, ok := value.(int); ok {
+ v := int64(intVal)
+ if v < command.MinLimiterSize {
+ return nil, errors.Errorf("invalid value %v for commandRateLimiter, must be at least %v", value, command.MinLimiterSize)
+ }
+ if v > math.MaxUint32 {
+ return nil, errors.Errorf("invalid value %v for commandRateLimiter, must be at most %v", value, int64(math.MaxUint32))
+ }
+ controllerConfig.CommandRateLimiter.QueueSize = uint32(v)
+ } else {
+ return nil, errors.Errorf("invalid value %v for commandRateLimiter, must be integer value", value)
+ }
+ }
+ }
+ }
+
return controllerConfig, nil
}
diff --git a/controller/config/config.go b/controller/config/config.go
index 59bb77840..e2662c5b7 100644
--- a/controller/config/config.go
+++ b/controller/config/config.go
@@ -19,6 +19,7 @@ package config
import (
"bytes"
"crypto/sha1"
+ "crypto/x509"
"encoding/pem"
"fmt"
"github.com/michaelquigley/pfxlog"
@@ -434,11 +435,39 @@ func CalculateCaPems(caPems *bytes.Buffer) *bytes.Buffer {
newCaPems := bytes.Buffer{}
blocksToProcess := caPems.Bytes()
+
for len(blocksToProcess) != 0 {
var block *pem.Block
block, blocksToProcess = pem.Decode(blocksToProcess)
if block != nil {
+
+ if block.Type != "CERTIFICATE" {
+ pfxlog.Logger().
+ WithField("type", block.Type).
+ WithField("block", pem.EncodeToMemory(block)).
+ Warn("encountered an invalid PEM block type loading configured CAs, block will be ignored")
+ continue
+ }
+
+ cert, err := x509.ParseCertificate(block.Bytes)
+
+ if err != nil {
+ pfxlog.Logger().
+ WithField("type", block.Type).
+ WithField("block", pem.EncodeToMemory(block)).
+ WithError(err).
+ Warn("block could not be parsed as a certificate, block will be ignored")
+ continue
+ }
+
+ if !cert.IsCA {
+ pfxlog.Logger().
+ WithField("type", block.Type).
+ WithField("block", pem.EncodeToMemory(block)).
+ Warn("block is not a CA, block will be ignored")
+ continue
+ }
// #nosec
hash := sha1.Sum(block.Bytes)
fingerprint := toHex(hash[:])
diff --git a/controller/config/config_test.go b/controller/config/config_test.go
index 3b6b82225..710fc548a 100644
--- a/controller/config/config_test.go
+++ b/controller/config/config_test.go
@@ -195,13 +195,16 @@ func Test_validateHostPortString(t *testing.T) {
}
func Test_CalculateCaPems(t *testing.T) {
- ca1, _ := newSelfSignedCert(uuid.NewString())
- ca2, _ := newSelfSignedCert(uuid.NewString())
- ca3, _ := newSelfSignedCert(uuid.NewString())
+ ca1, _ := newSelfSignedCert(uuid.NewString(), true)
+ ca2, _ := newSelfSignedCert(uuid.NewString(), true)
+ ca3, _ := newSelfSignedCert(uuid.NewString(), true)
+
+ notCaSelfSigned, _ := newSelfSignedCert(uuid.NewString(), false)
ca1Pem := nfpem.EncodeToBytes(ca1)
ca2Pem := nfpem.EncodeToBytes(ca2)
ca3Pem := nfpem.EncodeToBytes(ca3)
+ notCaSelfSignedPem := nfpem.EncodeToBytes(notCaSelfSigned)
inCas := []*x509.Certificate{
ca1,
@@ -209,6 +212,49 @@ func Test_CalculateCaPems(t *testing.T) {
ca3,
}
+ t.Run("1 non-ca in, 0 out", func(t *testing.T) {
+ req := require.New(t)
+
+ buf := bytes.NewBuffer([]byte{})
+
+ buf.Write(notCaSelfSignedPem)
+
+ outBuf := CalculateCaPems(buf)
+
+ outCerts := nfpem.PemBytesToCertificates(outBuf.Bytes())
+
+ req.Len(outCerts, 0)
+ })
+
+ t.Run("1 non-ca + 3 ca in, 3 out", func(t *testing.T) {
+ req := require.New(t)
+
+ buf := bytes.NewBuffer([]byte{})
+
+ buf.Write(notCaSelfSignedPem)
+ buf.Write(ca1Pem)
+ buf.Write(ca2Pem)
+ buf.Write(ca3Pem)
+
+ outBuf := CalculateCaPems(buf)
+
+ outCerts := nfpem.PemBytesToCertificates(outBuf.Bytes())
+
+ req.Len(outCerts, 3)
+
+ for _, inCert := range inCas {
+ found := false
+ for _, outCert := range outCerts {
+ if bytes.Equal(inCert.Raw, outCert.Raw) {
+ req.Falsef(found, "certificate %s was found multiple times, expected once instance in output", inCert.Subject.String())
+
+ found = true
+ }
+ }
+ req.Truef(found, "certificate %s was provided as input but not found as output", inCert.Subject.String())
+ }
+ })
+
t.Run("three unique CAs in, three out", func(t *testing.T) {
req := require.New(t)
@@ -315,7 +361,7 @@ func Test_CalculateCaPems(t *testing.T) {
}
-func newSelfSignedCert(commonName string) (*x509.Certificate, crypto.PrivateKey) {
+func newSelfSignedCert(commonName string, isCas bool) (*x509.Certificate, crypto.PrivateKey) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
@@ -326,14 +372,17 @@ func newSelfSignedCert(commonName string) (*x509.Certificate, crypto.PrivateKey)
CommonName: commonName,
Organization: []string{"API Test Co"},
},
- NotBefore: time.Now(),
- NotAfter: time.Now().Add(time.Hour * 24 * 180),
-
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(time.Hour * 24 * 180),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
+ if isCas {
+ template.IsCA = true
+ }
+
der, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
panic(err)
diff --git a/controller/controller.go b/controller/controller.go
index 2c8d5324f..00931edc9 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -22,12 +22,12 @@ import (
"crypto/x509"
"encoding/json"
"fmt"
+ "github.com/openziti/transport/v2"
"github.com/openziti/ziti/common/capabilities"
"github.com/openziti/ziti/common/config"
"github.com/openziti/ziti/controller/event"
"github.com/openziti/ziti/controller/events"
"github.com/openziti/ziti/controller/handler_peer_ctrl"
- "github.com/openziti/transport/v2"
"math/big"
"os"
"sync/atomic"
@@ -39,6 +39,11 @@ import (
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
"github.com/openziti/channel/v2/protobufs"
+ "github.com/openziti/foundation/v2/versions"
+ "github.com/openziti/identity"
+ "github.com/openziti/metrics"
+ "github.com/openziti/storage/boltz"
+ "github.com/openziti/xweb/v2"
"github.com/openziti/ziti/common/health"
fabricMetrics "github.com/openziti/ziti/common/metrics"
"github.com/openziti/ziti/common/pb/ctrl_pb"
@@ -55,11 +60,6 @@ import (
"github.com/openziti/ziti/controller/xt_random"
"github.com/openziti/ziti/controller/xt_smartrouting"
"github.com/openziti/ziti/controller/xt_weighted"
- "github.com/openziti/foundation/v2/versions"
- "github.com/openziti/identity"
- "github.com/openziti/metrics"
- "github.com/openziti/storage/boltz"
- "github.com/openziti/xweb/v2"
"github.com/sirupsen/logrus"
)
@@ -67,6 +67,7 @@ type Controller struct {
config *Config
network *network.Network
raftController *raft.Controller
+ localDispatcher *command.LocalDispatcher
ctrlConnectHandler *handler_ctrl.ConnectHandler
xctrls []xctrl.Xctrl
xmgmts []xmgmt.Xmgmt
@@ -113,7 +114,16 @@ func (c *Controller) GetOptions() *network.Options {
func (c *Controller) GetCommandDispatcher() command.Dispatcher {
if c.raftController == nil {
- return nil
+ if c.localDispatcher != nil {
+ return c.localDispatcher
+ }
+ devVersion := versions.MustParseSemVer("0.0.0")
+ version := versions.MustParseSemVer(c.GetVersionProvider().Version())
+ c.localDispatcher = &command.LocalDispatcher{
+ EncodeDecodeCommands: devVersion.Equals(version),
+ Limiter: command.NewRateLimiter(c.config.CommandRateLimiter, c.metricsRegistry, c.shutdownC),
+ }
+ return c.localDispatcher
}
return c.raftController
}
@@ -138,6 +148,10 @@ func (c *Controller) GetRaftConfig() *raft.Config {
return c.config.Raft
}
+func (c *Controller) GetCommandRateLimiterConfig() command.RateLimiterConfig {
+ return c.config.CommandRateLimiter
+}
+
func (c *Controller) RenderJsonConfig() (string, error) {
jsonMap, err := config.ToJsonCompatibleMap(c.config.src)
if err != nil {
diff --git a/controller/events/metrics_test.go b/controller/events/metrics_test.go
index 33de60112..09b9f70e7 100644
--- a/controller/events/metrics_test.go
+++ b/controller/events/metrics_test.go
@@ -130,6 +130,7 @@ func Test_MetricsFormat(t *testing.T) {
go func() {
registry := metrics2.NewRegistry("test", nil)
meter := registry.Meter("foo.bar")
+ time.Sleep(10 * time.Millisecond)
meter.Mark(1)
dispatcher.AcceptMetricsMsg(registry.Poll())
}()
diff --git a/controller/handler_ctrl/accept.go b/controller/handler_ctrl/accept.go
index 23bdda1ed..50b9f14c0 100644
--- a/controller/handler_ctrl/accept.go
+++ b/controller/handler_ctrl/accept.go
@@ -59,64 +59,75 @@ func (self *CtrlAccepter) Bind(binding channel.Binding) error {
ch := binding.GetChannel()
log := pfxlog.Logger().WithField("routerId", ch.Id())
-
// Use a new copy of the router instance each time we connect. That way we can tell on disconnect
// if we're working with the right connection, in case connects and disconnects happen quickly.
// It also means that the channel and connected time fields don't change and we don't have to protect them
- if r, err := self.network.GetReloadedRouter(ch.Id()); err == nil {
- if ch.Underlay().Headers() != nil {
- if versionValue, found := ch.Underlay().Headers()[channel.HelloVersionHeader]; found {
- if versionInfo, err := self.network.VersionProvider.EncoderDecoder().Decode(versionValue); err == nil {
- r.VersionInfo = versionInfo
- } else {
- return errors.Wrap(err, "could not parse version info from router hello, closing router connection")
- }
+ r, err := self.network.GetReloadedRouter(ch.Id())
+ if err != nil {
+ return err
+ }
+ if r == nil {
+ return errors.Errorf("no router with id [%v] found, closing connection", ch.Id())
+ }
+
+ if ch.Underlay().Headers() != nil {
+ if versionValue, found := ch.Underlay().Headers()[channel.HelloVersionHeader]; found {
+ if versionInfo, err := self.network.VersionProvider.EncoderDecoder().Decode(versionValue); err == nil {
+ r.VersionInfo = versionInfo
+ log = log.WithField("version", r.VersionInfo.Version).
+ WithField("revision", r.VersionInfo.Revision).
+ WithField("buildDate", r.VersionInfo.BuildDate).
+ WithField("os", r.VersionInfo.OS).
+ WithField("arch", r.VersionInfo.Arch)
} else {
- return errors.New("no version info header, closing router connection")
+ return errors.Wrap(err, "could not parse version info from router hello, not accepting router connection")
}
- r.Listeners = nil
- if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ContentType_ListenersHeader)]; found {
- log.Debug("router reported listeners using listeners header")
- listeners := &ctrl_pb.Listeners{}
- if err := proto.Unmarshal(val, listeners); err != nil {
- log.WithError(err).Error("unable to unmarshall listeners value")
- } else {
- r.SetLinkListeners(listeners.Listeners)
- for _, listener := range listeners.Listeners {
- log.WithField("address", listener.GetAddress()).
- WithField("protocol", listener.GetProtocol()).
- WithField("costTags", listener.GetCostTags()).
- Debug("router listener")
- }
- }
+ } else {
+ return errors.New("no version info header, not accepting router connection")
+ }
+
+ r.Listeners = nil
+ if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ContentType_ListenersHeader)]; found {
+ listeners := &ctrl_pb.Listeners{}
+ if err = proto.Unmarshal(val, listeners); err != nil {
+ log.WithError(err).Error("unable to unmarshall listeners value")
} else {
- log.Warn("no advertised listeners")
- }
- if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ContentType_RouterMetadataHeader)]; found {
- log.Debug("router reported listeners using listeners header")
- routerMetadata := &ctrl_pb.RouterMetadata{}
- if err = proto.Unmarshal(val, routerMetadata); err != nil {
- log.WithError(err).Error("unable to unmarshall router metadata value")
+ r.SetLinkListeners(listeners.Listeners)
+ for _, listener := range listeners.Listeners {
+ log.WithField("address", listener.GetAddress()).
+ WithField("protocol", listener.GetProtocol()).
+ WithField("costTags", listener.GetCostTags()).
+ Debug("router listener")
}
- r.SetMetadata(routerMetadata)
}
} else {
- return errors.New("no version info header, closing router connection")
- }
-
- r.Control = ch
- r.ConnectTime = time.Now()
- if err := binding.Bind(newBindHandler(self.heartbeatOptions, r, self.network, self.xctrls)); err != nil {
- return errors.Wrap(err, "error binding router")
+ log.Debug("no advertised listeners")
}
- if self.traceHandler != nil {
- binding.AddPeekHandler(self.traceHandler)
+ if val, found := ch.Underlay().Headers()[int32(ctrl_pb.ContentType_RouterMetadataHeader)]; found {
+ routerMetadata := &ctrl_pb.RouterMetadata{}
+ if err = proto.Unmarshal(val, routerMetadata); err != nil {
+ log.WithError(err).Error("unable to unmarshall router metadata value")
+ }
+ r.SetMetadata(routerMetadata)
}
+ } else {
+ return errors.New("channel provided no headers, not accepting router connection as version info not provided")
+ }
- log.Infof("accepted new router connection [r/%s]", r.Id)
+ r.Control = ch
+ r.ConnectTime = time.Now()
+ if err := binding.Bind(newBindHandler(self.heartbeatOptions, r, self.network, self.xctrls)); err != nil {
+ return errors.Wrap(err, "error binding router")
+ }
- self.network.ConnectRouter(r)
+ if self.traceHandler != nil {
+ binding.AddPeekHandler(self.traceHandler)
}
+
+ log.Info("accepted new router connection")
+
+ self.network.ConnectRouter(r)
+
return nil
}
diff --git a/controller/handler_edge_ctrl/hello.go b/controller/handler_edge_ctrl/hello.go
index 060e958af..e79ffed4e 100644
--- a/controller/handler_edge_ctrl/hello.go
+++ b/controller/handler_edge_ctrl/hello.go
@@ -21,16 +21,15 @@ import (
"github.com/openziti/channel/v2"
"github.com/openziti/ziti/common/pb/edge_ctrl_pb"
"github.com/openziti/ziti/controller/env"
- "github.com/openziti/ziti/controller/network"
"google.golang.org/protobuf/proto"
)
type helloHandler struct {
appEnv *env.AppEnv
- callback func(r *network.Router, respHello *edge_ctrl_pb.ClientHello)
+ callback func(routerId string, respHello *edge_ctrl_pb.ClientHello)
}
-func NewHelloHandler(appEnv *env.AppEnv, callback func(r *network.Router, respHello *edge_ctrl_pb.ClientHello)) *helloHandler {
+func NewHelloHandler(appEnv *env.AppEnv, callback func(routerId string, respHello *edge_ctrl_pb.ClientHello)) *helloHandler {
return &helloHandler{
appEnv: appEnv,
callback: callback,
@@ -48,12 +47,5 @@ func (h *helloHandler) HandleReceive(msg *channel.Message, ch channel.Channel) {
return
}
- r := h.appEnv.GetHostController().GetNetwork().GetConnectedRouter(ch.Id())
- if r == nil {
- pfxlog.Logger().Errorf("could not find router %v, closing channel", ch.Id())
- _ = ch.Close()
- return
- }
-
- h.callback(r, respHello)
+ h.callback(ch.Id(), respHello)
}
diff --git a/controller/handler_edge_ctrl/resync.go b/controller/handler_edge_ctrl/resync.go
index 5ac65f4aa..45401b113 100644
--- a/controller/handler_edge_ctrl/resync.go
+++ b/controller/handler_edge_ctrl/resync.go
@@ -21,16 +21,15 @@ import (
"github.com/openziti/channel/v2"
"github.com/openziti/ziti/common/pb/edge_ctrl_pb"
"github.com/openziti/ziti/controller/env"
- "github.com/openziti/ziti/controller/network"
"google.golang.org/protobuf/proto"
)
type resyncHandler struct {
appEnv *env.AppEnv
- callback func(r *network.Router, respHello *edge_ctrl_pb.RequestClientReSync)
+ callback func(routerId string, respHello *edge_ctrl_pb.RequestClientReSync)
}
-func NewResyncHandler(appEnv *env.AppEnv, callback func(r *network.Router, respHello *edge_ctrl_pb.RequestClientReSync)) *resyncHandler {
+func NewResyncHandler(appEnv *env.AppEnv, callback func(routerId string, respHello *edge_ctrl_pb.RequestClientReSync)) *resyncHandler {
return &resyncHandler{
appEnv: appEnv,
callback: callback,
@@ -48,12 +47,5 @@ func (h *resyncHandler) HandleReceive(msg *channel.Message, ch channel.Channel)
return
}
- r, err := h.appEnv.GetHostController().GetNetwork().GetRouter(ch.Id())
- if err != nil {
- pfxlog.Logger().WithError(err).Errorf("could not find router %v, closing channel", ch.Id())
- _ = ch.Close()
- return
- }
-
- h.callback(r, resyncReq)
+ h.callback(ch.Id(), resyncReq)
}
diff --git a/controller/internal/routes/version_router.go b/controller/internal/routes/version_router.go
index 7f13c920c..be613c91f 100644
--- a/controller/internal/routes/version_router.go
+++ b/controller/internal/routes/version_router.go
@@ -58,6 +58,10 @@ func (ir *VersionRouter) Register(ae *env.AppEnv) {
return ae.IsAllowed(ir.List, params.HTTPRequest, "", "", permissions.Always())
})
+ ae.ClientApi.InformationalListEnumeratedCapabilitiesHandler = clientInformational.ListEnumeratedCapabilitiesHandlerFunc(func(params clientInformational.ListEnumeratedCapabilitiesParams) middleware.Responder {
+ return ae.IsAllowed(ir.ListCapabilities, params.HTTPRequest, "", "", permissions.Always())
+ })
+
ae.ManagementApi.InformationalListVersionHandler = managementInformational.ListVersionHandlerFunc(func(params managementInformational.ListVersionParams) middleware.Responder {
return ae.IsAllowed(ir.List, params.HTTPRequest, "", "", permissions.Always())
})
@@ -65,9 +69,13 @@ func (ir *VersionRouter) Register(ae *env.AppEnv) {
ae.ManagementApi.InformationalListRootHandler = managementInformational.ListRootHandlerFunc(func(params managementInformational.ListRootParams) middleware.Responder {
return ae.IsAllowed(ir.List, params.HTTPRequest, "", "", permissions.Always())
})
+
+ ae.ManagementApi.InformationalListEnumeratedCapabilitiesHandler = managementInformational.ListEnumeratedCapabilitiesHandlerFunc(func(params managementInformational.ListEnumeratedCapabilitiesParams) middleware.Responder {
+ return ae.IsAllowed(ir.ListCapabilities, params.HTTPRequest, "", "", permissions.Always())
+ })
}
-func (ir *VersionRouter) List(_ *env.AppEnv, rc *response.RequestContext) {
+func (ir *VersionRouter) List(ae *env.AppEnv, rc *response.RequestContext) {
ir.cachedVersionsOnce.Do(func() {
buildInfo := build.GetBuildInfo()
@@ -80,6 +88,7 @@ func (ir *VersionRouter) List(_ *env.AppEnv, rc *response.RequestContext) {
controller.ClientApiBinding: {controller.VersionV1: mapApiVersionToRestModel(controller.ClientRestApiBaseUrlV1)},
controller.ManagementApiBinding: {controller.VersionV1: mapApiVersionToRestModel(controller.ManagementRestApiBaseUrlV1)},
},
+ Capabilities: []string{},
}
for apiBinding, apiVersionToPathMap := range controller.AllApiBindingVersions {
@@ -107,6 +116,21 @@ func (ir *VersionRouter) List(_ *env.AppEnv, rc *response.RequestContext) {
}
}
+ oidcEnabled := false
+
+ for _, serverConfig := range ae.HostController.GetXWebInstance().GetConfig().ServerConfigs {
+ for _, api := range serverConfig.APIs {
+ if api.Binding() == controller.OidcApiBinding {
+ oidcEnabled = true
+ break
+ }
+ }
+
+ if oidcEnabled {
+ break
+ }
+ }
+
for apiBinding, apiVersionMap := range ir.cachedVersions.APIVersions {
for apiBaseUrl := range apiToBaseUrls[apiBinding] {
apiVersion := apiVersionMap["v1"]
@@ -116,11 +140,29 @@ func (ir *VersionRouter) List(_ *env.AppEnv, rc *response.RequestContext) {
}
ir.cachedVersions.APIVersions[controller.LegacyClientApiBinding] = ir.cachedVersions.APIVersions[controller.ClientApiBinding]
+
+ if oidcEnabled {
+ ir.cachedVersions.Capabilities = append(ir.cachedVersions.Capabilities, string(rest_model.CapabilitiesOIDCAUTH))
+ }
+
+ if ae.HostController.IsRaftEnabled() {
+ ir.cachedVersions.Capabilities = append(ir.cachedVersions.Capabilities, string(rest_model.CapabilitiesHACONTROLLER))
+ }
+
})
rc.RespondWithOk(ir.cachedVersions, &rest_model.Meta{})
}
+func (ir *VersionRouter) ListCapabilities(_ *env.AppEnv, rc *response.RequestContext) {
+ capabilities := []rest_model.Capabilities{
+ rest_model.CapabilitiesOIDCAUTH,
+ rest_model.CapabilitiesHACONTROLLER,
+ }
+
+ rc.RespondWithOk(capabilities, &rest_model.Meta{})
+}
+
func apiBindingToPath(binding string) string {
switch binding {
case "edge":
diff --git a/controller/model/edge_service_manager.go b/controller/model/edge_service_manager.go
index da9171607..09c3170bd 100644
--- a/controller/model/edge_service_manager.go
+++ b/controller/model/edge_service_manager.go
@@ -18,16 +18,16 @@ package model
import (
"github.com/michaelquigley/pfxlog"
+ "github.com/openziti/storage/ast"
+ "github.com/openziti/storage/boltz"
"github.com/openziti/ziti/common/pb/edge_cmd_pb"
- "github.com/openziti/ziti/controller/persistence"
"github.com/openziti/ziti/controller/change"
"github.com/openziti/ziti/controller/command"
"github.com/openziti/ziti/controller/db"
"github.com/openziti/ziti/controller/fields"
"github.com/openziti/ziti/controller/models"
"github.com/openziti/ziti/controller/network"
- "github.com/openziti/storage/ast"
- "github.com/openziti/storage/boltz"
+ "github.com/openziti/ziti/controller/persistence"
"go.etcd.io/bbolt"
"google.golang.org/protobuf/proto"
)
diff --git a/controller/network/network.go b/controller/network/network.go
index 17196e690..4029f07b3 100644
--- a/controller/network/network.go
+++ b/controller/network/network.go
@@ -21,9 +21,9 @@ import (
"compress/gzip"
"encoding/json"
"fmt"
+ "github.com/openziti/foundation/v2/goroutines"
fabricMetrics "github.com/openziti/ziti/common/metrics"
"github.com/openziti/ziti/controller/event"
- "github.com/openziti/foundation/v2/goroutines"
"os"
"path/filepath"
"runtime/debug"
@@ -32,17 +32,11 @@ import (
"sync"
"time"
- "github.com/openziti/ziti/controller/command"
"github.com/openziti/foundation/v2/versions"
+ "github.com/openziti/ziti/controller/command"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2/protobufs"
- "github.com/openziti/ziti/common/ctrl_msg"
- "github.com/openziti/ziti/common/logcontext"
- "github.com/openziti/ziti/common/pb/ctrl_pb"
- "github.com/openziti/ziti/common/trace"
- "github.com/openziti/ziti/controller/db"
- "github.com/openziti/ziti/controller/xt"
"github.com/openziti/foundation/v2/debugz"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/foundation/v2/sequence"
@@ -50,6 +44,12 @@ import (
"github.com/openziti/metrics"
"github.com/openziti/metrics/metrics_pb"
"github.com/openziti/storage/boltz"
+ "github.com/openziti/ziti/common/ctrl_msg"
+ "github.com/openziti/ziti/common/logcontext"
+ "github.com/openziti/ziti/common/pb/ctrl_pb"
+ "github.com/openziti/ziti/common/trace"
+ "github.com/openziti/ziti/controller/db"
+ "github.com/openziti/ziti/controller/xt"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"go.etcd.io/bbolt"
@@ -909,6 +909,8 @@ func (network *Network) watchdog() {
case <-network.watchdogCh:
consecutiveFails = 0
continue
+ case <-network.closeNotify:
+ return
default:
consecutiveFails++
// network.Run didn't complete, something is stalling it
diff --git a/controller/network/network_test.go b/controller/network/network_test.go
index c63e7900e..3396f060e 100644
--- a/controller/network/network_test.go
+++ b/controller/network/network_test.go
@@ -7,16 +7,16 @@ import (
"testing"
"time"
- "github.com/openziti/ziti/controller/command"
- "github.com/openziti/ziti/controller/db"
- "github.com/openziti/ziti/controller/models"
- "github.com/openziti/ziti/controller/xt"
- "github.com/openziti/ziti/common/logcontext"
"github.com/openziti/foundation/v2/versions"
"github.com/openziti/identity"
"github.com/openziti/metrics"
"github.com/openziti/storage/boltz"
"github.com/openziti/transport/v2/tcp"
+ "github.com/openziti/ziti/common/logcontext"
+ "github.com/openziti/ziti/controller/command"
+ "github.com/openziti/ziti/controller/db"
+ "github.com/openziti/ziti/controller/models"
+ "github.com/openziti/ziti/controller/xt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -64,7 +64,9 @@ func (self *testConfig) GetOptions() *Options {
}
func (self *testConfig) GetCommandDispatcher() command.Dispatcher {
- return &command.LocalDispatcher{}
+ return &command.LocalDispatcher{
+ Limiter: command.NoOpRateLimiter{},
+ }
}
func (self *testConfig) GetDb() boltz.Db {
diff --git a/controller/persistence/testing.go b/controller/persistence/testing.go
index e30f608d9..3bd772bb1 100644
--- a/controller/persistence/testing.go
+++ b/controller/persistence/testing.go
@@ -72,7 +72,9 @@ func (self *testConfig) GetOptions() *network.Options {
}
func (self *testConfig) GetCommandDispatcher() command.Dispatcher {
- return nil
+ return &command.LocalDispatcher{
+ Limiter: command.NoOpRateLimiter{},
+ }
}
func (self *testConfig) GetDb() boltz.Db {
diff --git a/controller/raft/index_tracker_test.go b/controller/raft/index_tracker_test.go
index 695f1b74e..e159e8d8d 100644
--- a/controller/raft/index_tracker_test.go
+++ b/controller/raft/index_tracker_test.go
@@ -23,62 +23,105 @@ import (
)
func TestIndexTracker(t *testing.T) {
- indexTracker := NewIndexTracker()
-
- req := require.New(t)
- indexTracker.NotifyOfIndex(1)
- req.NoError(indexTracker.WaitForIndex(1, time.Now())) // if it's already complete, should work
-
- // If it never completes, should fail
- req.Error(indexTracker.WaitForIndex(2, time.Now().Add(20*time.Millisecond)))
-
- notifyAsync := func(index uint64, after time.Duration) {
- go func() {
- time.Sleep(after)
- indexTracker.NotifyOfIndex(index)
- }()
- }
-
- notifyAsync(2, 20*time.Millisecond)
- req.NoError(indexTracker.WaitForIndex(2, time.Now().Add(30*time.Millisecond)))
- req.NoError(indexTracker.WaitForIndex(2, time.Now()))
-
- waitAsync := func(index uint64, timeout time.Duration) <-chan error {
- result := make(chan error, 1)
- go func() {
- err := indexTracker.WaitForIndex(index, time.Now().Add(timeout))
- if err == nil {
- close(result)
+
+ t.Run("index 1 can be set and notifies", func(t *testing.T) {
+ req := require.New(t)
+ indexTracker := &testTracker{
+ NewIndexTracker(),
+ }
+
+ indexTracker.NotifyOfIndex(1)
+ req.NoError(indexTracker.WaitForIndex(1, time.Now())) // if it's already complete, should work
+
+ // If it never completes, should fail
+ req.Error(indexTracker.WaitForIndex(2, time.Now().Add(100*time.Millisecond)))
+ })
+
+ t.Run("index 2 is received. no error", func(t *testing.T) {
+ req := require.New(t)
+
+ indexTracker := &testTracker{
+ NewIndexTracker(),
+ }
+
+ indexTracker.notifyAsync(1, 20*time.Millisecond)
+ indexTracker.notifyAsync(2, 20*time.Millisecond)
+
+ req.NoError(indexTracker.WaitForIndex(2, time.Now().Add(100*time.Millisecond)))
+ req.NoError(indexTracker.WaitForIndex(2, time.Now()))
+
+ })
+
+ t.Run("index 3 has time out errors until it is added", func(t *testing.T) {
+ req := require.New(t)
+
+ indexTracker := &testTracker{
+ NewIndexTracker(),
+ }
+
+ //move the index forward 2
+ indexTracker.notifyAsync(1, 5*time.Millisecond)
+ indexTracker.notifyAsync(2, 20*time.Millisecond)
+
+ //wait for index 2 to appear
+ req.NoError(indexTracker.WaitForIndex(2, time.Now().Add(100*time.Millisecond)))
+
+ //notify of index 3 after a delay
+ //during the delay check to see if the index has arrived after varying levels of timeouts
+ indexTracker.notifyAsync(3, 200*time.Millisecond)
+
+ var results []<-chan error
+
+ //add waits for index 3 starting a 30ms and increased by 30ms till 330ms
+ for i := 0; i < 10; i++ {
+ results = append(results, indexTracker.waitAsync(3, time.Duration((i+1)*30)*time.Millisecond))
+ }
+
+ //once index3Notified is true, no timeout errors should be received
+ index3Notified := false
+
+ for _, result := range results {
+ err := <-result
+
+ if index3Notified {
+ if err != nil {
+ req.Fail("received error after first notification of index received, expected no more errors")
+ }
} else {
- result <- err
- close(result)
+ //no notification yet, if no error, that is the notification
+ if err == nil {
+ index3Notified = true
+ }
}
- }()
- return result
- }
-
- notifyAsync(3, 20*time.Millisecond)
- var results []<-chan error
- for i := 0; i < 10; i++ {
- results = append(results, waitAsync(3, 30*time.Millisecond))
- }
- req.Error(indexTracker.WaitForIndex(3, time.Now().Add(10*time.Millisecond)))
- time.Sleep(15 * time.Millisecond)
-
- for _, result := range results {
- var err error
- select {
- case err = <-result:
- default:
}
- req.NoError(err)
- closed := false
- select {
- case <-result:
- closed = true
- default:
+ //make sure we didn't receive all errors and index 3 was eventually notified
+ req.True(index3Notified, "index 3 was never received")
+ })
+}
+
+// testTracker adds helper function used to power async index notification used in the above tests.
+type testTracker struct {
+ IndexTracker
+}
+
+func (t *testTracker) notifyAsync(index uint64, after time.Duration) {
+ go func() {
+ time.Sleep(after)
+ t.NotifyOfIndex(index)
+ }()
+}
+
+func (t *testTracker) waitAsync(index uint64, timeout time.Duration) <-chan error {
+ result := make(chan error, 1)
+ go func() {
+ err := t.WaitForIndex(index, time.Now().Add(timeout))
+ if err == nil {
+ close(result)
+ } else {
+ result <- err
+ close(result)
}
- req.True(closed)
- }
+ }()
+ return result
}
diff --git a/controller/raft/raft.go b/controller/raft/raft.go
index 00dae08ea..f1b30c92c 100644
--- a/controller/raft/raft.go
+++ b/controller/raft/raft.go
@@ -21,12 +21,12 @@ import (
"encoding/json"
"fmt"
"github.com/hashicorp/go-hclog"
- "github.com/openziti/ziti/common/pb/cmd_pb"
- "github.com/openziti/ziti/controller/event"
- "github.com/openziti/ziti/controller/peermsg"
"github.com/openziti/foundation/v2/concurrenz"
"github.com/openziti/foundation/v2/versions"
"github.com/openziti/transport/v2"
+ "github.com/openziti/ziti/common/pb/cmd_pb"
+ "github.com/openziti/ziti/controller/event"
+ "github.com/openziti/ziti/controller/peermsg"
"os"
"path"
"reflect"
@@ -39,12 +39,12 @@ import (
raftboltdb "github.com/hashicorp/raft-boltdb"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
- "github.com/openziti/ziti/controller/command"
- "github.com/openziti/ziti/controller/raft/mesh"
"github.com/openziti/foundation/v2/errorz"
"github.com/openziti/identity"
"github.com/openziti/metrics"
"github.com/openziti/storage/boltz"
+ "github.com/openziti/ziti/controller/command"
+ "github.com/openziti/ziti/controller/raft/mesh"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -192,18 +192,21 @@ func newClusterState(isLeader, isReadWrite bool) ClusterState {
type Env interface {
GetId() *identity.TokenId
GetVersionProvider() versions.VersionProvider
+ GetCommandRateLimiterConfig() command.RateLimiterConfig
GetRaftConfig() *Config
GetMetricsRegistry() metrics.Registry
GetEventDispatcher() event.Dispatcher
+ GetCloseNotify() <-chan struct{}
}
func NewController(env Env, migrationMgr MigrationManager) *Controller {
result := &Controller{
- env: env,
- Config: env.GetRaftConfig(),
- indexTracker: NewIndexTracker(),
- migrationMgr: migrationMgr,
- clusterEvents: make(chan raft.Observation, 16),
+ env: env,
+ Config: env.GetRaftConfig(),
+ indexTracker: NewIndexTracker(),
+ migrationMgr: migrationMgr,
+ clusterEvents: make(chan raft.Observation, 16),
+ commandRateLimiter: command.NewRateLimiter(env.GetCommandRateLimiterConfig(), env.GetMetricsRegistry(), env.GetCloseNotify()),
}
return result
}
@@ -224,6 +227,7 @@ type Controller struct {
clusterStateChangeHandlers concurrenz.CopyOnWriteSlice[func(event ClusterEvent, state ClusterState)]
isLeader atomic.Bool
clusterEvents chan raft.Observation
+ commandRateLimiter command.RateLimiter
}
func (self *Controller) RegisterClusterEventHandler(f func(event ClusterEvent, state ClusterState)) {
@@ -448,6 +452,7 @@ func (self *Controller) applyCommand(cmd command.Command) (uint64, error) {
if err != nil {
return 0, err
}
+
return self.ApplyEncodedCommand(encoded)
}
@@ -473,11 +478,24 @@ func (self *Controller) ApplyEncodedCommand(encoded []byte) (uint64, error) {
// ApplyWithTimeout applies the given command to the RAFT distributed log with the given timeout
func (self *Controller) ApplyWithTimeout(log []byte, timeout time.Duration) (interface{}, uint64, error) {
- f := self.Raft.Apply(log, timeout)
- if err := f.Error(); err != nil {
+ returnValue := atomic.Value{}
+ index := atomic.Uint64{}
+ err := self.commandRateLimiter.RunRateLimited(func() error {
+ f := self.Raft.Apply(log, timeout)
+ if err := f.Error(); err != nil {
+ return err
+ }
+
+ returnValue.Store(f.Response())
+ index.Store(f.Index())
+ return nil
+ })
+
+ if err != nil {
return nil, 0, err
}
- return f.Response(), f.Index(), nil
+
+ return returnValue.Load(), index.Load(), nil
}
// Init sets up the Mesh and Raft instances
diff --git a/controller/response/responder.go b/controller/response/responder.go
index d598b5572..80cc3d48a 100644
--- a/controller/response/responder.go
+++ b/controller/response/responder.go
@@ -20,9 +20,9 @@ import (
"fmt"
"github.com/go-openapi/errors"
"github.com/openziti/edge-api/rest_model"
+ "github.com/openziti/foundation/v2/errorz"
"github.com/openziti/ziti/controller/api"
"github.com/openziti/ziti/controller/apierror"
- "github.com/openziti/foundation/v2/errorz"
"net/http"
)
@@ -110,7 +110,7 @@ func (self EdgeResponseMapper) toRestModel(e *errorz.ApiError, requestId string)
ret.Code = errorz.CouldNotValidateCode
ret.Message = errorz.CouldNotValidateMessage
- } else if genericErr, ok := e.Cause.(apierror.GenericCauseError); ok {
+ } else if genericErr, ok := e.Cause.(*apierror.GenericCauseError); ok {
ret.Cause = &rest_model.APIErrorCause{
APIError: rest_model.APIError{
Data: genericErr.DataMap,
diff --git a/controller/rest_client/circuit/delete_circuit_responses.go b/controller/rest_client/circuit/delete_circuit_responses.go
index f4659a81a..3f31fafdc 100644
--- a/controller/rest_client/circuit/delete_circuit_responses.go
+++ b/controller/rest_client/circuit/delete_circuit_responses.go
@@ -71,6 +71,12 @@ func (o *DeleteCircuitReader) ReadResponse(response runtime.ClientResponse, cons
return nil, err
}
return nil, result
+ case 429:
+ result := NewDeleteCircuitTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *DeleteCircuitConflict) readResponse(response runtime.ClientResponse, co
return nil
}
+
+// NewDeleteCircuitTooManyRequests creates a DeleteCircuitTooManyRequests with default headers values
+func NewDeleteCircuitTooManyRequests() *DeleteCircuitTooManyRequests {
+ return &DeleteCircuitTooManyRequests{}
+}
+
+/* DeleteCircuitTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DeleteCircuitTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DeleteCircuitTooManyRequests) Error() string {
+ return fmt.Sprintf("[DELETE /circuits/{id}][%d] deleteCircuitTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DeleteCircuitTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DeleteCircuitTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/circuit/detail_circuit_responses.go b/controller/rest_client/circuit/detail_circuit_responses.go
index e07901016..6479c48aa 100644
--- a/controller/rest_client/circuit/detail_circuit_responses.go
+++ b/controller/rest_client/circuit/detail_circuit_responses.go
@@ -65,6 +65,12 @@ func (o *DetailCircuitReader) ReadResponse(response runtime.ClientResponse, cons
return nil, err
}
return nil, result
+ case 429:
+ result := NewDetailCircuitTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *DetailCircuitNotFound) readResponse(response runtime.ClientResponse, co
return nil
}
+
+// NewDetailCircuitTooManyRequests creates a DetailCircuitTooManyRequests with default headers values
+func NewDetailCircuitTooManyRequests() *DetailCircuitTooManyRequests {
+ return &DetailCircuitTooManyRequests{}
+}
+
+/* DetailCircuitTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DetailCircuitTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DetailCircuitTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /circuits/{id}][%d] detailCircuitTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DetailCircuitTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DetailCircuitTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/circuit/list_circuits_responses.go b/controller/rest_client/circuit/list_circuits_responses.go
index 76f212d02..cbc6c4d79 100644
--- a/controller/rest_client/circuit/list_circuits_responses.go
+++ b/controller/rest_client/circuit/list_circuits_responses.go
@@ -59,6 +59,12 @@ func (o *ListCircuitsReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewListCircuitsTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *ListCircuitsUnauthorized) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewListCircuitsTooManyRequests creates a ListCircuitsTooManyRequests with default headers values
+func NewListCircuitsTooManyRequests() *ListCircuitsTooManyRequests {
+ return &ListCircuitsTooManyRequests{}
+}
+
+/* ListCircuitsTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListCircuitsTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListCircuitsTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /circuits][%d] listCircuitsTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListCircuitsTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListCircuitsTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/database/data_integrity_results_responses.go b/controller/rest_client/database/data_integrity_results_responses.go
index 04d24beee..97ae75163 100644
--- a/controller/rest_client/database/data_integrity_results_responses.go
+++ b/controller/rest_client/database/data_integrity_results_responses.go
@@ -59,6 +59,12 @@ func (o *DataIntegrityResultsReader) ReadResponse(response runtime.ClientRespons
return nil, err
}
return nil, result
+ case 429:
+ result := NewDataIntegrityResultsTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *DataIntegrityResultsUnauthorized) readResponse(response runtime.ClientR
return nil
}
+
+// NewDataIntegrityResultsTooManyRequests creates a DataIntegrityResultsTooManyRequests with default headers values
+func NewDataIntegrityResultsTooManyRequests() *DataIntegrityResultsTooManyRequests {
+ return &DataIntegrityResultsTooManyRequests{}
+}
+
+/* DataIntegrityResultsTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DataIntegrityResultsTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DataIntegrityResultsTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /database/data-integrity-results][%d] dataIntegrityResultsTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DataIntegrityResultsTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DataIntegrityResultsTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/inspect/inspect_responses.go b/controller/rest_client/inspect/inspect_responses.go
index c6b131fbc..7fb3fa117 100644
--- a/controller/rest_client/inspect/inspect_responses.go
+++ b/controller/rest_client/inspect/inspect_responses.go
@@ -59,6 +59,12 @@ func (o *InspectReader) ReadResponse(response runtime.ClientResponse, consumer r
return nil, err
}
return nil, result
+ case 429:
+ result := NewInspectTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *InspectUnauthorized) readResponse(response runtime.ClientResponse, cons
return nil
}
+
+// NewInspectTooManyRequests creates a InspectTooManyRequests with default headers values
+func NewInspectTooManyRequests() *InspectTooManyRequests {
+ return &InspectTooManyRequests{}
+}
+
+/* InspectTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type InspectTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *InspectTooManyRequests) Error() string {
+ return fmt.Sprintf("[POST /inspections][%d] inspectTooManyRequests %+v", 429, o.Payload)
+}
+func (o *InspectTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *InspectTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/link/delete_link_responses.go b/controller/rest_client/link/delete_link_responses.go
index 6a8c22e05..c11beecfa 100644
--- a/controller/rest_client/link/delete_link_responses.go
+++ b/controller/rest_client/link/delete_link_responses.go
@@ -65,6 +65,12 @@ func (o *DeleteLinkReader) ReadResponse(response runtime.ClientResponse, consume
return nil, err
}
return nil, result
+ case 429:
+ result := NewDeleteLinkTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *DeleteLinkUnauthorized) readResponse(response runtime.ClientResponse, c
return nil
}
+
+// NewDeleteLinkTooManyRequests creates a DeleteLinkTooManyRequests with default headers values
+func NewDeleteLinkTooManyRequests() *DeleteLinkTooManyRequests {
+ return &DeleteLinkTooManyRequests{}
+}
+
+/* DeleteLinkTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DeleteLinkTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DeleteLinkTooManyRequests) Error() string {
+ return fmt.Sprintf("[DELETE /links/{id}][%d] deleteLinkTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DeleteLinkTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DeleteLinkTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/link/detail_link_responses.go b/controller/rest_client/link/detail_link_responses.go
index 03d427fb7..5959fc74e 100644
--- a/controller/rest_client/link/detail_link_responses.go
+++ b/controller/rest_client/link/detail_link_responses.go
@@ -65,6 +65,12 @@ func (o *DetailLinkReader) ReadResponse(response runtime.ClientResponse, consume
return nil, err
}
return nil, result
+ case 429:
+ result := NewDetailLinkTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *DetailLinkNotFound) readResponse(response runtime.ClientResponse, consu
return nil
}
+
+// NewDetailLinkTooManyRequests creates a DetailLinkTooManyRequests with default headers values
+func NewDetailLinkTooManyRequests() *DetailLinkTooManyRequests {
+ return &DetailLinkTooManyRequests{}
+}
+
+/* DetailLinkTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DetailLinkTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DetailLinkTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /links/{id}][%d] detailLinkTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DetailLinkTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DetailLinkTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/link/list_links_responses.go b/controller/rest_client/link/list_links_responses.go
index 93820d150..886059738 100644
--- a/controller/rest_client/link/list_links_responses.go
+++ b/controller/rest_client/link/list_links_responses.go
@@ -59,6 +59,12 @@ func (o *ListLinksReader) ReadResponse(response runtime.ClientResponse, consumer
return nil, err
}
return nil, result
+ case 429:
+ result := NewListLinksTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *ListLinksUnauthorized) readResponse(response runtime.ClientResponse, co
return nil
}
+
+// NewListLinksTooManyRequests creates a ListLinksTooManyRequests with default headers values
+func NewListLinksTooManyRequests() *ListLinksTooManyRequests {
+ return &ListLinksTooManyRequests{}
+}
+
+/* ListLinksTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListLinksTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListLinksTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /links][%d] listLinksTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListLinksTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListLinksTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/link/patch_link_responses.go b/controller/rest_client/link/patch_link_responses.go
index 7a14d0875..41dab6794 100644
--- a/controller/rest_client/link/patch_link_responses.go
+++ b/controller/rest_client/link/patch_link_responses.go
@@ -71,6 +71,12 @@ func (o *PatchLinkReader) ReadResponse(response runtime.ClientResponse, consumer
return nil, err
}
return nil, result
+ case 429:
+ result := NewPatchLinkTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *PatchLinkNotFound) readResponse(response runtime.ClientResponse, consum
return nil
}
+
+// NewPatchLinkTooManyRequests creates a PatchLinkTooManyRequests with default headers values
+func NewPatchLinkTooManyRequests() *PatchLinkTooManyRequests {
+ return &PatchLinkTooManyRequests{}
+}
+
+/* PatchLinkTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type PatchLinkTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *PatchLinkTooManyRequests) Error() string {
+ return fmt.Sprintf("[PATCH /links/{id}][%d] patchLinkTooManyRequests %+v", 429, o.Payload)
+}
+func (o *PatchLinkTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *PatchLinkTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/raft/raft_list_members_responses.go b/controller/rest_client/raft/raft_list_members_responses.go
index 09d41bc3f..6c8d87092 100644
--- a/controller/rest_client/raft/raft_list_members_responses.go
+++ b/controller/rest_client/raft/raft_list_members_responses.go
@@ -59,6 +59,12 @@ func (o *RaftListMembersReader) ReadResponse(response runtime.ClientResponse, co
return nil, err
}
return nil, result
+ case 429:
+ result := NewRaftListMembersTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *RaftListMembersUnauthorized) readResponse(response runtime.ClientRespon
return nil
}
+
+// NewRaftListMembersTooManyRequests creates a RaftListMembersTooManyRequests with default headers values
+func NewRaftListMembersTooManyRequests() *RaftListMembersTooManyRequests {
+ return &RaftListMembersTooManyRequests{}
+}
+
+/* RaftListMembersTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type RaftListMembersTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *RaftListMembersTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /raft/list-members][%d] raftListMembersTooManyRequests %+v", 429, o.Payload)
+}
+func (o *RaftListMembersTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *RaftListMembersTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/create_router_responses.go b/controller/rest_client/router/create_router_responses.go
index 2c2d7a8f1..67122ed22 100644
--- a/controller/rest_client/router/create_router_responses.go
+++ b/controller/rest_client/router/create_router_responses.go
@@ -65,6 +65,12 @@ func (o *CreateRouterReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewCreateRouterTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *CreateRouterUnauthorized) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewCreateRouterTooManyRequests creates a CreateRouterTooManyRequests with default headers values
+func NewCreateRouterTooManyRequests() *CreateRouterTooManyRequests {
+ return &CreateRouterTooManyRequests{}
+}
+
+/* CreateRouterTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type CreateRouterTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *CreateRouterTooManyRequests) Error() string {
+ return fmt.Sprintf("[POST /routers][%d] createRouterTooManyRequests %+v", 429, o.Payload)
+}
+func (o *CreateRouterTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *CreateRouterTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/delete_router_responses.go b/controller/rest_client/router/delete_router_responses.go
index e55e3ba7d..46cfbcccc 100644
--- a/controller/rest_client/router/delete_router_responses.go
+++ b/controller/rest_client/router/delete_router_responses.go
@@ -71,6 +71,12 @@ func (o *DeleteRouterReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewDeleteRouterTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *DeleteRouterConflict) readResponse(response runtime.ClientResponse, con
return nil
}
+
+// NewDeleteRouterTooManyRequests creates a DeleteRouterTooManyRequests with default headers values
+func NewDeleteRouterTooManyRequests() *DeleteRouterTooManyRequests {
+ return &DeleteRouterTooManyRequests{}
+}
+
+/* DeleteRouterTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DeleteRouterTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DeleteRouterTooManyRequests) Error() string {
+ return fmt.Sprintf("[DELETE /routers/{id}][%d] deleteRouterTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DeleteRouterTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DeleteRouterTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/detail_router_responses.go b/controller/rest_client/router/detail_router_responses.go
index 3d30fe573..84815d9ad 100644
--- a/controller/rest_client/router/detail_router_responses.go
+++ b/controller/rest_client/router/detail_router_responses.go
@@ -65,6 +65,12 @@ func (o *DetailRouterReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewDetailRouterTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *DetailRouterNotFound) readResponse(response runtime.ClientResponse, con
return nil
}
+
+// NewDetailRouterTooManyRequests creates a DetailRouterTooManyRequests with default headers values
+func NewDetailRouterTooManyRequests() *DetailRouterTooManyRequests {
+ return &DetailRouterTooManyRequests{}
+}
+
+/* DetailRouterTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DetailRouterTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DetailRouterTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /routers/{id}][%d] detailRouterTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DetailRouterTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DetailRouterTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/list_router_terminators_responses.go b/controller/rest_client/router/list_router_terminators_responses.go
index 939368597..7e059859f 100644
--- a/controller/rest_client/router/list_router_terminators_responses.go
+++ b/controller/rest_client/router/list_router_terminators_responses.go
@@ -65,6 +65,12 @@ func (o *ListRouterTerminatorsReader) ReadResponse(response runtime.ClientRespon
return nil, err
}
return nil, result
+ case 429:
+ result := NewListRouterTerminatorsTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *ListRouterTerminatorsUnauthorized) readResponse(response runtime.Client
return nil
}
+
+// NewListRouterTerminatorsTooManyRequests creates a ListRouterTerminatorsTooManyRequests with default headers values
+func NewListRouterTerminatorsTooManyRequests() *ListRouterTerminatorsTooManyRequests {
+ return &ListRouterTerminatorsTooManyRequests{}
+}
+
+/* ListRouterTerminatorsTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListRouterTerminatorsTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListRouterTerminatorsTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /routers/{id}/terminators][%d] listRouterTerminatorsTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListRouterTerminatorsTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListRouterTerminatorsTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/list_routers_responses.go b/controller/rest_client/router/list_routers_responses.go
index 2d9cfa2bf..f23ed5aa9 100644
--- a/controller/rest_client/router/list_routers_responses.go
+++ b/controller/rest_client/router/list_routers_responses.go
@@ -59,6 +59,12 @@ func (o *ListRoutersReader) ReadResponse(response runtime.ClientResponse, consum
return nil, err
}
return nil, result
+ case 429:
+ result := NewListRoutersTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *ListRoutersUnauthorized) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewListRoutersTooManyRequests creates a ListRoutersTooManyRequests with default headers values
+func NewListRoutersTooManyRequests() *ListRoutersTooManyRequests {
+ return &ListRoutersTooManyRequests{}
+}
+
+/* ListRoutersTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListRoutersTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListRoutersTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /routers][%d] listRoutersTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListRoutersTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListRoutersTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/patch_router_responses.go b/controller/rest_client/router/patch_router_responses.go
index 249cb52cb..5a062da9b 100644
--- a/controller/rest_client/router/patch_router_responses.go
+++ b/controller/rest_client/router/patch_router_responses.go
@@ -71,6 +71,12 @@ func (o *PatchRouterReader) ReadResponse(response runtime.ClientResponse, consum
return nil, err
}
return nil, result
+ case 429:
+ result := NewPatchRouterTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *PatchRouterNotFound) readResponse(response runtime.ClientResponse, cons
return nil
}
+
+// NewPatchRouterTooManyRequests creates a PatchRouterTooManyRequests with default headers values
+func NewPatchRouterTooManyRequests() *PatchRouterTooManyRequests {
+ return &PatchRouterTooManyRequests{}
+}
+
+/* PatchRouterTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type PatchRouterTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *PatchRouterTooManyRequests) Error() string {
+ return fmt.Sprintf("[PATCH /routers/{id}][%d] patchRouterTooManyRequests %+v", 429, o.Payload)
+}
+func (o *PatchRouterTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *PatchRouterTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/router/update_router_responses.go b/controller/rest_client/router/update_router_responses.go
index e9ba48ddf..05fec1a76 100644
--- a/controller/rest_client/router/update_router_responses.go
+++ b/controller/rest_client/router/update_router_responses.go
@@ -71,6 +71,12 @@ func (o *UpdateRouterReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewUpdateRouterTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *UpdateRouterNotFound) readResponse(response runtime.ClientResponse, con
return nil
}
+
+// NewUpdateRouterTooManyRequests creates a UpdateRouterTooManyRequests with default headers values
+func NewUpdateRouterTooManyRequests() *UpdateRouterTooManyRequests {
+ return &UpdateRouterTooManyRequests{}
+}
+
+/* UpdateRouterTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type UpdateRouterTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *UpdateRouterTooManyRequests) Error() string {
+ return fmt.Sprintf("[PUT /routers/{id}][%d] updateRouterTooManyRequests %+v", 429, o.Payload)
+}
+func (o *UpdateRouterTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *UpdateRouterTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/create_service_responses.go b/controller/rest_client/service/create_service_responses.go
index 02114b05d..4aba359ef 100644
--- a/controller/rest_client/service/create_service_responses.go
+++ b/controller/rest_client/service/create_service_responses.go
@@ -65,6 +65,12 @@ func (o *CreateServiceReader) ReadResponse(response runtime.ClientResponse, cons
return nil, err
}
return nil, result
+ case 429:
+ result := NewCreateServiceTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *CreateServiceUnauthorized) readResponse(response runtime.ClientResponse
return nil
}
+
+// NewCreateServiceTooManyRequests creates a CreateServiceTooManyRequests with default headers values
+func NewCreateServiceTooManyRequests() *CreateServiceTooManyRequests {
+ return &CreateServiceTooManyRequests{}
+}
+
+/* CreateServiceTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type CreateServiceTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *CreateServiceTooManyRequests) Error() string {
+ return fmt.Sprintf("[POST /services][%d] createServiceTooManyRequests %+v", 429, o.Payload)
+}
+func (o *CreateServiceTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *CreateServiceTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/delete_service_responses.go b/controller/rest_client/service/delete_service_responses.go
index fa94e8e1b..ab2ecabf8 100644
--- a/controller/rest_client/service/delete_service_responses.go
+++ b/controller/rest_client/service/delete_service_responses.go
@@ -71,6 +71,12 @@ func (o *DeleteServiceReader) ReadResponse(response runtime.ClientResponse, cons
return nil, err
}
return nil, result
+ case 429:
+ result := NewDeleteServiceTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *DeleteServiceConflict) readResponse(response runtime.ClientResponse, co
return nil
}
+
+// NewDeleteServiceTooManyRequests creates a DeleteServiceTooManyRequests with default headers values
+func NewDeleteServiceTooManyRequests() *DeleteServiceTooManyRequests {
+ return &DeleteServiceTooManyRequests{}
+}
+
+/* DeleteServiceTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DeleteServiceTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DeleteServiceTooManyRequests) Error() string {
+ return fmt.Sprintf("[DELETE /services/{id}][%d] deleteServiceTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DeleteServiceTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DeleteServiceTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/detail_service_responses.go b/controller/rest_client/service/detail_service_responses.go
index 1191e69c9..e7abdf31a 100644
--- a/controller/rest_client/service/detail_service_responses.go
+++ b/controller/rest_client/service/detail_service_responses.go
@@ -65,6 +65,12 @@ func (o *DetailServiceReader) ReadResponse(response runtime.ClientResponse, cons
return nil, err
}
return nil, result
+ case 429:
+ result := NewDetailServiceTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *DetailServiceNotFound) readResponse(response runtime.ClientResponse, co
return nil
}
+
+// NewDetailServiceTooManyRequests creates a DetailServiceTooManyRequests with default headers values
+func NewDetailServiceTooManyRequests() *DetailServiceTooManyRequests {
+ return &DetailServiceTooManyRequests{}
+}
+
+/* DetailServiceTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DetailServiceTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DetailServiceTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /services/{id}][%d] detailServiceTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DetailServiceTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DetailServiceTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/list_service_terminators_responses.go b/controller/rest_client/service/list_service_terminators_responses.go
index f7480dd1e..ce483b4e6 100644
--- a/controller/rest_client/service/list_service_terminators_responses.go
+++ b/controller/rest_client/service/list_service_terminators_responses.go
@@ -65,6 +65,12 @@ func (o *ListServiceTerminatorsReader) ReadResponse(response runtime.ClientRespo
return nil, err
}
return nil, result
+ case 429:
+ result := NewListServiceTerminatorsTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *ListServiceTerminatorsUnauthorized) readResponse(response runtime.Clien
return nil
}
+
+// NewListServiceTerminatorsTooManyRequests creates a ListServiceTerminatorsTooManyRequests with default headers values
+func NewListServiceTerminatorsTooManyRequests() *ListServiceTerminatorsTooManyRequests {
+ return &ListServiceTerminatorsTooManyRequests{}
+}
+
+/* ListServiceTerminatorsTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListServiceTerminatorsTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListServiceTerminatorsTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /services/{id}/terminators][%d] listServiceTerminatorsTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListServiceTerminatorsTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListServiceTerminatorsTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/list_services_responses.go b/controller/rest_client/service/list_services_responses.go
index f9b4bb332..0cf244810 100644
--- a/controller/rest_client/service/list_services_responses.go
+++ b/controller/rest_client/service/list_services_responses.go
@@ -59,6 +59,12 @@ func (o *ListServicesReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewListServicesTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -127,3 +133,35 @@ func (o *ListServicesUnauthorized) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewListServicesTooManyRequests creates a ListServicesTooManyRequests with default headers values
+func NewListServicesTooManyRequests() *ListServicesTooManyRequests {
+ return &ListServicesTooManyRequests{}
+}
+
+/* ListServicesTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListServicesTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListServicesTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /services][%d] listServicesTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListServicesTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListServicesTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/patch_service_responses.go b/controller/rest_client/service/patch_service_responses.go
index 60010983e..c7e2812d4 100644
--- a/controller/rest_client/service/patch_service_responses.go
+++ b/controller/rest_client/service/patch_service_responses.go
@@ -71,6 +71,12 @@ func (o *PatchServiceReader) ReadResponse(response runtime.ClientResponse, consu
return nil, err
}
return nil, result
+ case 429:
+ result := NewPatchServiceTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *PatchServiceNotFound) readResponse(response runtime.ClientResponse, con
return nil
}
+
+// NewPatchServiceTooManyRequests creates a PatchServiceTooManyRequests with default headers values
+func NewPatchServiceTooManyRequests() *PatchServiceTooManyRequests {
+ return &PatchServiceTooManyRequests{}
+}
+
+/* PatchServiceTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type PatchServiceTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *PatchServiceTooManyRequests) Error() string {
+ return fmt.Sprintf("[PATCH /services/{id}][%d] patchServiceTooManyRequests %+v", 429, o.Payload)
+}
+func (o *PatchServiceTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *PatchServiceTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/service/update_service_responses.go b/controller/rest_client/service/update_service_responses.go
index d06505dad..6a5ace99d 100644
--- a/controller/rest_client/service/update_service_responses.go
+++ b/controller/rest_client/service/update_service_responses.go
@@ -71,6 +71,12 @@ func (o *UpdateServiceReader) ReadResponse(response runtime.ClientResponse, cons
return nil, err
}
return nil, result
+ case 429:
+ result := NewUpdateServiceTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *UpdateServiceNotFound) readResponse(response runtime.ClientResponse, co
return nil
}
+
+// NewUpdateServiceTooManyRequests creates a UpdateServiceTooManyRequests with default headers values
+func NewUpdateServiceTooManyRequests() *UpdateServiceTooManyRequests {
+ return &UpdateServiceTooManyRequests{}
+}
+
+/* UpdateServiceTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type UpdateServiceTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *UpdateServiceTooManyRequests) Error() string {
+ return fmt.Sprintf("[PUT /services/{id}][%d] updateServiceTooManyRequests %+v", 429, o.Payload)
+}
+func (o *UpdateServiceTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *UpdateServiceTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/terminator/create_terminator_responses.go b/controller/rest_client/terminator/create_terminator_responses.go
index 3cf6eb07d..262de8616 100644
--- a/controller/rest_client/terminator/create_terminator_responses.go
+++ b/controller/rest_client/terminator/create_terminator_responses.go
@@ -65,6 +65,12 @@ func (o *CreateTerminatorReader) ReadResponse(response runtime.ClientResponse, c
return nil, err
}
return nil, result
+ case 429:
+ result := NewCreateTerminatorTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *CreateTerminatorUnauthorized) readResponse(response runtime.ClientRespo
return nil
}
+
+// NewCreateTerminatorTooManyRequests creates a CreateTerminatorTooManyRequests with default headers values
+func NewCreateTerminatorTooManyRequests() *CreateTerminatorTooManyRequests {
+ return &CreateTerminatorTooManyRequests{}
+}
+
+/* CreateTerminatorTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type CreateTerminatorTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *CreateTerminatorTooManyRequests) Error() string {
+ return fmt.Sprintf("[POST /terminators][%d] createTerminatorTooManyRequests %+v", 429, o.Payload)
+}
+func (o *CreateTerminatorTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *CreateTerminatorTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/terminator/delete_terminator_responses.go b/controller/rest_client/terminator/delete_terminator_responses.go
index 9c312af19..c230f533f 100644
--- a/controller/rest_client/terminator/delete_terminator_responses.go
+++ b/controller/rest_client/terminator/delete_terminator_responses.go
@@ -71,6 +71,12 @@ func (o *DeleteTerminatorReader) ReadResponse(response runtime.ClientResponse, c
return nil, err
}
return nil, result
+ case 429:
+ result := NewDeleteTerminatorTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *DeleteTerminatorConflict) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewDeleteTerminatorTooManyRequests creates a DeleteTerminatorTooManyRequests with default headers values
+func NewDeleteTerminatorTooManyRequests() *DeleteTerminatorTooManyRequests {
+ return &DeleteTerminatorTooManyRequests{}
+}
+
+/* DeleteTerminatorTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DeleteTerminatorTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DeleteTerminatorTooManyRequests) Error() string {
+ return fmt.Sprintf("[DELETE /terminators/{id}][%d] deleteTerminatorTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DeleteTerminatorTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DeleteTerminatorTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/terminator/detail_terminator_responses.go b/controller/rest_client/terminator/detail_terminator_responses.go
index 2eb4cffcd..888a60d70 100644
--- a/controller/rest_client/terminator/detail_terminator_responses.go
+++ b/controller/rest_client/terminator/detail_terminator_responses.go
@@ -65,6 +65,12 @@ func (o *DetailTerminatorReader) ReadResponse(response runtime.ClientResponse, c
return nil, err
}
return nil, result
+ case 429:
+ result := NewDetailTerminatorTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *DetailTerminatorNotFound) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewDetailTerminatorTooManyRequests creates a DetailTerminatorTooManyRequests with default headers values
+func NewDetailTerminatorTooManyRequests() *DetailTerminatorTooManyRequests {
+ return &DetailTerminatorTooManyRequests{}
+}
+
+/* DetailTerminatorTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type DetailTerminatorTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *DetailTerminatorTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /terminators/{id}][%d] detailTerminatorTooManyRequests %+v", 429, o.Payload)
+}
+func (o *DetailTerminatorTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *DetailTerminatorTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/terminator/list_terminators_responses.go b/controller/rest_client/terminator/list_terminators_responses.go
index 688d3ee90..25b3488a9 100644
--- a/controller/rest_client/terminator/list_terminators_responses.go
+++ b/controller/rest_client/terminator/list_terminators_responses.go
@@ -65,6 +65,12 @@ func (o *ListTerminatorsReader) ReadResponse(response runtime.ClientResponse, co
return nil, err
}
return nil, result
+ case 429:
+ result := NewListTerminatorsTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -165,3 +171,35 @@ func (o *ListTerminatorsUnauthorized) readResponse(response runtime.ClientRespon
return nil
}
+
+// NewListTerminatorsTooManyRequests creates a ListTerminatorsTooManyRequests with default headers values
+func NewListTerminatorsTooManyRequests() *ListTerminatorsTooManyRequests {
+ return &ListTerminatorsTooManyRequests{}
+}
+
+/* ListTerminatorsTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type ListTerminatorsTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *ListTerminatorsTooManyRequests) Error() string {
+ return fmt.Sprintf("[GET /terminators][%d] listTerminatorsTooManyRequests %+v", 429, o.Payload)
+}
+func (o *ListTerminatorsTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *ListTerminatorsTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/terminator/patch_terminator_responses.go b/controller/rest_client/terminator/patch_terminator_responses.go
index 6d0e76e3f..8c6e5e399 100644
--- a/controller/rest_client/terminator/patch_terminator_responses.go
+++ b/controller/rest_client/terminator/patch_terminator_responses.go
@@ -71,6 +71,12 @@ func (o *PatchTerminatorReader) ReadResponse(response runtime.ClientResponse, co
return nil, err
}
return nil, result
+ case 429:
+ result := NewPatchTerminatorTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *PatchTerminatorNotFound) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewPatchTerminatorTooManyRequests creates a PatchTerminatorTooManyRequests with default headers values
+func NewPatchTerminatorTooManyRequests() *PatchTerminatorTooManyRequests {
+ return &PatchTerminatorTooManyRequests{}
+}
+
+/* PatchTerminatorTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type PatchTerminatorTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *PatchTerminatorTooManyRequests) Error() string {
+ return fmt.Sprintf("[PATCH /terminators/{id}][%d] patchTerminatorTooManyRequests %+v", 429, o.Payload)
+}
+func (o *PatchTerminatorTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *PatchTerminatorTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_client/terminator/update_terminator_responses.go b/controller/rest_client/terminator/update_terminator_responses.go
index 09ca6b58d..b2f7e9ee4 100644
--- a/controller/rest_client/terminator/update_terminator_responses.go
+++ b/controller/rest_client/terminator/update_terminator_responses.go
@@ -71,6 +71,12 @@ func (o *UpdateTerminatorReader) ReadResponse(response runtime.ClientResponse, c
return nil, err
}
return nil, result
+ case 429:
+ result := NewUpdateTerminatorTooManyRequests()
+ if err := result.readResponse(response, consumer, o.formats); err != nil {
+ return nil, err
+ }
+ return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
@@ -203,3 +209,35 @@ func (o *UpdateTerminatorNotFound) readResponse(response runtime.ClientResponse,
return nil
}
+
+// NewUpdateTerminatorTooManyRequests creates a UpdateTerminatorTooManyRequests with default headers values
+func NewUpdateTerminatorTooManyRequests() *UpdateTerminatorTooManyRequests {
+ return &UpdateTerminatorTooManyRequests{}
+}
+
+/* UpdateTerminatorTooManyRequests describes a response with status code 429, with default header values.
+
+The resource requested is rate limited and the rate limit has been exceeded
+*/
+type UpdateTerminatorTooManyRequests struct {
+ Payload *rest_model.APIErrorEnvelope
+}
+
+func (o *UpdateTerminatorTooManyRequests) Error() string {
+ return fmt.Sprintf("[PUT /terminators/{id}][%d] updateTerminatorTooManyRequests %+v", 429, o.Payload)
+}
+func (o *UpdateTerminatorTooManyRequests) GetPayload() *rest_model.APIErrorEnvelope {
+ return o.Payload
+}
+
+func (o *UpdateTerminatorTooManyRequests) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
+
+ o.Payload = new(rest_model.APIErrorEnvelope)
+
+ // response payload
+ if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
+ return err
+ }
+
+ return nil
+}
diff --git a/controller/rest_server/embedded_spec.go b/controller/rest_server/embedded_spec.go
index 586ff3210..9872057f5 100644
--- a/controller/rest_server/embedded_spec.go
+++ b/controller/rest_server/embedded_spec.go
@@ -83,6 +83,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -104,6 +107,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -136,6 +142,9 @@ func init() {
},
"409": {
"$ref": "#/responses/cannotDeleteReferencedResourceResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -216,6 +225,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -303,6 +315,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -321,6 +336,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -342,6 +360,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -361,6 +382,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -394,6 +418,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -417,6 +444,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -446,6 +476,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -476,6 +509,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -497,6 +533,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -530,6 +569,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -552,6 +594,9 @@ func init() {
},
"409": {
"$ref": "#/responses/cannotDeleteReferencedResourceResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -585,6 +630,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -622,6 +670,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -656,6 +707,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -686,6 +740,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -707,6 +764,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -740,6 +800,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -762,6 +825,9 @@ func init() {
},
"409": {
"$ref": "#/responses/cannotDeleteReferencedResourceResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -795,6 +861,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -832,6 +901,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -869,6 +941,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -899,6 +974,9 @@ func init() {
},
"401": {
"$ref": "#/responses/unauthorizedResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
}
@@ -920,6 +998,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -953,6 +1034,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -975,6 +1059,9 @@ func init() {
},
"409": {
"$ref": "#/responses/cannotDeleteReferencedResourceResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -1008,6 +1095,9 @@ func init() {
},
"404": {
"$ref": "#/responses/notFoundResponse"
+ },
+ "429": {
+ "$ref": "#/responses/rateLimitedResponse"
}
}
},
@@ -2581,6 +2671,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -2649,6 +2762,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -2761,6 +2897,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -2957,6 +3116,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -3156,6 +3338,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -3198,6 +3403,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -3266,6 +3494,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -3343,11 +3594,34 @@ func init() {
}
}
}
- }
- }
- },
- "patch": {
- "description": "Update the supplied fields on a link. Requires admin access.",
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "patch": {
+ "description": "Update the supplied fields on a link. Requires admin access.",
"tags": [
"Link"
],
@@ -3457,6 +3731,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -3508,6 +3805,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -3567,6 +3887,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -3655,6 +3998,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -3723,6 +4089,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -3837,6 +4226,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -3939,6 +4351,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4053,6 +4488,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4158,6 +4616,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4226,6 +4707,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4314,6 +4818,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -4382,6 +4909,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4496,6 +5046,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4598,6 +5171,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4712,6 +5308,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4817,6 +5436,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -4922,6 +5564,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -5010,6 +5675,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
}
@@ -5078,6 +5766,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -5192,6 +5903,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -5294,6 +6028,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
@@ -5408,6 +6165,29 @@ func init() {
}
}
}
+ },
+ "429": {
+ "description": "The resource requested is rate limited and the rate limit has been exceeded",
+ "schema": {
+ "$ref": "#/definitions/apiErrorEnvelope"
+ },
+ "examples": {
+ "application/json": {
+ "error": {
+ "args": {
+ "urlVars": {}
+ },
+ "causeMessage": "you have hit a rate limit in the requested operation",
+ "code": "RATE_LIMITED",
+ "message": "The resource is rate limited and the rate limit has been exceeded. Please try again later",
+ "requestId": "270908d6-f2ef-4577-b973-67bec18ae376"
+ },
+ "meta": {
+ "apiEnrollmentVersion": "0.0.1",
+ "apiVersion": "0.0.1"
+ }
+ }
+ }
}
}
},
diff --git a/controller/rest_server/operations/circuit/delete_circuit_responses.go b/controller/rest_server/operations/circuit/delete_circuit_responses.go
index 272f31a94..bf3cdd849 100644
--- a/controller/rest_server/operations/circuit/delete_circuit_responses.go
+++ b/controller/rest_server/operations/circuit/delete_circuit_responses.go
@@ -212,3 +212,47 @@ func (o *DeleteCircuitConflict) WriteResponse(rw http.ResponseWriter, producer r
}
}
}
+
+// DeleteCircuitTooManyRequestsCode is the HTTP code returned for type DeleteCircuitTooManyRequests
+const DeleteCircuitTooManyRequestsCode int = 429
+
+/*DeleteCircuitTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response deleteCircuitTooManyRequests
+*/
+type DeleteCircuitTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDeleteCircuitTooManyRequests creates DeleteCircuitTooManyRequests with default headers values
+func NewDeleteCircuitTooManyRequests() *DeleteCircuitTooManyRequests {
+
+ return &DeleteCircuitTooManyRequests{}
+}
+
+// WithPayload adds the payload to the delete circuit too many requests response
+func (o *DeleteCircuitTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DeleteCircuitTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the delete circuit too many requests response
+func (o *DeleteCircuitTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DeleteCircuitTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/circuit/detail_circuit_responses.go b/controller/rest_server/operations/circuit/detail_circuit_responses.go
index c67acc916..b7f7771a6 100644
--- a/controller/rest_server/operations/circuit/detail_circuit_responses.go
+++ b/controller/rest_server/operations/circuit/detail_circuit_responses.go
@@ -168,3 +168,47 @@ func (o *DetailCircuitNotFound) WriteResponse(rw http.ResponseWriter, producer r
}
}
}
+
+// DetailCircuitTooManyRequestsCode is the HTTP code returned for type DetailCircuitTooManyRequests
+const DetailCircuitTooManyRequestsCode int = 429
+
+/*DetailCircuitTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response detailCircuitTooManyRequests
+*/
+type DetailCircuitTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDetailCircuitTooManyRequests creates DetailCircuitTooManyRequests with default headers values
+func NewDetailCircuitTooManyRequests() *DetailCircuitTooManyRequests {
+
+ return &DetailCircuitTooManyRequests{}
+}
+
+// WithPayload adds the payload to the detail circuit too many requests response
+func (o *DetailCircuitTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DetailCircuitTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the detail circuit too many requests response
+func (o *DetailCircuitTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DetailCircuitTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/circuit/list_circuits_responses.go b/controller/rest_server/operations/circuit/list_circuits_responses.go
index 9ca6417ed..5cb52c325 100644
--- a/controller/rest_server/operations/circuit/list_circuits_responses.go
+++ b/controller/rest_server/operations/circuit/list_circuits_responses.go
@@ -124,3 +124,47 @@ func (o *ListCircuitsUnauthorized) WriteResponse(rw http.ResponseWriter, produce
}
}
}
+
+// ListCircuitsTooManyRequestsCode is the HTTP code returned for type ListCircuitsTooManyRequests
+const ListCircuitsTooManyRequestsCode int = 429
+
+/*ListCircuitsTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listCircuitsTooManyRequests
+*/
+type ListCircuitsTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListCircuitsTooManyRequests creates ListCircuitsTooManyRequests with default headers values
+func NewListCircuitsTooManyRequests() *ListCircuitsTooManyRequests {
+
+ return &ListCircuitsTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list circuits too many requests response
+func (o *ListCircuitsTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListCircuitsTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list circuits too many requests response
+func (o *ListCircuitsTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListCircuitsTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/database/data_integrity_results_responses.go b/controller/rest_server/operations/database/data_integrity_results_responses.go
index 11c095f4b..cd65e12e7 100644
--- a/controller/rest_server/operations/database/data_integrity_results_responses.go
+++ b/controller/rest_server/operations/database/data_integrity_results_responses.go
@@ -124,3 +124,47 @@ func (o *DataIntegrityResultsUnauthorized) WriteResponse(rw http.ResponseWriter,
}
}
}
+
+// DataIntegrityResultsTooManyRequestsCode is the HTTP code returned for type DataIntegrityResultsTooManyRequests
+const DataIntegrityResultsTooManyRequestsCode int = 429
+
+/*DataIntegrityResultsTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response dataIntegrityResultsTooManyRequests
+*/
+type DataIntegrityResultsTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDataIntegrityResultsTooManyRequests creates DataIntegrityResultsTooManyRequests with default headers values
+func NewDataIntegrityResultsTooManyRequests() *DataIntegrityResultsTooManyRequests {
+
+ return &DataIntegrityResultsTooManyRequests{}
+}
+
+// WithPayload adds the payload to the data integrity results too many requests response
+func (o *DataIntegrityResultsTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DataIntegrityResultsTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the data integrity results too many requests response
+func (o *DataIntegrityResultsTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DataIntegrityResultsTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/inspect/inspect_responses.go b/controller/rest_server/operations/inspect/inspect_responses.go
index 74a2a792e..4f9dc4bb9 100644
--- a/controller/rest_server/operations/inspect/inspect_responses.go
+++ b/controller/rest_server/operations/inspect/inspect_responses.go
@@ -124,3 +124,47 @@ func (o *InspectUnauthorized) WriteResponse(rw http.ResponseWriter, producer run
}
}
}
+
+// InspectTooManyRequestsCode is the HTTP code returned for type InspectTooManyRequests
+const InspectTooManyRequestsCode int = 429
+
+/*InspectTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response inspectTooManyRequests
+*/
+type InspectTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewInspectTooManyRequests creates InspectTooManyRequests with default headers values
+func NewInspectTooManyRequests() *InspectTooManyRequests {
+
+ return &InspectTooManyRequests{}
+}
+
+// WithPayload adds the payload to the inspect too many requests response
+func (o *InspectTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *InspectTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the inspect too many requests response
+func (o *InspectTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *InspectTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/link/delete_link_responses.go b/controller/rest_server/operations/link/delete_link_responses.go
index e426ada03..e456d57e5 100644
--- a/controller/rest_server/operations/link/delete_link_responses.go
+++ b/controller/rest_server/operations/link/delete_link_responses.go
@@ -168,3 +168,47 @@ func (o *DeleteLinkUnauthorized) WriteResponse(rw http.ResponseWriter, producer
}
}
}
+
+// DeleteLinkTooManyRequestsCode is the HTTP code returned for type DeleteLinkTooManyRequests
+const DeleteLinkTooManyRequestsCode int = 429
+
+/*DeleteLinkTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response deleteLinkTooManyRequests
+*/
+type DeleteLinkTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDeleteLinkTooManyRequests creates DeleteLinkTooManyRequests with default headers values
+func NewDeleteLinkTooManyRequests() *DeleteLinkTooManyRequests {
+
+ return &DeleteLinkTooManyRequests{}
+}
+
+// WithPayload adds the payload to the delete link too many requests response
+func (o *DeleteLinkTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DeleteLinkTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the delete link too many requests response
+func (o *DeleteLinkTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DeleteLinkTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/link/detail_link_responses.go b/controller/rest_server/operations/link/detail_link_responses.go
index 3dd6de72c..db7ebe183 100644
--- a/controller/rest_server/operations/link/detail_link_responses.go
+++ b/controller/rest_server/operations/link/detail_link_responses.go
@@ -168,3 +168,47 @@ func (o *DetailLinkNotFound) WriteResponse(rw http.ResponseWriter, producer runt
}
}
}
+
+// DetailLinkTooManyRequestsCode is the HTTP code returned for type DetailLinkTooManyRequests
+const DetailLinkTooManyRequestsCode int = 429
+
+/*DetailLinkTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response detailLinkTooManyRequests
+*/
+type DetailLinkTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDetailLinkTooManyRequests creates DetailLinkTooManyRequests with default headers values
+func NewDetailLinkTooManyRequests() *DetailLinkTooManyRequests {
+
+ return &DetailLinkTooManyRequests{}
+}
+
+// WithPayload adds the payload to the detail link too many requests response
+func (o *DetailLinkTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DetailLinkTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the detail link too many requests response
+func (o *DetailLinkTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DetailLinkTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/link/list_links_responses.go b/controller/rest_server/operations/link/list_links_responses.go
index b1b0967a8..895b27946 100644
--- a/controller/rest_server/operations/link/list_links_responses.go
+++ b/controller/rest_server/operations/link/list_links_responses.go
@@ -124,3 +124,47 @@ func (o *ListLinksUnauthorized) WriteResponse(rw http.ResponseWriter, producer r
}
}
}
+
+// ListLinksTooManyRequestsCode is the HTTP code returned for type ListLinksTooManyRequests
+const ListLinksTooManyRequestsCode int = 429
+
+/*ListLinksTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listLinksTooManyRequests
+*/
+type ListLinksTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListLinksTooManyRequests creates ListLinksTooManyRequests with default headers values
+func NewListLinksTooManyRequests() *ListLinksTooManyRequests {
+
+ return &ListLinksTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list links too many requests response
+func (o *ListLinksTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListLinksTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list links too many requests response
+func (o *ListLinksTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListLinksTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/link/patch_link_responses.go b/controller/rest_server/operations/link/patch_link_responses.go
index bcd7d81e0..704153f5c 100644
--- a/controller/rest_server/operations/link/patch_link_responses.go
+++ b/controller/rest_server/operations/link/patch_link_responses.go
@@ -212,3 +212,47 @@ func (o *PatchLinkNotFound) WriteResponse(rw http.ResponseWriter, producer runti
}
}
}
+
+// PatchLinkTooManyRequestsCode is the HTTP code returned for type PatchLinkTooManyRequests
+const PatchLinkTooManyRequestsCode int = 429
+
+/*PatchLinkTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response patchLinkTooManyRequests
+*/
+type PatchLinkTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewPatchLinkTooManyRequests creates PatchLinkTooManyRequests with default headers values
+func NewPatchLinkTooManyRequests() *PatchLinkTooManyRequests {
+
+ return &PatchLinkTooManyRequests{}
+}
+
+// WithPayload adds the payload to the patch link too many requests response
+func (o *PatchLinkTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *PatchLinkTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the patch link too many requests response
+func (o *PatchLinkTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *PatchLinkTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/raft/raft_list_members_responses.go b/controller/rest_server/operations/raft/raft_list_members_responses.go
index 7b3df864a..53822fd85 100644
--- a/controller/rest_server/operations/raft/raft_list_members_responses.go
+++ b/controller/rest_server/operations/raft/raft_list_members_responses.go
@@ -124,3 +124,47 @@ func (o *RaftListMembersUnauthorized) WriteResponse(rw http.ResponseWriter, prod
}
}
}
+
+// RaftListMembersTooManyRequestsCode is the HTTP code returned for type RaftListMembersTooManyRequests
+const RaftListMembersTooManyRequestsCode int = 429
+
+/*RaftListMembersTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response raftListMembersTooManyRequests
+*/
+type RaftListMembersTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewRaftListMembersTooManyRequests creates RaftListMembersTooManyRequests with default headers values
+func NewRaftListMembersTooManyRequests() *RaftListMembersTooManyRequests {
+
+ return &RaftListMembersTooManyRequests{}
+}
+
+// WithPayload adds the payload to the raft list members too many requests response
+func (o *RaftListMembersTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *RaftListMembersTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the raft list members too many requests response
+func (o *RaftListMembersTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *RaftListMembersTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/create_router_responses.go b/controller/rest_server/operations/router/create_router_responses.go
index 4ef55ffc0..00ffa8339 100644
--- a/controller/rest_server/operations/router/create_router_responses.go
+++ b/controller/rest_server/operations/router/create_router_responses.go
@@ -168,3 +168,47 @@ func (o *CreateRouterUnauthorized) WriteResponse(rw http.ResponseWriter, produce
}
}
}
+
+// CreateRouterTooManyRequestsCode is the HTTP code returned for type CreateRouterTooManyRequests
+const CreateRouterTooManyRequestsCode int = 429
+
+/*CreateRouterTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response createRouterTooManyRequests
+*/
+type CreateRouterTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewCreateRouterTooManyRequests creates CreateRouterTooManyRequests with default headers values
+func NewCreateRouterTooManyRequests() *CreateRouterTooManyRequests {
+
+ return &CreateRouterTooManyRequests{}
+}
+
+// WithPayload adds the payload to the create router too many requests response
+func (o *CreateRouterTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *CreateRouterTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the create router too many requests response
+func (o *CreateRouterTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CreateRouterTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/delete_router_responses.go b/controller/rest_server/operations/router/delete_router_responses.go
index c7b1ea3ed..0e245eb90 100644
--- a/controller/rest_server/operations/router/delete_router_responses.go
+++ b/controller/rest_server/operations/router/delete_router_responses.go
@@ -212,3 +212,47 @@ func (o *DeleteRouterConflict) WriteResponse(rw http.ResponseWriter, producer ru
}
}
}
+
+// DeleteRouterTooManyRequestsCode is the HTTP code returned for type DeleteRouterTooManyRequests
+const DeleteRouterTooManyRequestsCode int = 429
+
+/*DeleteRouterTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response deleteRouterTooManyRequests
+*/
+type DeleteRouterTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDeleteRouterTooManyRequests creates DeleteRouterTooManyRequests with default headers values
+func NewDeleteRouterTooManyRequests() *DeleteRouterTooManyRequests {
+
+ return &DeleteRouterTooManyRequests{}
+}
+
+// WithPayload adds the payload to the delete router too many requests response
+func (o *DeleteRouterTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DeleteRouterTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the delete router too many requests response
+func (o *DeleteRouterTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DeleteRouterTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/detail_router_responses.go b/controller/rest_server/operations/router/detail_router_responses.go
index a4f176c7b..697fdbd1f 100644
--- a/controller/rest_server/operations/router/detail_router_responses.go
+++ b/controller/rest_server/operations/router/detail_router_responses.go
@@ -168,3 +168,47 @@ func (o *DetailRouterNotFound) WriteResponse(rw http.ResponseWriter, producer ru
}
}
}
+
+// DetailRouterTooManyRequestsCode is the HTTP code returned for type DetailRouterTooManyRequests
+const DetailRouterTooManyRequestsCode int = 429
+
+/*DetailRouterTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response detailRouterTooManyRequests
+*/
+type DetailRouterTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDetailRouterTooManyRequests creates DetailRouterTooManyRequests with default headers values
+func NewDetailRouterTooManyRequests() *DetailRouterTooManyRequests {
+
+ return &DetailRouterTooManyRequests{}
+}
+
+// WithPayload adds the payload to the detail router too many requests response
+func (o *DetailRouterTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DetailRouterTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the detail router too many requests response
+func (o *DetailRouterTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DetailRouterTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/list_router_terminators_responses.go b/controller/rest_server/operations/router/list_router_terminators_responses.go
index 7ba0c1343..c17cfab3b 100644
--- a/controller/rest_server/operations/router/list_router_terminators_responses.go
+++ b/controller/rest_server/operations/router/list_router_terminators_responses.go
@@ -168,3 +168,47 @@ func (o *ListRouterTerminatorsUnauthorized) WriteResponse(rw http.ResponseWriter
}
}
}
+
+// ListRouterTerminatorsTooManyRequestsCode is the HTTP code returned for type ListRouterTerminatorsTooManyRequests
+const ListRouterTerminatorsTooManyRequestsCode int = 429
+
+/*ListRouterTerminatorsTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listRouterTerminatorsTooManyRequests
+*/
+type ListRouterTerminatorsTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListRouterTerminatorsTooManyRequests creates ListRouterTerminatorsTooManyRequests with default headers values
+func NewListRouterTerminatorsTooManyRequests() *ListRouterTerminatorsTooManyRequests {
+
+ return &ListRouterTerminatorsTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list router terminators too many requests response
+func (o *ListRouterTerminatorsTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListRouterTerminatorsTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list router terminators too many requests response
+func (o *ListRouterTerminatorsTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListRouterTerminatorsTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/list_routers_responses.go b/controller/rest_server/operations/router/list_routers_responses.go
index 3c990d4e3..1eb30d62d 100644
--- a/controller/rest_server/operations/router/list_routers_responses.go
+++ b/controller/rest_server/operations/router/list_routers_responses.go
@@ -124,3 +124,47 @@ func (o *ListRoutersUnauthorized) WriteResponse(rw http.ResponseWriter, producer
}
}
}
+
+// ListRoutersTooManyRequestsCode is the HTTP code returned for type ListRoutersTooManyRequests
+const ListRoutersTooManyRequestsCode int = 429
+
+/*ListRoutersTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listRoutersTooManyRequests
+*/
+type ListRoutersTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListRoutersTooManyRequests creates ListRoutersTooManyRequests with default headers values
+func NewListRoutersTooManyRequests() *ListRoutersTooManyRequests {
+
+ return &ListRoutersTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list routers too many requests response
+func (o *ListRoutersTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListRoutersTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list routers too many requests response
+func (o *ListRoutersTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListRoutersTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/patch_router_responses.go b/controller/rest_server/operations/router/patch_router_responses.go
index 64d96feef..8076c43d2 100644
--- a/controller/rest_server/operations/router/patch_router_responses.go
+++ b/controller/rest_server/operations/router/patch_router_responses.go
@@ -212,3 +212,47 @@ func (o *PatchRouterNotFound) WriteResponse(rw http.ResponseWriter, producer run
}
}
}
+
+// PatchRouterTooManyRequestsCode is the HTTP code returned for type PatchRouterTooManyRequests
+const PatchRouterTooManyRequestsCode int = 429
+
+/*PatchRouterTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response patchRouterTooManyRequests
+*/
+type PatchRouterTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewPatchRouterTooManyRequests creates PatchRouterTooManyRequests with default headers values
+func NewPatchRouterTooManyRequests() *PatchRouterTooManyRequests {
+
+ return &PatchRouterTooManyRequests{}
+}
+
+// WithPayload adds the payload to the patch router too many requests response
+func (o *PatchRouterTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *PatchRouterTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the patch router too many requests response
+func (o *PatchRouterTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *PatchRouterTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/router/update_router_responses.go b/controller/rest_server/operations/router/update_router_responses.go
index 0d1e53f93..62e375c7b 100644
--- a/controller/rest_server/operations/router/update_router_responses.go
+++ b/controller/rest_server/operations/router/update_router_responses.go
@@ -212,3 +212,47 @@ func (o *UpdateRouterNotFound) WriteResponse(rw http.ResponseWriter, producer ru
}
}
}
+
+// UpdateRouterTooManyRequestsCode is the HTTP code returned for type UpdateRouterTooManyRequests
+const UpdateRouterTooManyRequestsCode int = 429
+
+/*UpdateRouterTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response updateRouterTooManyRequests
+*/
+type UpdateRouterTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewUpdateRouterTooManyRequests creates UpdateRouterTooManyRequests with default headers values
+func NewUpdateRouterTooManyRequests() *UpdateRouterTooManyRequests {
+
+ return &UpdateRouterTooManyRequests{}
+}
+
+// WithPayload adds the payload to the update router too many requests response
+func (o *UpdateRouterTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *UpdateRouterTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the update router too many requests response
+func (o *UpdateRouterTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *UpdateRouterTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/create_service_responses.go b/controller/rest_server/operations/service/create_service_responses.go
index 726af8090..c27c349f3 100644
--- a/controller/rest_server/operations/service/create_service_responses.go
+++ b/controller/rest_server/operations/service/create_service_responses.go
@@ -168,3 +168,47 @@ func (o *CreateServiceUnauthorized) WriteResponse(rw http.ResponseWriter, produc
}
}
}
+
+// CreateServiceTooManyRequestsCode is the HTTP code returned for type CreateServiceTooManyRequests
+const CreateServiceTooManyRequestsCode int = 429
+
+/*CreateServiceTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response createServiceTooManyRequests
+*/
+type CreateServiceTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewCreateServiceTooManyRequests creates CreateServiceTooManyRequests with default headers values
+func NewCreateServiceTooManyRequests() *CreateServiceTooManyRequests {
+
+ return &CreateServiceTooManyRequests{}
+}
+
+// WithPayload adds the payload to the create service too many requests response
+func (o *CreateServiceTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *CreateServiceTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the create service too many requests response
+func (o *CreateServiceTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CreateServiceTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/delete_service_responses.go b/controller/rest_server/operations/service/delete_service_responses.go
index de2c0e86f..c7ce4a61a 100644
--- a/controller/rest_server/operations/service/delete_service_responses.go
+++ b/controller/rest_server/operations/service/delete_service_responses.go
@@ -212,3 +212,47 @@ func (o *DeleteServiceConflict) WriteResponse(rw http.ResponseWriter, producer r
}
}
}
+
+// DeleteServiceTooManyRequestsCode is the HTTP code returned for type DeleteServiceTooManyRequests
+const DeleteServiceTooManyRequestsCode int = 429
+
+/*DeleteServiceTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response deleteServiceTooManyRequests
+*/
+type DeleteServiceTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDeleteServiceTooManyRequests creates DeleteServiceTooManyRequests with default headers values
+func NewDeleteServiceTooManyRequests() *DeleteServiceTooManyRequests {
+
+ return &DeleteServiceTooManyRequests{}
+}
+
+// WithPayload adds the payload to the delete service too many requests response
+func (o *DeleteServiceTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DeleteServiceTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the delete service too many requests response
+func (o *DeleteServiceTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DeleteServiceTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/detail_service_responses.go b/controller/rest_server/operations/service/detail_service_responses.go
index f382a56bc..1ed31212a 100644
--- a/controller/rest_server/operations/service/detail_service_responses.go
+++ b/controller/rest_server/operations/service/detail_service_responses.go
@@ -168,3 +168,47 @@ func (o *DetailServiceNotFound) WriteResponse(rw http.ResponseWriter, producer r
}
}
}
+
+// DetailServiceTooManyRequestsCode is the HTTP code returned for type DetailServiceTooManyRequests
+const DetailServiceTooManyRequestsCode int = 429
+
+/*DetailServiceTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response detailServiceTooManyRequests
+*/
+type DetailServiceTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDetailServiceTooManyRequests creates DetailServiceTooManyRequests with default headers values
+func NewDetailServiceTooManyRequests() *DetailServiceTooManyRequests {
+
+ return &DetailServiceTooManyRequests{}
+}
+
+// WithPayload adds the payload to the detail service too many requests response
+func (o *DetailServiceTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DetailServiceTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the detail service too many requests response
+func (o *DetailServiceTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DetailServiceTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/list_service_terminators_responses.go b/controller/rest_server/operations/service/list_service_terminators_responses.go
index 5ed6a064a..1a487dea2 100644
--- a/controller/rest_server/operations/service/list_service_terminators_responses.go
+++ b/controller/rest_server/operations/service/list_service_terminators_responses.go
@@ -168,3 +168,47 @@ func (o *ListServiceTerminatorsUnauthorized) WriteResponse(rw http.ResponseWrite
}
}
}
+
+// ListServiceTerminatorsTooManyRequestsCode is the HTTP code returned for type ListServiceTerminatorsTooManyRequests
+const ListServiceTerminatorsTooManyRequestsCode int = 429
+
+/*ListServiceTerminatorsTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listServiceTerminatorsTooManyRequests
+*/
+type ListServiceTerminatorsTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListServiceTerminatorsTooManyRequests creates ListServiceTerminatorsTooManyRequests with default headers values
+func NewListServiceTerminatorsTooManyRequests() *ListServiceTerminatorsTooManyRequests {
+
+ return &ListServiceTerminatorsTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list service terminators too many requests response
+func (o *ListServiceTerminatorsTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListServiceTerminatorsTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list service terminators too many requests response
+func (o *ListServiceTerminatorsTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListServiceTerminatorsTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/list_services_responses.go b/controller/rest_server/operations/service/list_services_responses.go
index 286a6d6d6..6161fa79a 100644
--- a/controller/rest_server/operations/service/list_services_responses.go
+++ b/controller/rest_server/operations/service/list_services_responses.go
@@ -124,3 +124,47 @@ func (o *ListServicesUnauthorized) WriteResponse(rw http.ResponseWriter, produce
}
}
}
+
+// ListServicesTooManyRequestsCode is the HTTP code returned for type ListServicesTooManyRequests
+const ListServicesTooManyRequestsCode int = 429
+
+/*ListServicesTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listServicesTooManyRequests
+*/
+type ListServicesTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListServicesTooManyRequests creates ListServicesTooManyRequests with default headers values
+func NewListServicesTooManyRequests() *ListServicesTooManyRequests {
+
+ return &ListServicesTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list services too many requests response
+func (o *ListServicesTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListServicesTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list services too many requests response
+func (o *ListServicesTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListServicesTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/patch_service_responses.go b/controller/rest_server/operations/service/patch_service_responses.go
index c73c7d237..efa04e967 100644
--- a/controller/rest_server/operations/service/patch_service_responses.go
+++ b/controller/rest_server/operations/service/patch_service_responses.go
@@ -212,3 +212,47 @@ func (o *PatchServiceNotFound) WriteResponse(rw http.ResponseWriter, producer ru
}
}
}
+
+// PatchServiceTooManyRequestsCode is the HTTP code returned for type PatchServiceTooManyRequests
+const PatchServiceTooManyRequestsCode int = 429
+
+/*PatchServiceTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response patchServiceTooManyRequests
+*/
+type PatchServiceTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewPatchServiceTooManyRequests creates PatchServiceTooManyRequests with default headers values
+func NewPatchServiceTooManyRequests() *PatchServiceTooManyRequests {
+
+ return &PatchServiceTooManyRequests{}
+}
+
+// WithPayload adds the payload to the patch service too many requests response
+func (o *PatchServiceTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *PatchServiceTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the patch service too many requests response
+func (o *PatchServiceTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *PatchServiceTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/service/update_service_responses.go b/controller/rest_server/operations/service/update_service_responses.go
index 2f99ef7ae..d493df4a4 100644
--- a/controller/rest_server/operations/service/update_service_responses.go
+++ b/controller/rest_server/operations/service/update_service_responses.go
@@ -212,3 +212,47 @@ func (o *UpdateServiceNotFound) WriteResponse(rw http.ResponseWriter, producer r
}
}
}
+
+// UpdateServiceTooManyRequestsCode is the HTTP code returned for type UpdateServiceTooManyRequests
+const UpdateServiceTooManyRequestsCode int = 429
+
+/*UpdateServiceTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response updateServiceTooManyRequests
+*/
+type UpdateServiceTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewUpdateServiceTooManyRequests creates UpdateServiceTooManyRequests with default headers values
+func NewUpdateServiceTooManyRequests() *UpdateServiceTooManyRequests {
+
+ return &UpdateServiceTooManyRequests{}
+}
+
+// WithPayload adds the payload to the update service too many requests response
+func (o *UpdateServiceTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *UpdateServiceTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the update service too many requests response
+func (o *UpdateServiceTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *UpdateServiceTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/terminator/create_terminator_responses.go b/controller/rest_server/operations/terminator/create_terminator_responses.go
index ffc7305a9..8f1240e1e 100644
--- a/controller/rest_server/operations/terminator/create_terminator_responses.go
+++ b/controller/rest_server/operations/terminator/create_terminator_responses.go
@@ -168,3 +168,47 @@ func (o *CreateTerminatorUnauthorized) WriteResponse(rw http.ResponseWriter, pro
}
}
}
+
+// CreateTerminatorTooManyRequestsCode is the HTTP code returned for type CreateTerminatorTooManyRequests
+const CreateTerminatorTooManyRequestsCode int = 429
+
+/*CreateTerminatorTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response createTerminatorTooManyRequests
+*/
+type CreateTerminatorTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewCreateTerminatorTooManyRequests creates CreateTerminatorTooManyRequests with default headers values
+func NewCreateTerminatorTooManyRequests() *CreateTerminatorTooManyRequests {
+
+ return &CreateTerminatorTooManyRequests{}
+}
+
+// WithPayload adds the payload to the create terminator too many requests response
+func (o *CreateTerminatorTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *CreateTerminatorTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the create terminator too many requests response
+func (o *CreateTerminatorTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CreateTerminatorTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/terminator/delete_terminator_responses.go b/controller/rest_server/operations/terminator/delete_terminator_responses.go
index cdf8cca82..0a478627b 100644
--- a/controller/rest_server/operations/terminator/delete_terminator_responses.go
+++ b/controller/rest_server/operations/terminator/delete_terminator_responses.go
@@ -212,3 +212,47 @@ func (o *DeleteTerminatorConflict) WriteResponse(rw http.ResponseWriter, produce
}
}
}
+
+// DeleteTerminatorTooManyRequestsCode is the HTTP code returned for type DeleteTerminatorTooManyRequests
+const DeleteTerminatorTooManyRequestsCode int = 429
+
+/*DeleteTerminatorTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response deleteTerminatorTooManyRequests
+*/
+type DeleteTerminatorTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDeleteTerminatorTooManyRequests creates DeleteTerminatorTooManyRequests with default headers values
+func NewDeleteTerminatorTooManyRequests() *DeleteTerminatorTooManyRequests {
+
+ return &DeleteTerminatorTooManyRequests{}
+}
+
+// WithPayload adds the payload to the delete terminator too many requests response
+func (o *DeleteTerminatorTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DeleteTerminatorTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the delete terminator too many requests response
+func (o *DeleteTerminatorTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DeleteTerminatorTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/terminator/detail_terminator_responses.go b/controller/rest_server/operations/terminator/detail_terminator_responses.go
index b3be05c7b..fe576f89a 100644
--- a/controller/rest_server/operations/terminator/detail_terminator_responses.go
+++ b/controller/rest_server/operations/terminator/detail_terminator_responses.go
@@ -168,3 +168,47 @@ func (o *DetailTerminatorNotFound) WriteResponse(rw http.ResponseWriter, produce
}
}
}
+
+// DetailTerminatorTooManyRequestsCode is the HTTP code returned for type DetailTerminatorTooManyRequests
+const DetailTerminatorTooManyRequestsCode int = 429
+
+/*DetailTerminatorTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response detailTerminatorTooManyRequests
+*/
+type DetailTerminatorTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewDetailTerminatorTooManyRequests creates DetailTerminatorTooManyRequests with default headers values
+func NewDetailTerminatorTooManyRequests() *DetailTerminatorTooManyRequests {
+
+ return &DetailTerminatorTooManyRequests{}
+}
+
+// WithPayload adds the payload to the detail terminator too many requests response
+func (o *DetailTerminatorTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *DetailTerminatorTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the detail terminator too many requests response
+func (o *DetailTerminatorTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *DetailTerminatorTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/terminator/list_terminators_responses.go b/controller/rest_server/operations/terminator/list_terminators_responses.go
index 81c1a07d4..6af0c53b9 100644
--- a/controller/rest_server/operations/terminator/list_terminators_responses.go
+++ b/controller/rest_server/operations/terminator/list_terminators_responses.go
@@ -168,3 +168,47 @@ func (o *ListTerminatorsUnauthorized) WriteResponse(rw http.ResponseWriter, prod
}
}
}
+
+// ListTerminatorsTooManyRequestsCode is the HTTP code returned for type ListTerminatorsTooManyRequests
+const ListTerminatorsTooManyRequestsCode int = 429
+
+/*ListTerminatorsTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response listTerminatorsTooManyRequests
+*/
+type ListTerminatorsTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewListTerminatorsTooManyRequests creates ListTerminatorsTooManyRequests with default headers values
+func NewListTerminatorsTooManyRequests() *ListTerminatorsTooManyRequests {
+
+ return &ListTerminatorsTooManyRequests{}
+}
+
+// WithPayload adds the payload to the list terminators too many requests response
+func (o *ListTerminatorsTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *ListTerminatorsTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the list terminators too many requests response
+func (o *ListTerminatorsTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *ListTerminatorsTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/terminator/patch_terminator_responses.go b/controller/rest_server/operations/terminator/patch_terminator_responses.go
index 0cd041598..4b76243fc 100644
--- a/controller/rest_server/operations/terminator/patch_terminator_responses.go
+++ b/controller/rest_server/operations/terminator/patch_terminator_responses.go
@@ -212,3 +212,47 @@ func (o *PatchTerminatorNotFound) WriteResponse(rw http.ResponseWriter, producer
}
}
}
+
+// PatchTerminatorTooManyRequestsCode is the HTTP code returned for type PatchTerminatorTooManyRequests
+const PatchTerminatorTooManyRequestsCode int = 429
+
+/*PatchTerminatorTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response patchTerminatorTooManyRequests
+*/
+type PatchTerminatorTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewPatchTerminatorTooManyRequests creates PatchTerminatorTooManyRequests with default headers values
+func NewPatchTerminatorTooManyRequests() *PatchTerminatorTooManyRequests {
+
+ return &PatchTerminatorTooManyRequests{}
+}
+
+// WithPayload adds the payload to the patch terminator too many requests response
+func (o *PatchTerminatorTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *PatchTerminatorTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the patch terminator too many requests response
+func (o *PatchTerminatorTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *PatchTerminatorTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/rest_server/operations/terminator/update_terminator_responses.go b/controller/rest_server/operations/terminator/update_terminator_responses.go
index 6bbe5b703..f4e1af130 100644
--- a/controller/rest_server/operations/terminator/update_terminator_responses.go
+++ b/controller/rest_server/operations/terminator/update_terminator_responses.go
@@ -212,3 +212,47 @@ func (o *UpdateTerminatorNotFound) WriteResponse(rw http.ResponseWriter, produce
}
}
}
+
+// UpdateTerminatorTooManyRequestsCode is the HTTP code returned for type UpdateTerminatorTooManyRequests
+const UpdateTerminatorTooManyRequestsCode int = 429
+
+/*UpdateTerminatorTooManyRequests The resource requested is rate limited and the rate limit has been exceeded
+
+swagger:response updateTerminatorTooManyRequests
+*/
+type UpdateTerminatorTooManyRequests struct {
+
+ /*
+ In: Body
+ */
+ Payload *rest_model.APIErrorEnvelope `json:"body,omitempty"`
+}
+
+// NewUpdateTerminatorTooManyRequests creates UpdateTerminatorTooManyRequests with default headers values
+func NewUpdateTerminatorTooManyRequests() *UpdateTerminatorTooManyRequests {
+
+ return &UpdateTerminatorTooManyRequests{}
+}
+
+// WithPayload adds the payload to the update terminator too many requests response
+func (o *UpdateTerminatorTooManyRequests) WithPayload(payload *rest_model.APIErrorEnvelope) *UpdateTerminatorTooManyRequests {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the update terminator too many requests response
+func (o *UpdateTerminatorTooManyRequests) SetPayload(payload *rest_model.APIErrorEnvelope) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *UpdateTerminatorTooManyRequests) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(429)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/controller/specs/swagger.yml b/controller/specs/swagger.yml
index a36a3dd8a..1cdd6a64e 100644
--- a/controller/specs/swagger.yml
+++ b/controller/specs/swagger.yml
@@ -46,6 +46,9 @@ paths:
$ref: '#/responses/listServices'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
post:
summary: Create a service resource
description: Create a service resource. Requires admin access.
@@ -66,6 +69,9 @@ paths:
$ref: '#/responses/badRequestResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
'/services/{id}':
parameters:
- $ref: '#/parameters/id'
@@ -82,6 +88,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
put:
summary: Update all fields on a service
description: Update all fields on a service by id. Requires admin access.
@@ -104,6 +113,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
patch:
summary: Update the supplied fields on a service
description: Update the supplied fields on a service. Requires admin access.
@@ -126,6 +138,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
delete:
summary: Delete a service
description: Delete a service by id. Requires admin access.
@@ -141,6 +156,8 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'409':
$ref: '#/responses/cannotDeleteReferencedResourceResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
'/services/{id}/terminators':
parameters:
@@ -163,6 +180,8 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'400':
$ref: '#/responses/badRequestResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Routers
@@ -184,6 +203,9 @@ paths:
$ref: '#/responses/listRouters'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
post:
summary: Create a router resource
description: Create a router resource. Requires admin access.
@@ -204,6 +226,9 @@ paths:
$ref: '#/responses/badRequestResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
'/routers/{id}':
parameters:
- $ref: '#/parameters/id'
@@ -220,6 +245,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
put:
summary: Update all fields on a router
description: Update all fields on a router by id. Requires admin access.
@@ -242,6 +270,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
patch:
summary: Update the supplied fields on a router
description: Update the supplied fields on a router. Requires admin access.
@@ -264,6 +295,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
delete:
summary: Delete a router
description: Delete a router by id. Requires admin access.
@@ -279,6 +313,8 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'409':
$ref: '#/responses/cannotDeleteReferencedResourceResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
'/routers/{id}/terminators':
parameters:
@@ -301,6 +337,8 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'400':
$ref: '#/responses/badRequestResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Terminators
@@ -324,6 +362,9 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'400':
$ref: '#/responses/badRequestResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
post:
summary: Create a terminator resource
description: Create a terminator resource. Requires admin access.
@@ -344,6 +385,9 @@ paths:
$ref: '#/responses/badRequestResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
'/terminators/{id}':
parameters:
- $ref: '#/parameters/id'
@@ -360,6 +404,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
put:
summary: Update all fields on a terminator
description: Update all fields on a terminator by id. Requires admin access.
@@ -382,6 +429,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
patch:
summary: Update the supplied fields on a terminator
description: Update the supplied fields on a terminator. Requires admin access.
@@ -404,6 +454,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
delete:
summary: Delete a terminator
description: Delete a terminator by id. Requires admin access.
@@ -419,6 +472,8 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'409':
$ref: '#/responses/cannotDeleteReferencedResourceResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Links
@@ -436,6 +491,9 @@ paths:
$ref: '#/responses/listLinks'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
'/links/{id}':
parameters:
- $ref: '#/parameters/id'
@@ -452,6 +510,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
patch:
summary: Update the supplied fields on a link
description: Update the supplied fields on a link. Requires admin access.
@@ -474,6 +535,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
delete:
summary: Delete a link
description: Delete a link by id. Requires admin access.
@@ -487,6 +551,8 @@ paths:
$ref: '#/responses/badRequestResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Circuits
@@ -504,6 +570,9 @@ paths:
$ref: '#/responses/listCircuits'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
'/circuits/{id}':
parameters:
- $ref: '#/parameters/id'
@@ -520,6 +589,9 @@ paths:
$ref: '#/responses/notFoundResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
+
delete:
summary: Delete a circuit
description: Delete a circuit by id. Requires admin access.
@@ -542,6 +614,8 @@ paths:
$ref: '#/responses/unauthorizedResponse'
'409':
$ref: '#/responses/cannotDeleteReferencedResourceResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Inspections
@@ -566,6 +640,8 @@ paths:
$ref: '#/responses/inspectResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Database
@@ -653,6 +729,8 @@ paths:
$ref: '#/responses/dataIntegrityCheckResult'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
###################################################################
# Raft
@@ -669,6 +747,8 @@ paths:
$ref: '#/responses/raftListMembersResponse'
'401':
$ref: '#/responses/unauthorizedResponse'
+ '429':
+ $ref: '#/responses/rateLimitedResponse'
#######################################################################################################################
#
diff --git a/controller/sync_strats/sync_instant.go b/controller/sync_strats/sync_instant.go
index 202780ae2..8d800abc4 100644
--- a/controller/sync_strats/sync_instant.go
+++ b/controller/sync_strats/sync_instant.go
@@ -22,17 +22,17 @@ import (
"github.com/lucsky/cuid"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
+ "github.com/openziti/foundation/v2/debugz"
+ "github.com/openziti/foundation/v2/genext"
+ "github.com/openziti/storage/ast"
+ "github.com/openziti/ziti/common/build"
"github.com/openziti/ziti/common/pb/edge_ctrl_pb"
"github.com/openziti/ziti/controller/env"
+ "github.com/openziti/ziti/controller/event"
"github.com/openziti/ziti/controller/handler_edge_ctrl"
"github.com/openziti/ziti/controller/model"
- "github.com/openziti/ziti/controller/persistence"
- "github.com/openziti/ziti/common/build"
"github.com/openziti/ziti/controller/network"
- "github.com/openziti/ziti/controller/event"
- "github.com/openziti/foundation/v2/debugz"
- "github.com/openziti/foundation/v2/genext"
- "github.com/openziti/storage/ast"
+ "github.com/openziti/ziti/controller/persistence"
cmap "github.com/orcaman/concurrent-map/v2"
"go.etcd.io/bbolt"
"google.golang.org/protobuf/proto"
@@ -431,14 +431,18 @@ func (strategy *InstantStrategy) sendHello(rtx *RouterSender) {
}
}
-func (strategy *InstantStrategy) ReceiveResync(r *network.Router, _ *edge_ctrl_pb.RequestClientReSync) {
- rtx := strategy.rtxMap.Get(r.Id)
+func (strategy *InstantStrategy) ReceiveResync(routerId string, _ *edge_ctrl_pb.RequestClientReSync) {
+ rtx := strategy.rtxMap.Get(routerId)
if rtx == nil {
+ routerName := ""
+ if router, _ := strategy.ae.Managers.Router.Read(routerId); router != nil {
+ routerName = router.Name
+ }
pfxlog.Logger().
WithField("strategy", strategy.Type()).
- WithField("routerId", r.Id).
- WithField("routerName", r.Name).
+ WithField("routerId", routerId).
+ WithField("routerName", routerName).
Error("received resync from router that is currently not tracked by the strategy, dropping resync")
return
}
@@ -450,14 +454,18 @@ func (strategy *InstantStrategy) ReceiveResync(r *network.Router, _ *edge_ctrl_p
strategy.receivedClientHelloQueue <- rtx
}
-func (strategy *InstantStrategy) ReceiveClientHello(r *network.Router, respHello *edge_ctrl_pb.ClientHello) {
- rtx := strategy.rtxMap.Get(r.Id)
+func (strategy *InstantStrategy) ReceiveClientHello(routerId string, respHello *edge_ctrl_pb.ClientHello) {
+ rtx := strategy.rtxMap.Get(routerId)
if rtx == nil {
+ routerName := ""
+ if router, _ := strategy.ae.Managers.Router.Read(routerId); router != nil {
+ routerName = router.Name
+ }
pfxlog.Logger().
WithField("strategy", strategy.Type()).
- WithField("routerId", r.Id).
- WithField("routerName", r.Name).
+ WithField("routerId", routerId).
+ WithField("routerName", routerName).
Error("received hello from router that is currently not tracked by the strategy, dropping hello")
return
}
@@ -467,17 +475,12 @@ func (strategy *InstantStrategy) ReceiveClientHello(r *network.Router, respHello
WithField("protocols", respHello.Protocols).
WithField("protocolPorts", respHello.ProtocolPorts).
WithField("listeners", respHello.Listeners).
- WithField("data", respHello.Data)
-
- serverVersion := build.GetBuildInfo().Version()
-
- if r.VersionInfo != nil {
- logger = logger.WithField("version", r.VersionInfo.Version).
- WithField("revision", r.VersionInfo.Revision).
- WithField("buildDate", r.VersionInfo.BuildDate).
- WithField("os", r.VersionInfo.OS).
- WithField("arch", r.VersionInfo.Arch)
- }
+ WithField("data", respHello.Data).
+ WithField("version", rtx.Router.VersionInfo.Version).
+ WithField("revision", rtx.Router.VersionInfo.Revision).
+ WithField("buildDate", rtx.Router.VersionInfo.BuildDate).
+ WithField("os", rtx.Router.VersionInfo.OS).
+ WithField("arch", rtx.Router.VersionInfo.Arch)
protocols := map[string]string{}
@@ -497,8 +500,9 @@ func (strategy *InstantStrategy) ReceiveClientHello(r *network.Router, respHello
rtx.SetHostname(respHello.Hostname)
rtx.SetProtocols(protocols)
- rtx.SetVersionInfo(*r.VersionInfo)
+ rtx.SetVersionInfo(*rtx.Router.VersionInfo)
+ serverVersion := build.GetBuildInfo().Version()
logger.Infof("edge router sent hello with version [%s] to controller with version [%s]", respHello.Version, serverVersion)
strategy.receivedClientHelloQueue <- rtx
}
diff --git a/dist/cloudfront/get.openziti.io/routes.yml b/dist/cloudfront/get.openziti.io/routes.yml
index f2c16c2f1..7c80f09f7 100644
--- a/dist/cloudfront/get.openziti.io/routes.yml
+++ b/dist/cloudfront/get.openziti.io/routes.yml
@@ -28,3 +28,7 @@
- get: /pack/
raw: /openziti/ziti-tunnel-sdk-c/main/
file: package-repos.gpg
+
+- get: /zdew/
+ raw: /openziti/desktop-edge-win/release-next/
+ file: version-check.json
diff --git a/dist/docker-images/ziti-cli/Dockerfile b/dist/docker-images/ziti-cli/Dockerfile
index 0a006e7ce..8508e5b72 100644
--- a/dist/docker-images/ziti-cli/Dockerfile
+++ b/dist/docker-images/ziti-cli/Dockerfile
@@ -31,7 +31,7 @@ LABEL name="openziti/ziti-cli" \
USER root
### install packages
-RUN INSTALL_PKGS="python38 python38-pip tar bash-completion vim-minimal less shadow-utils" && \
+RUN INSTALL_PKGS="python3.11 python3.11-pip tar bash-completion vim-minimal less shadow-utils jq" && \
microdnf -y update --setopt=install_weak_deps=0 --setopt=tsflags=nodocs && \
microdnf -y install --setopt=install_weak_deps=0 --setopt=tsflags=nodocs ${INSTALL_PKGS}
diff --git a/etc/ctrl.with.edge.yml b/etc/ctrl.with.edge.yml
index 98f7fd846..7e99f9678 100644
--- a/etc/ctrl.with.edge.yml
+++ b/etc/ctrl.with.edge.yml
@@ -233,3 +233,6 @@ web:
- binding: edge-client
options: { }
+commandRateLimiter:
+ enabled: true
+ maxQueued: 100
diff --git a/go.mod b/go.mod
index 800655f84..45476153a 100644
--- a/go.mod
+++ b/go.mod
@@ -24,11 +24,11 @@ require (
github.com/go-openapi/strfmt v0.21.7
github.com/go-openapi/swag v0.22.4
github.com/go-openapi/validate v0.22.1
- github.com/go-resty/resty/v2 v2.9.1
+ github.com/go-resty/resty/v2 v2.10.0
github.com/golang-jwt/jwt/v5 v5.0.0
- github.com/google/go-cmp v0.5.9
+ github.com/google/go-cmp v0.6.0
github.com/google/gopacket v1.1.19
- github.com/google/uuid v1.3.1
+ github.com/google/uuid v1.4.0
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
@@ -46,18 +46,18 @@ require (
github.com/miekg/dns v1.1.56
github.com/mitchellh/mapstructure v1.5.0
github.com/natefinch/lumberjack v2.0.0+incompatible
- github.com/openziti/agent v1.0.15
- github.com/openziti/channel/v2 v2.0.101
- github.com/openziti/edge-api v0.25.38
+ github.com/openziti/agent v1.0.16
+ github.com/openziti/channel/v2 v2.0.105
+ github.com/openziti/edge-api v0.26.0
github.com/openziti/foundation/v2 v2.0.33
- github.com/openziti/identity v1.0.64
+ github.com/openziti/identity v1.0.66
github.com/openziti/jwks v1.0.3
- github.com/openziti/metrics v1.2.36
+ github.com/openziti/metrics v1.2.37
github.com/openziti/runzmd v1.0.33
- github.com/openziti/sdk-golang v0.20.122
- github.com/openziti/secretstream v0.1.12
- github.com/openziti/storage v0.2.20
- github.com/openziti/transport/v2 v2.0.109
+ github.com/openziti/sdk-golang v0.20.129
+ github.com/openziti/secretstream v0.1.13
+ github.com/openziti/storage v0.2.23
+ github.com/openziti/transport/v2 v2.0.113
github.com/openziti/x509-claims v1.0.3
github.com/openziti/xweb/v2 v2.1.0
github.com/openziti/ziti-db-explorer v1.1.3
@@ -76,7 +76,7 @@ require (
github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125
github.com/xeipuuv/gojsonschema v1.2.0
github.com/zitadel/oidc/v2 v2.7.0
- go.etcd.io/bbolt v1.3.7
+ go.etcd.io/bbolt v1.3.8
golang.org/x/crypto v0.14.0
golang.org/x/net v0.17.0
golang.org/x/sync v0.4.0
@@ -95,7 +95,7 @@ require (
github.com/MichaelMure/go-term-markdown v0.1.4 // indirect
github.com/MichaelMure/go-term-text v0.3.1 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
- github.com/andybalholm/brotli v1.0.5 // indirect
+ github.com/andybalholm/brotli v1.0.6 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
@@ -109,9 +109,9 @@ require (
github.com/docker/go-units v0.5.0 // indirect
github.com/eliukblau/pixterm/pkg/ansimage v0.0.0-20191210081756-9fb6cf8c2f75 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
- github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
- github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
@@ -129,15 +129,14 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/klauspost/compress v1.17.0 // indirect
github.com/kr/pty v1.1.8 // indirect
github.com/kyokomi/emoji/v2 v2.2.12 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
- github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
+ github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-tty v0.0.3 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
@@ -187,5 +186,5 @@ require (
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
- nhooyr.io/websocket v1.8.7 // indirect
+ nhooyr.io/websocket v1.8.10 // indirect
)
diff --git a/go.sum b/go.sum
index 4b7e21f74..ae3db55fa 100644
--- a/go.sum
+++ b/go.sum
@@ -80,8 +80,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
-github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
+github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
@@ -192,16 +192,12 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
-github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
-github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-acme/lego/v4 v4.14.2 h1:/D/jqRgLi8Cbk33sLGtu2pX2jEg3bGJWHyV8kFuUHGM=
github.com/go-acme/lego/v4 v4.14.2/go.mod h1:kBXxbeTg0x9AgaOYjPSwIeJy3Y33zTz+tMD16O4MO6c=
@@ -217,8 +213,8 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
-github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
+github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
@@ -263,15 +259,8 @@ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogB
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
-github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
-github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
-github.com/go-resty/resty/v2 v2.9.1 h1:PIgGx4VrHvag0juCJ4dDv3MiFRlDmP0vicBucwf+gLM=
-github.com/go-resty/resty/v2 v2.9.1/go.mod h1:4/GYJVjh9nhkhGR6AUNW3XhpDYNUr+Uvy9gV/VGZIy4=
+github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo=
+github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
@@ -297,12 +286,6 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
-github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
-github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
-github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
-github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -363,8 +346,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -388,8 +372,8 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
-github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@@ -404,7 +388,6 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
-github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -480,7 +463,6 @@ github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2C
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -494,10 +476,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
-github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -519,8 +498,6 @@ github.com/kyokomi/emoji/v2 v2.2.12 h1:sSVA5nH9ebR3Zji1o31wu3yOwD1zKXQA2z0zUyeit
github.com/kyokomi/emoji/v2 v2.2.12/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
-github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
-github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
@@ -528,8 +505,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i
github.com/lucsky/cuid v1.2.1 h1:MtJrL2OFhvYufUIn48d35QGXyeTC8tn0upumW9WwTHg=
github.com/lucsky/cuid v1.2.1/go.mod h1:QaaJqckboimOmhRSJXSx/+IT+VTfxfPGSo/6mfgUfmE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
-github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik=
-github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
+github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
+github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@@ -567,8 +544,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
@@ -609,11 +586,9 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM=
github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM=
@@ -639,32 +614,32 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
-github.com/openziti/agent v1.0.15 h1:NW4egpS3Mw1RQBZWfUEvrmBh9kn/SU/dU5fndsyyhZ4=
-github.com/openziti/agent v1.0.15/go.mod h1:zfm53+PVWoGFzjGGgQdKby5749G6VRYHe+eQJmoVKy4=
-github.com/openziti/channel/v2 v2.0.101 h1:UaveW/ogYKVtCQZfwRoMhsZhj/tvs1bD7SvH0aLaYNw=
-github.com/openziti/channel/v2 v2.0.101/go.mod h1:b9CBWpH6tnLqCHInDKL6AzMGqXdbEjsul3yVQUGENVU=
+github.com/openziti/agent v1.0.16 h1:9Saji+8hFE1NpzP2XzDhsVJbCrDlhixoLHfOpFt5Z+U=
+github.com/openziti/agent v1.0.16/go.mod h1:zfm53+PVWoGFzjGGgQdKby5749G6VRYHe+eQJmoVKy4=
+github.com/openziti/channel/v2 v2.0.105 h1:WT2zFF7krZkYUfuXA+4tQxhYiiVWlldD3mKX3qJU9Ww=
+github.com/openziti/channel/v2 v2.0.105/go.mod h1:++bV6FFgGUNxaBu7iOkkCa6rSiueU34Kd6f2LSCrEtU=
github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k=
github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo=
-github.com/openziti/edge-api v0.25.38 h1:aijFEC4pMCi2gR6zL6FYQRkm59SQAwrF0tZS4LZsxi4=
-github.com/openziti/edge-api v0.25.38/go.mod h1:5mmcMgqK1MsBb0K8V1CBfGbtRUji5KYdmhJJJkJBMqY=
+github.com/openziti/edge-api v0.26.0 h1:082hXjj8rnyMBZHYiB6jb4n7mCXtdMXpF2iCqZOv4IM=
+github.com/openziti/edge-api v0.26.0/go.mod h1:/e1pK92L471fvOAwE/hLX5sqBuuo+NwI8vmL04dUHsM=
github.com/openziti/foundation/v2 v2.0.33 h1:8CP+fi4KsmzA4jDi54jibwFWWxKpd0rSiplzN9Z0Isw=
github.com/openziti/foundation/v2 v2.0.33/go.mod h1:dWR0g3NOka3uKz9MgUHq6dmuRLmSvunkyeuOXEW/5qU=
-github.com/openziti/identity v1.0.64 h1:HwALRY1J/rNNcIAlr1OwCwTHU/rlMRaUi5TXAfZotjw=
-github.com/openziti/identity v1.0.64/go.mod h1:t/mW5mCpCbcRrssj4EpzfrmebI7+UKXGH2twll7IQIo=
+github.com/openziti/identity v1.0.66 h1:wCIVNCoiHmeicC9yM15FC0xe6jSic879ztN63fSD6hM=
+github.com/openziti/identity v1.0.66/go.mod h1:grReHVqBwhECrnrAZCxNw4ZpA2I1ox66tYfPkfGuKJY=
github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc=
github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ=
-github.com/openziti/metrics v1.2.36 h1:oW5YM9H8IqtFuxIyo0rMC3mTpl3rdSnDKcHp+ZTn+JM=
-github.com/openziti/metrics v1.2.36/go.mod h1:fjYG6sUC/n6VXe0nZbYGEBaopbRThBo/3xt7o9VatRQ=
+github.com/openziti/metrics v1.2.37 h1:5yWvMwQT6X43LDlNVcUtqAPJQXfKtbWSYoCIiOfXztg=
+github.com/openziti/metrics v1.2.37/go.mod h1:jIL9iilxby8tR98C18uZaSe6bRG15ItR8XF2hmMt8vs=
github.com/openziti/runzmd v1.0.33 h1:tOyjRoUuVXIo1z1pNU32jALWkMmhzsSaDrhLtuOn3Ts=
github.com/openziti/runzmd v1.0.33/go.mod h1:8c/uvZR/XWXQNllTq6LuTpfKL2DTNxfI2X2wYhgRwik=
-github.com/openziti/sdk-golang v0.20.122 h1:fuxws2yFEFl4hdq4l96/N23ztC1oUiQIM/lePTI6rBY=
-github.com/openziti/sdk-golang v0.20.122/go.mod h1:n6Ft+Gz7e2JO6DQ6Ixc9oIn06I1MjzkI3V9kilkOBIQ=
-github.com/openziti/secretstream v0.1.12 h1:N78CHxtqWzSyNFOsYtYRWNNTfX1ZDAPkFgzHobpodZU=
-github.com/openziti/secretstream v0.1.12/go.mod h1:gHMH1REH0r4VlmCtuWx8biU7j5ZfOivFjz9mLgwq7mk=
-github.com/openziti/storage v0.2.20 h1:xpLczyF/czIw76M4Rrt2urYn/EvGNor+SPzoixuOkLs=
-github.com/openziti/storage v0.2.20/go.mod h1:UO8D6h4AAf5OT1iJg1sppKoEPC2YWaBGZFLK7rPyk5M=
-github.com/openziti/transport/v2 v2.0.109 h1:12ZdM9R7lETKP7cT2xsGlTX/4w2qBtC8nThxw8RG77Q=
-github.com/openziti/transport/v2 v2.0.109/go.mod h1:r1jay/cSzkw15SJLtbk/I9YZtMIYjhueqAqfWtO5ioE=
+github.com/openziti/sdk-golang v0.20.129 h1:FjvXsGFxEiHq89sNyLSvNymruACFW5tbhkgZ3VCg2pE=
+github.com/openziti/sdk-golang v0.20.129/go.mod h1:ZpJ7HCcIQbp8XiSno3YXkfhoDIbgjCjS2ScK2bda8eo=
+github.com/openziti/secretstream v0.1.13 h1:grp53Q5gCFPXv6okwWHDVvqBBk2BhD0ikHwfV3Adhnc=
+github.com/openziti/secretstream v0.1.13/go.mod h1:M4DYavDc3TVF/eemNqp5Fa+zGuYTNa0HTGSz/GkgUzA=
+github.com/openziti/storage v0.2.23 h1:R5ZBGDGC/LvOz3fE/GlevwbPZ3HL7VxYEvlhKuezvNU=
+github.com/openziti/storage v0.2.23/go.mod h1:NZCrN2dLtRU73McVEflK5prDgYds9J54mMNz5DmgvZE=
+github.com/openziti/transport/v2 v2.0.113 h1:xFPd1W00KqkFb62rRsRXmLqfgr9d9uk0CAVZegvtGhA=
+github.com/openziti/transport/v2 v2.0.113/go.mod h1:TSDHV7RTGg/FinzfOP8cg86O53BCabXedANh3eUNics=
github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0=
github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE=
github.com/openziti/xweb/v2 v2.1.0 h1:Xhh3C2pZkq/Prr65V+SfFSibLDYteoc4f62KQCcTZF4=
@@ -858,10 +833,6 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
-github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
-github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
-github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
@@ -896,8 +867,8 @@ github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
github.com/zitadel/oidc/v2 v2.7.0 h1:IGX4EDk6tegTjUSsZDWeTfLseFU0BdJ/Glf1tgys2lU=
github.com/zitadel/oidc/v2 v2.7.0/go.mod h1:zkUkVJS0sDVy9m0UA9RgO3f8i/C0rtjvXU36UJj7T+0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
-go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
+go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
@@ -962,7 +933,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1065,7 +1035,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1181,7 +1150,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1195,7 +1163,6 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1217,8 +1184,8 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1456,8 +1423,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
-nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
+nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
+nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=
rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
diff --git a/quickstart/docker/docker-compose.yml b/quickstart/docker/docker-compose.yml
index c6e751bfa..75eda8236 100644
--- a/quickstart/docker/docker-compose.yml
+++ b/quickstart/docker/docker-compose.yml
@@ -2,6 +2,11 @@ version: '2.4'
services:
ziti-controller:
image: "${ZITI_IMAGE}:${ZITI_VERSION}"
+ healthcheck:
+ test: curl -m 1 -s -k https://${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS:-ziti-edge-controller}:${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280}/edge/client/v1/version
+ interval: 1s
+ timeout: 3s
+ retries: 30
env_file:
- ./.env
ports:
@@ -32,7 +37,8 @@ services:
ziti-controller-init-container:
image: "${ZITI_IMAGE}:${ZITI_VERSION}"
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
environment:
- ZITI_CTRL_EDGE_ADVERTISED_ADDRESS=${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS:-ziti-edge-controller}
- ZITI_CTRL_EDGE_ADVERTISED_PORT=${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280}
@@ -57,7 +63,8 @@ services:
env_file:
- ./.env
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
ports:
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_PORT:-3022}:${ZITI_ROUTER_PORT:-3022}
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_LISTENER_BIND_PORT:-10080}:${ZITI_ROUTER_LISTENER_BIND_PORT:-10080}
@@ -84,7 +91,8 @@ services:
env_file:
- ./.env
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
ports:
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_WSS_PORT:-3023}:${ZITI_ROUTER_WSS_PORT:-3023}
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_LISTENER_BIND_PORT:-10081}:${ZITI_ROUTER_LISTENER_BIND_PORT:-10081}
@@ -113,7 +121,8 @@ services:
env_file:
- ./.env
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
environment:
- ZITI_CTRL_ADVERTISED_ADDRESS=${ZITI_CTRL_ADVERTISED_ADDRESS:-ziti-controller}
- ZITI_CTRL_ADVERTISED_PORT=${ZITI_CTRL_ADVERTISED_PORT:-6262}
@@ -135,7 +144,8 @@ services:
env_file:
- ./.env
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
environment:
- ZITI_CTRL_ADVERTISED_ADDRESS=${ZITI_CTRL_ADVERTISED_ADDRESS:-ziti-controller}
- ZITI_CTRL_ADVERTISED_PORT=${ZITI_CTRL_ADVERTISED_PORT:-6262}
@@ -156,7 +166,8 @@ services:
env_file:
- ./.env
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
environment:
- ZITI_CTRL_ADVERTISED_ADDRESS=${ZITI_CTRL_ADVERTISED_ADDRESS:-ziti-controller}
- ZITI_CTRL_ADVERTISED_PORT=${ZITI_CTRL_ADVERTISED_PORT:-6262}
@@ -194,7 +205,8 @@ services:
- ZITI_CTRL_NAME=${ZITI_CTRL_NAME:-ziti-edge-controller}
- PORTTLS=8443
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
ports:
- ${ZITI_INTERFACE:-0.0.0.0}:8443:8443
volumes:
diff --git a/quickstart/docker/image/run-controller.sh b/quickstart/docker/image/run-controller.sh
index 0ec35e252..40faea127 100755
--- a/quickstart/docker/image/run-controller.sh
+++ b/quickstart/docker/image/run-controller.sh
@@ -1,6 +1,14 @@
#!/bin/bash
ziti_controller_cfg="${ZITI_HOME}/ziti-edge-controller.yaml"
+# Global Variables
+ASCI_RESTORE='\033[0m'
+ASCI_RED='\033[00;31m'
+
+function RED { # Generally used for ERROR
+ echo "${ASCI_RED}${1-}${ASCI_RESTORE}"
+}
+
if [[ "${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS-}" == "" ]]; then export ZITI_CTRL_EDGE_ADVERTISED_ADDRESS="ziti-edge-controller"; fi
if [[ "${ZITI_CTRL_NAME-}" == "" ]]; then export ZITI_CTRL_NAME="${ZITI_NETWORK}-controller"; fi
@@ -35,6 +43,10 @@ if [ ! -f "${ZITI_HOME}/access-control.init" ]; then
# initialize the database with the admin user:
"${ZITI_BIN_DIR}/ziti" controller edge init "${ZITI_HOME}/${ZITI_CTRL_NAME}.yaml" -u "${ZITI_USER}" -p "${ZITI_PWD}"
+ if [[ "$?" != 0 ]]; then
+ echo -e "$(RED " --- There was an error while initializing the controller ---")"
+ exit 1
+ fi
else
echo "system has been initialized. starting the process."
# don't move the sourcing of the file. yes it's duplicated but it needs to be here
diff --git a/quickstart/docker/image/ziti-cli-functions.sh b/quickstart/docker/image/ziti-cli-functions.sh
index a31d495a7..c71d0e896 100644
--- a/quickstart/docker/image/ziti-cli-functions.sh
+++ b/quickstart/docker/image/ziti-cli-functions.sh
@@ -405,7 +405,7 @@ function persistEnvironmentValues {
# Store all ZITI_ variables in the environment file, creating the directory if necessary
tmpfilepath="$(mktemp)"
mkdir -p "$(dirname "${filepath}")" && echo "" > "${tmpfilepath}"
- for zEnvVar in $(set | grep -e "^ZITI_" | sort); do
+ for zEnvVar in $(set | grep -e "^ZITI_" | sed "s/='\(.*\)'\$/=\1/" | sort); do
envvar="$(echo "${zEnvVar}" | cut -d '=' -f1)"
envval="$(echo "${zEnvVar}" | cut -d '=' -f2-1000)"
echo 'if [[ "$'${envvar}'" == "" ]]; then export '${envvar}'="'${envval}'"; else echo "NOT OVERRIDING: env var '${envvar}' already set. using existing value"; fi' >> "${tmpfilepath}"
@@ -717,10 +717,10 @@ function getZiti {
if ! test -f "${ZITI_ENV_FILE}"; then
echo -e " * $(YELLOW "WARN: The OpenZiti Environment file could not be found to update ziti binary related paths")"
else
- sed "s/export ZITI_BIN_DIR=.*/export ZITI_BIN_DIR=${ZITI_BIN_DIR}/g"
- sed "s/export ZITI_BINARIES_VERSION=.*/export ZITI_BINARIES_VERSION=${ZITI_BINARIES_VERSION}/g"
- sed "s/export ZITI_BINARIES_FILE=.*/export ZITI_BINARIES_FILE=${ZITI_BINARIES_FILE}/g"
- sed "s/export ZITI_BINARIES_FILE_ABSPATH=.*/d"
+ sed -i.bak "s/export ZITI_BIN_DIR=.*/export ZITI_BIN_DIR=$(echo ${ZITI_BIN_DIR} | sed 's/\//\\\//g')/g" "${ZITI_ENV_FILE}"
+ sed -i.bak "s/export ZITI_BINARIES_VERSION=.*/export ZITI_BINARIES_VERSION=$(echo ${ZITI_BINARIES_VERSION} | sed 's/\//\\\//g')/g" "${ZITI_ENV_FILE}"
+ sed -i.bak "s/export ZITI_BINARIES_FILE=.*/export ZITI_BINARIES_FILE=$(echo ${ZITI_BINARIES_FILE} | sed 's/\//\\\//g')/g" "${ZITI_ENV_FILE}"
+ sed -i.bak "/export ZITI_BINARIES_FILE_ABSPATH=.*/d" "${ZITI_ENV_FILE}"
fi
echo -e "$(YELLOW 'Getting latest binaries ')$(BLUE "${ZITI_BIN_DIR}")"
@@ -1024,6 +1024,11 @@ function initializeController {
log_file="${ZITI_HOME-}/${ZITI_CTRL_NAME}-init.log"
"${ZITI_BIN_DIR-}/ziti" controller edge init "${ZITI_HOME}/${ZITI_CTRL_NAME}.yaml" -u "${ZITI_USER-}" -p "${ZITI_PWD}" &> "${log_file}"
+ retVal=$?
+ if [[ "${retVal}" != 0 ]]; then
+ echo -e "$(RED " --- There was an error while initializing the controller, check the logs at ${log_file} ---")"
+ return 1
+ fi
echo -e "${ZITI_CTRL_NAME} initialized. See $(BLUE "${log_file}") for details"
}
@@ -1085,7 +1090,9 @@ function expressInstall {
echo -e "$(PURPLE "******** Setting Up Controller ********")"
createControllerConfig
- initializeController
+ if ! initializeController; then
+ return 1
+ fi
startController
echo "waiting for the controller to come online to allow the edge router to enroll"
_wait_for_controller
@@ -1553,31 +1560,33 @@ function performMigration {
fi
# Replace old Env Vars in the env file with new ones
- # NOTE: the '' after -i is required for Mac, otherwise an error is thrown
- sed -i '' 's/ZITI_CONTROLLER_HOSTNAME/ZITI_CTRL_EDGE_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CONTROLLER_INTERMEDIATE_NAME/ZITI_PKI_CTRL_INTERMEDIATE_NAME/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CONTROLLER_RAWNAME/ZITI_CTRL_EDGE_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CONTROLLER_ROOTCA_NAME/ZITI_PKI_CTRL_ROOTCA_NAME/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CTRL_EDGE_PORT/ZITI_CTRL_EDGE_ADVERTISED_PORT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CTRL_IDENTITY_CA/ZITI_PKI_CTRL_CA/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CTRL_IDENTITY_CERT/ZITI_PKI_CTRL_CERT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CTRL_IDENTITY_KEY/ZITI_PKI_CTRL_KEY/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CTRL_IDENTITY_SERVER_CERT/ZITI_PKI_CTRL_SERVER_CERT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_CTRL_PORT/ZITI_CTRL_ADVERTISED_PORT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CONTROLLER_HOSTNAME/ZITI_CTRL_EDGE_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME/ZITI_PKI_CTRL_EDGE_INTERMEDIATE_NAME/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CONTROLLER_PORT/ZITI_CTRL_EDGE_ADVERTISED_PORT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CONTROLLER_RAWNAME/ZITI_CTRL_NAME/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CONTROLLER_ROOTCA_NAME/ZITI_PKI_CTRL_EDGE_ROOTCA_NAME/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CTRL_IDENTITY_CA/ZITI_PKI_EDGE_CA/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CTRL_IDENTITY_CERT/ZITI_PKI_EDGE_CERT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CTRL_IDENTITY_KEY/ZITI_PKI_EDGE_KEY/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_EDGE_CTRL_IDENTITY_SERVER_CERT/ZITI_PKI_EDGE_SERVER_CERT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_ROUTER_RAWNAME/ZITI_ROUTER_NAME/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_PKI_OS_SPECIFIC/ZITI_PKI/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_SIGNING_CERT/ZITI_PKI_SIGNER_CERT/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_SIGNING_KEY/ZITI_PKI_SIGNER_KEY/g' "${ZITI_ENV_FILE}"
- sed -i '' 's/ZITI_ROUTER_HOSTNAME/ZITI_ROUTER_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
+ # NOTE: use of -i behaves differently for Mac vs Linux. -i.bak is a workaround so the command works in both OSs
+ sed -i.bak 's/ZITI_CONTROLLER_HOSTNAME/ZITI_CTRL_EDGE_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CONTROLLER_INTERMEDIATE_NAME/ZITI_PKI_CTRL_INTERMEDIATE_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CONTROLLER_RAWNAME/ZITI_CTRL_EDGE_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CONTROLLER_ROOTCA_NAME/ZITI_PKI_CTRL_ROOTCA_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CTRL_EDGE_PORT/ZITI_CTRL_EDGE_ADVERTISED_PORT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CTRL_IDENTITY_CA/ZITI_PKI_CTRL_CA/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CTRL_IDENTITY_CERT/ZITI_PKI_CTRL_CERT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CTRL_IDENTITY_KEY/ZITI_PKI_CTRL_KEY/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CTRL_IDENTITY_SERVER_CERT/ZITI_PKI_CTRL_SERVER_CERT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_CTRL_PORT/ZITI_CTRL_ADVERTISED_PORT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CONTROLLER_HOSTNAME/ZITI_CTRL_EDGE_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CONTROLLER_INTERMEDIATE_NAME/ZITI_PKI_CTRL_EDGE_INTERMEDIATE_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CONTROLLER_PORT/ZITI_CTRL_EDGE_ADVERTISED_PORT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CONTROLLER_RAWNAME/ZITI_CTRL_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CONTROLLER_ROOTCA_NAME/ZITI_PKI_CTRL_EDGE_ROOTCA_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CTRL_IDENTITY_CA/ZITI_PKI_EDGE_CA/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CTRL_IDENTITY_CERT/ZITI_PKI_EDGE_CERT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CTRL_IDENTITY_KEY/ZITI_PKI_EDGE_KEY/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_EDGE_CTRL_IDENTITY_SERVER_CERT/ZITI_PKI_EDGE_SERVER_CERT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_ROUTER_RAWNAME/ZITI_ROUTER_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_PKI_OS_SPECIFIC/ZITI_PKI/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_SIGNING_CERT/ZITI_PKI_SIGNER_CERT/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_SIGNING_KEY/ZITI_PKI_SIGNER_KEY/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_ROUTER_HOSTNAME/ZITI_ROUTER_ADVERTISED_ADDRESS/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_SIGNING_ROOTCA_NAME/ZITI_PKI_SIGNER_ROOTCA_NAME/g' "${ZITI_ENV_FILE}"
+ sed -i.bak 's/ZITI_SIGNING_INTERMEDIATE_NAME/ZITI_PKI_SIGNER_INTERMEDIATE_NAME/g' "${ZITI_ENV_FILE}"
# Update environment variables if currently set
if [[ "${ZITI_EDGE_CONTROLLER_HOSTNAME-}" != "" ]]; then export ZITI_CTRL_EDGE_ADVERTISED_ADDRESS="${ZITI_EDGE_CONTROLLER_HOSTNAME}"; fi
@@ -1600,14 +1609,16 @@ function performMigration {
if [[ "${ZITI_SIGNING_CERT-}" != "" ]]; then export ZITI_PKI_SIGNER_CERT="${ZITI_SIGNING_CERT}"; fi
if [[ "${ZITI_SIGNING_KEY-}" != "" ]]; then export ZITI_PKI_SIGNER_KEY="${ZITI_SIGNING_KEY}"; fi
if [[ "${ZITI_ROUTER_HOSTNAME-}" != "" ]]; then export ZITI_ROUTER_ADVERTISED_ADDRESS="${ZITI_ROUTER_HOSTNAME}"; fi
+ if [[ "${ZITI_SIGNING_ROOTCA_NAME-}" != "" ]]; then export ZITI_PKI_SIGNER_ROOTCA_NAME="${ZITI_SIGNING_ROOTCA_NAME}"; fi
+ if [[ "${ZITI_SIGNING_INTERMEDIATE_NAME-}" != "" ]]; then export ZITI_PKI_SIGNER_INTERMEDIATE_NAME="${ZITI_SIGNING_INTERMEDIATE_NAME}"; fi
# Update the necessary ziti binary references (others are not needed or are overwritten later)
if [[ "${ZITI_BIN_DIR-}" != "" ]]; then
- sed '/^export ZITI_BIN_DIR=/d' "${ZITI_ENV_FILE}"
+ sed -i.bak '/^export ZITI_BIN_DIR=/d' "${ZITI_ENV_FILE}"
echo "export ZITI_BIN_DIR=${ZITI_BIN_DIR}" >> "${ZITI_ENV_FILE}"
fi
if [[ "${ZITI_BINARIES_VERSION-}" != "" ]]; then
- sed '/^export ZITI_BINARIES_VERSION=/d' "${ZITI_ENV_FILE}"
+ sed -i.bak '/^export ZITI_BINARIES_VERSION=/d' "${ZITI_ENV_FILE}"
echo "export ZITI_BINARIES_VERSION=${ZITI_BINARIES_VERSION}" >> "${ZITI_ENV_FILE}"
fi
diff --git a/quickstart/docker/simplified-docker-compose.yml b/quickstart/docker/simplified-docker-compose.yml
index a4399cda5..c50429fa0 100644
--- a/quickstart/docker/simplified-docker-compose.yml
+++ b/quickstart/docker/simplified-docker-compose.yml
@@ -1,6 +1,11 @@
services:
ziti-controller:
image: "${ZITI_IMAGE}:${ZITI_VERSION}"
+ healthcheck:
+ test: curl -m 1 -s -k https://${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS:-ziti-edge-controller}:${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280}/edge/client/v1/version
+ interval: 1s
+ timeout: 3s
+ retries: 30
env_file:
- ./.env
ports:
@@ -28,7 +33,8 @@ services:
ziti-controller-init-container:
image: "${ZITI_IMAGE}:${ZITI_VERSION}"
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
environment:
- ZITI_CTRL_EDGE_ADVERTISED_ADDRESS=${ZITI_CTRL_EDGE_ADVERTISED_ADDRESS:-ziti-edge-controller}
- ZITI_CTRL_EDGE_ADVERTISED_PORT=${ZITI_CTRL_EDGE_ADVERTISED_PORT:-1280}
@@ -48,7 +54,8 @@ services:
env_file:
- ./.env
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
ports:
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_PORT:-3022}:${ZITI_ROUTER_PORT:-3022}
- ${ZITI_INTERFACE:-0.0.0.0}:${ZITI_ROUTER_LISTENER_BIND_PORT:-10080}:${ZITI_ROUTER_LISTENER_BIND_PORT:-10080}
@@ -80,7 +87,8 @@ services:
- ZITI_CTRL_NAME=${ZITI_CTRL_NAME:-ziti-edge-controller}
- PORTTLS=8443
depends_on:
- - ziti-controller
+ ziti-controller:
+ condition: service_healthy
ports:
- ${ZITI_INTERFACE:-0.0.0.0}:8443:8443
volumes:
diff --git a/router/forwarder/forwarder.go b/router/forwarder/forwarder.go
index 1be4eff6a..3274d7270 100644
--- a/router/forwarder/forwarder.go
+++ b/router/forwarder/forwarder.go
@@ -18,14 +18,14 @@ package forwarder
import (
"github.com/michaelquigley/pfxlog"
+ "github.com/openziti/foundation/v2/errorz"
+ "github.com/openziti/foundation/v2/info"
+ "github.com/openziti/metrics"
"github.com/openziti/ziti/common/inspect"
"github.com/openziti/ziti/common/pb/ctrl_pb"
"github.com/openziti/ziti/common/trace"
"github.com/openziti/ziti/router/xgress"
"github.com/openziti/ziti/router/xlink"
- "github.com/openziti/foundation/v2/errorz"
- "github.com/openziti/foundation/v2/info"
- "github.com/openziti/metrics"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"time"
@@ -110,14 +110,12 @@ func (forwarder *Forwarder) HasDestination(address xgress.Address) bool {
}
func (forwarder *Forwarder) RegisterLink(link xlink.LinkDestination) error {
- if !forwarder.destinations.addDestinationIfAbsent(xgress.Address(link.Id()), link) {
- return errors.Errorf("unable to register link %v as it is already registered", link.Id())
- }
+ forwarder.destinations.addDestination(xgress.Address(link.Id()), link)
return nil
}
func (forwarder *Forwarder) UnregisterLink(link xlink.LinkDestination) {
- forwarder.destinations.removeDestination(xgress.Address(link.Id()))
+ forwarder.destinations.removeDestinationIfMatches(xgress.Address(link.Id()), link)
}
func (forwarder *Forwarder) Route(ctrlId string, route *ctrl_pb.Route) error {
diff --git a/router/forwarder/tables.go b/router/forwarder/tables.go
index a4ffdce5f..e80aa392e 100644
--- a/router/forwarder/tables.go
+++ b/router/forwarder/tables.go
@@ -115,10 +115,6 @@ func (dt *destinationTable) addDestination(addr xgress.Address, destination Dest
dt.destinations.Set(string(addr), destination)
}
-func (dt *destinationTable) addDestinationIfAbsent(addr xgress.Address, destination Destination) bool {
- return dt.destinations.SetIfAbsent(string(addr), destination)
-}
-
func (dt *destinationTable) getDestination(addr xgress.Address) (Destination, bool) {
if dst, found := dt.destinations.Get(string(addr)); found {
return dst, true
@@ -130,6 +126,12 @@ func (dt *destinationTable) removeDestination(addr xgress.Address) {
dt.destinations.Remove(string(addr))
}
+func (dt *destinationTable) removeDestinationIfMatches(addr xgress.Address, destination Destination) {
+ dt.destinations.RemoveCb(string(addr), func(key string, v Destination, exists bool) bool {
+ return exists && destination == v
+ })
+}
+
func (dt *destinationTable) linkDestinationToCircuit(circuitId string, address xgress.Address) {
var addresses []xgress.Address
if i, found := dt.xgress.Get(circuitId); found {
diff --git a/router/handler_link/close.go b/router/handler_link/close.go
index 4676ea696..8803fed9d 100644
--- a/router/handler_link/close.go
+++ b/router/handler_link/close.go
@@ -52,6 +52,8 @@ func (self *closeHandler) HandleClose(ch channel.Channel) {
WithField("linkId", self.link.Id()).
WithField("routerId", self.link.DestinationId())
+ self.forwarder.UnregisterLink(self.link)
+
// ensure that both parts of a split link are closed, if one side closes
go func() {
_ = self.link.Close()
@@ -72,7 +74,6 @@ func (self *closeHandler) HandleClose(ch channel.Channel) {
})
})
- self.forwarder.UnregisterLink(self.link)
close(self.closeNotify)
}
}
diff --git a/router/link/link_events.go b/router/link/link_events.go
index 6524e38cf..9392d7a44 100644
--- a/router/link/link_events.go
+++ b/router/link/link_events.go
@@ -19,11 +19,11 @@ package link
import (
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
- "github.com/openziti/ziti/controller/idgen"
+ "github.com/openziti/foundation/v2/stringz"
"github.com/openziti/ziti/common/inspect"
"github.com/openziti/ziti/common/pb/ctrl_pb"
+ "github.com/openziti/ziti/controller/idgen"
"github.com/openziti/ziti/router/xlink"
- "github.com/openziti/foundation/v2/stringz"
"github.com/pkg/errors"
"sync/atomic"
"time"
@@ -255,7 +255,7 @@ func (self *updateLinkState) Handle(registry *linkRegistryImpl) {
}
state.status = self.status
- if state.status == StatusQueueFailed || state.status == StatusDialFailed {
+ if state.status == StatusDialFailed {
state.dialFailed(registry)
}
}
diff --git a/router/link/link_registry.go b/router/link/link_registry.go
index 84bd8fd79..3955c7704 100644
--- a/router/link/link_registry.go
+++ b/router/link/link_registry.go
@@ -22,11 +22,11 @@ import (
"github.com/michaelquigley/pfxlog"
"github.com/openziti/channel/v2"
"github.com/openziti/channel/v2/protobufs"
+ "github.com/openziti/foundation/v2/goroutines"
"github.com/openziti/ziti/common/inspect"
"github.com/openziti/ziti/common/pb/ctrl_pb"
"github.com/openziti/ziti/router/env"
"github.com/openziti/ziti/router/xlink"
- "github.com/openziti/foundation/v2/goroutines"
"github.com/sirupsen/logrus"
"sync"
"sync/atomic"
@@ -165,9 +165,9 @@ func (self *linkRegistryImpl) LinkClosed(link xlink.Xlink) {
defer self.Unlock()
if val := self.linkMap[link.Key()]; val == link {
delete(self.linkMap, link.Key())
+ self.updateLinkStateClosed(link) // only update link state to closed if this was the current link
}
delete(self.linkByIdMap, link.Id())
- self.updateLinkStateClosed(link)
}
func (self *linkRegistryImpl) Shutdown() {
@@ -325,13 +325,33 @@ func (self *linkRegistryImpl) evaluateLinkStateQueue() {
}
func (self *linkRegistryImpl) evaluateDestinations() {
- for _, dest := range self.destinations {
- // TODO: When do we drop destinations? Should we ask the controller after the router has been
- // unhealthy for a while and it doesn't have any established links? Do this on exponential backoff?
- // Should the controller send router removed messages?
+ for destId, dest := range self.destinations {
+ hasEstablishedLinks := false
for _, state := range dest.linkMap {
+ // verify that links marked as established have an open link. There's a small chance that a link established
+ // and link closed could be processed out of order if the event queue is full. This way, it will eventually
+ // get fixed.
+ if state.status == StatusEstablished {
+ link, _ := self.GetLink(state.linkKey)
+ if link == nil || link.IsClosed() {
+ // If the link is not valid, allow it to be re-dialed
+ state.retryDelay = time.Duration(0)
+ state.nextDial = time.Now()
+ state.status = StatusLinkFailed
+ } else {
+ hasEstablishedLinks = true
+ }
+ }
+
self.evaluateLinkState(state)
}
+
+ // we are notified of deleted routers. In case we're unreachable while a router is deleted,
+ // we will also stop trying to contact unhealthy routers after a period. If a destination
+ // has nothing to dial, it should also be removed
+ if len(dest.linkMap) == 0 || (!dest.healthy && !hasEstablishedLinks && time.Since(dest.unhealthyAt) > 48*time.Hour) {
+ delete(self.destinations, destId)
+ }
}
}
@@ -343,14 +363,17 @@ func (self *linkRegistryImpl) evaluateLinkState(state *linkState) {
if couldDial {
state.status = StatusDialing
state.dialAttempts++
+ log.Info("queuing link to dial")
err := self.env.GetLinkDialerPool().QueueOrError(func() {
link, _ := self.GetLink(state.linkKey)
if link != nil {
- log.Warn("link already present, but link status still pending")
+ log.Info("link already present, attempting to mark established")
+ self.updateLinkStateEstablished(link)
return
}
+ log.Info("dialing link")
link, err := state.dialer.Dial(state)
if err != nil {
log.WithError(err).Error("error dialing link")
@@ -360,14 +383,23 @@ func (self *linkRegistryImpl) evaluateLinkState(state *linkState) {
})
return
}
- self.DialSucceeded(link)
+
+ existing, success := self.DialSucceeded(link)
+ if !success {
+ if existing != nil {
+ self.updateLinkStateEstablished(link)
+ } else {
+ self.queueEvent(&updateLinkState{
+ linkState: state,
+ status: StatusDialFailed,
+ })
+ }
+ }
})
if err != nil {
log.WithError(err).Error("unable to queue link dial, see pool error")
- self.queueEvent(&updateLinkState{
- linkState: state,
- status: StatusQueueFailed,
- })
+ state.status = StatusQueueFailed
+ state.dialFailed(self)
}
}
}
diff --git a/router/xgress_edge/certchecker_test.go b/router/xgress_edge/certchecker_test.go
index 469821073..8741666cf 100644
--- a/router/xgress_edge/certchecker_test.go
+++ b/router/xgress_edge/certchecker_test.go
@@ -8,13 +8,13 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"github.com/openziti/channel/v2"
- "github.com/openziti/ziti/common/eid"
- "github.com/openziti/ziti/router/internal/edgerouter"
- "github.com/openziti/ziti/router/env"
"github.com/openziti/foundation/v2/tlz"
"github.com/openziti/foundation/v2/versions"
"github.com/openziti/identity"
"github.com/openziti/transport/v2"
+ "github.com/openziti/ziti/common/eid"
+ "github.com/openziti/ziti/router/env"
+ "github.com/openziti/ziti/router/internal/edgerouter"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"math/big"
@@ -50,7 +50,7 @@ func Test_CertExpirationChecker(t *testing.T) {
req := require.New(t)
certChecker, _ := newCertChecker()
- now := time.Now()
+ now := time.Now().UTC()
notAfter := now.AddDate(0, 0, 7)
certChecker.id.Cert().Leaf.NotAfter = notAfter
@@ -210,7 +210,7 @@ func Test_CertExpirationChecker(t *testing.T) {
req := require.New(t)
certChecker, _ := newCertChecker()
- now := time.Now()
+ now := time.Now().UTC()
notAfter := now.AddDate(0, 0, 7)
certChecker.id.ServerCert()[0].Leaf.NotAfter = notAfter
diff --git a/router/xgress_edge/hosted.go b/router/xgress_edge/hosted.go
index 26187677d..b7a6f0161 100644
--- a/router/xgress_edge/hosted.go
+++ b/router/xgress_edge/hosted.go
@@ -66,7 +66,7 @@ func (registry *hostedServiceRegistry) cleanupDuplicates(newest *edgeTerminator)
registry.services.Range(func(key, value interface{}) bool {
terminator := value.(*edgeTerminator)
if terminator != newest && newest.token == terminator.token && newest.instance == terminator.instance {
- terminator.close(true, "duplicate terminator") // don't notify, channel is already closed, we can't send messages
+ terminator.close(false, "duplicate terminator") // don't notify, channel is already closed, we can't send messages
registry.services.Delete(key)
pfxlog.Logger().WithField("routerId", terminator.edgeClientConn.listener.id.Token).
WithField("sessionToken", terminator.token).
diff --git a/tests/accept_manual_start_test.go b/tests/accept_manual_start_test.go
index 1b2dab72f..ef88ce57f 100644
--- a/tests/accept_manual_start_test.go
+++ b/tests/accept_manual_start_test.go
@@ -20,9 +20,10 @@ package tests
import (
"github.com/michaelquigley/pfxlog"
- "github.com/openziti/ziti/controller/xt"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
+ "github.com/openziti/ziti/controller/change"
+ "github.com/openziti/ziti/controller/xt"
"github.com/pkg/errors"
"sync/atomic"
"testing"
@@ -34,7 +35,9 @@ func Test_ManualStart(t *testing.T) {
defer ctx.Teardown()
ctx.StartServer()
- xt.GlobalRegistry().RegisterFactory(&testFailoverStrategyFactory{})
+ xt.GlobalRegistry().RegisterFactory(&testFailoverStrategyFactory{
+ ctx: ctx,
+ })
t.Run("creating service and edge router", func(t *testing.T) {
ctx.testContextChanged(t)
ctx.RequireAdminManagementApiLogin()
@@ -165,25 +168,35 @@ func Test_ManualStart(t *testing.T) {
})
}
-type testFailoverStrategyFactory struct{}
+type testFailoverStrategyFactory struct {
+ ctx *TestContext
+}
func (self *testFailoverStrategyFactory) GetStrategyName() string {
return "test-failover"
}
func (self *testFailoverStrategyFactory) NewStrategy() xt.Strategy {
- return &testFailoverStrategy{}
+ return &testFailoverStrategy{
+ ctx: self.ctx,
+ }
}
type testFailoverStrategy struct {
xt.DefaultEventVisitor
failCount int32
+ ctx *TestContext
}
func (self *testFailoverStrategy) VisitDialFailed(event xt.TerminatorEvent) {
failCount := atomic.AddInt32(&self.failCount, 1)
if failCount >= 3 {
- xt.GlobalCosts().SetPrecedence(event.GetTerminator().GetId(), xt.Precedences.Failed)
+ mgr := self.ctx.EdgeController.AppEnv.Managers.Terminator
+ t, err := mgr.Read(event.GetTerminator().GetId())
+ self.ctx.Req.NoError(err)
+ t.Precedence = xt.Precedences.Failed
+ err = mgr.Update(t, nil, change.New())
+ self.ctx.Req.NoError(err)
}
}
diff --git a/tests/addressable_terminators_test.go b/tests/addressable_terminators_test.go
index 648250a97..c524ee0f3 100644
--- a/tests/addressable_terminators_test.go
+++ b/tests/addressable_terminators_test.go
@@ -19,9 +19,9 @@
package tests
import (
- "github.com/openziti/ziti/controller/xt_smartrouting"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
+ "github.com/openziti/ziti/controller/xt_smartrouting"
"github.com/pkg/errors"
"net"
"strings"
@@ -142,7 +142,9 @@ func Test_AddressableTerminatorSameIdentity(t *testing.T) {
listener.(edge.SessionListener).SetErrorEventHandler(errorHandler)
defer func() { _ = listener.Close() }()
- context2 := ziti.NewContext(identity.config)
+ context2, err := ziti.NewContext(identity.config)
+ ctx.Req.NoError(err)
+
listener2, err := context2.ListenWithOptions(service.Name, &ziti.ListenOptions{
BindUsingEdgeIdentity: true,
ConnectTimeout: 5 * time.Second,
diff --git a/tests/data_flow_close_test.go b/tests/data_flow_close_test.go
index 20bbb775c..b613169c1 100644
--- a/tests/data_flow_close_test.go
+++ b/tests/data_flow_close_test.go
@@ -22,8 +22,8 @@ package tests
import (
"errors"
"fmt"
- "github.com/openziti/ziti/common/eid"
"github.com/openziti/sdk-golang/ziti"
+ "github.com/openziti/ziti/common/eid"
"io"
"testing"
"time"
@@ -69,7 +69,9 @@ func Test_ServerConnClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
defer conn.Close()
@@ -134,7 +136,9 @@ func Test_ServerContextClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
defer conn.Close()
@@ -202,7 +206,9 @@ func Test_ServerCloseListenerPropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
defer conn.Close()
@@ -234,7 +240,9 @@ func Test_ClientConnClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
errC := make(chan error, 1)
@@ -296,7 +304,9 @@ func Test_ClientContextClosePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
errC := make(chan error, 1)
@@ -359,7 +369,9 @@ func Test_ServerConnCloseWritePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
errC := make(chan error, 1)
@@ -453,7 +465,9 @@ func Test_ClientConnCloseWritePropagation(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
conn := ctx.WrapConn(clientContext.Dial(service.Name))
name := eid.New()
diff --git a/tests/data_flow_hs_rotating_test.go b/tests/data_flow_hs_rotating_test.go
index d860d4406..6966e37ac 100644
--- a/tests/data_flow_hs_rotating_test.go
+++ b/tests/data_flow_hs_rotating_test.go
@@ -21,9 +21,9 @@ package tests
import (
"github.com/michaelquigley/pfxlog"
- "github.com/openziti/ziti/common/eid"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/edge"
+ "github.com/openziti/ziti/common/eid"
"github.com/pkg/errors"
"math/rand"
"sync"
@@ -122,7 +122,9 @@ func testClientFirstWithStrategy(t *testing.T, strategy string) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
logger := pfxlog.Logger()
@@ -265,7 +267,9 @@ func testServerFirstWithStrategy(t *testing.T, strategy string) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
diff --git a/tests/data_flow_hs_test.go b/tests/data_flow_hs_test.go
index 5a8295757..83d43ff5a 100644
--- a/tests/data_flow_hs_test.go
+++ b/tests/data_flow_hs_test.go
@@ -21,8 +21,8 @@ package tests
import (
"github.com/michaelquigley/pfxlog"
- "github.com/openziti/ziti/common/eid"
"github.com/openziti/sdk-golang/ziti"
+ "github.com/openziti/ziti/common/eid"
"sync/atomic"
"testing"
"time"
@@ -76,7 +76,9 @@ func Test_HSDataflow(t *testing.T) {
clientIdentity := ctx.AdminManagementSession.RequireNewIdentityWithOtt(false)
clientConfig := ctx.EnrollIdentity(clientIdentity.Id)
- clientContext := ziti.NewContext(clientConfig)
+
+ clientContext, err := ziti.NewContext(clientConfig)
+ ctx.Req.NoError(err)
for i := 0; i < 100; i++ {
conn := ctx.WrapConn(clientContext.Dial(service.Name))
diff --git a/version b/version
index f7c6c31b6..48b9990e0 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.30
+0.31
diff --git a/ziti/cmd/api/delete.go b/ziti/cmd/api/delete.go
index b245907b6..e846996e8 100644
--- a/ziti/cmd/api/delete.go
+++ b/ziti/cmd/api/delete.go
@@ -26,7 +26,7 @@ import (
func DeleteEntitiesOfType(api util.API, o *Options, entityType string, ids []string, body string) error {
for _, id := range ids {
- err := util.ControllerDelete(api, entityType, id, body, o.Out, o.OutputJSONRequest, o.OutputJSONResponse, o.Timeout, o.Verbose)
+ err, _ := util.ControllerDelete(api, entityType, id, body, o.Out, o.OutputJSONRequest, o.OutputJSONResponse, o.Timeout, o.Verbose)
if err != nil {
o.Printf("delete of %v with id %v: %v\n", boltz.GetSingularEntityType(entityType), id, color.New(color.FgRed, color.Bold).Sprint("FAIL"))
return err
diff --git a/ziti/cmd/create/create_config_controller.go b/ziti/cmd/create/create_config_controller.go
index e4f10aaf4..bd21f570f 100644
--- a/ziti/cmd/create/create_config_controller.go
+++ b/ziti/cmd/create/create_config_controller.go
@@ -173,10 +173,12 @@ func (options *CreateConfigControllerOptions) run(data *ConfigTemplateValues) er
if err != nil {
return errors.Wrapf(err, "unable to create config file: %s", options.Output)
}
+
+ //only close things we open
+ defer func() { _ = f.Close() }()
} else {
f = os.Stdout
}
- defer func() { _ = f.Close() }()
if err := tmpl.Execute(f, data); err != nil {
return errors.Wrap(err, "unable to execute template")
diff --git a/ziti/cmd/create/create_config_controller_test.go b/ziti/cmd/create/create_config_controller_test.go
index 5f319f4ad..925b18dc3 100644
--- a/ziti/cmd/create/create_config_controller_test.go
+++ b/ziti/cmd/create/create_config_controller_test.go
@@ -3,10 +3,12 @@ package create
import (
"fmt"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
+ "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"os"
"strings"
+ "syscall"
"testing"
"time"
)
@@ -111,15 +113,15 @@ func init() {
}
func TestControllerOutputPathDoesNotExist(t *testing.T) {
- expectedErrorMsg := "stat /IDoNotExist: no such file or directory"
-
// Create the options with non-existent path
options := &CreateConfigControllerOptions{}
options.Output = "/IDoNotExist/MyController.yaml"
err := options.run(&ConfigTemplateValues{})
- assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err)
+ //check wrapped error type and not internal strings as they vary between operating systems
+ assert.Error(t, err)
+ assert.Equal(t, errors.Unwrap(err), syscall.ENOENT)
}
func TestCreateConfigControllerTemplateValues(t *testing.T) {
diff --git a/ziti/cmd/create/create_config_router_edge_test.go b/ziti/cmd/create/create_config_router_edge_test.go
index c43a471f7..7a432d163 100644
--- a/ziti/cmd/create/create_config_router_edge_test.go
+++ b/ziti/cmd/create/create_config_router_edge_test.go
@@ -2,11 +2,13 @@ package create
import (
"github.com/openziti/ziti/ziti/constants"
+ "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"strconv"
"strings"
+ "syscall"
"testing"
"time"
)
@@ -215,8 +217,6 @@ func TestEdgeRouterCannotBeWSSAndPrivate(t *testing.T) {
}
func TestEdgeRouterOutputPathDoesNotExist(t *testing.T) {
- expectedErrorMsg := "stat /IDoNotExist: no such file or directory"
-
// Set the router options
routerOptions := clearEnvAndInitializeTestData()
routerOptions.TunnelerMode = defaultTunnelerMode
@@ -225,7 +225,8 @@ func TestEdgeRouterOutputPathDoesNotExist(t *testing.T) {
err := routerOptions.runEdgeRouter(&ConfigTemplateValues{})
- assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err)
+ assert.Error(t, err)
+ assert.Equal(t, errors.Unwrap(err), syscall.ENOENT)
}
func TestExecuteCreateConfigRouterEdgeHasNonBlankTemplateValues(t *testing.T) {
diff --git a/ziti/cmd/create/create_config_router_fabric_test.go b/ziti/cmd/create/create_config_router_fabric_test.go
index 1083c29da..3269d58b1 100644
--- a/ziti/cmd/create/create_config_router_fabric_test.go
+++ b/ziti/cmd/create/create_config_router_fabric_test.go
@@ -2,10 +2,12 @@ package create
import (
"github.com/openziti/ziti/ziti/constants"
+ "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"os"
"strconv"
"strings"
+ "syscall"
"testing"
"time"
)
@@ -94,7 +96,6 @@ func TestBlankFabricRouterNameBecomesHostname(t *testing.T) {
func TestFabricRouterOutputPathDoesNotExist(t *testing.T) {
routerOptions := clearEnvAndInitializeTestData()
- expectedErrorMsg := "stat /IDoNotExist: no such file or directory"
// Set the router options
clearEnvAndInitializeTestData()
@@ -103,7 +104,8 @@ func TestFabricRouterOutputPathDoesNotExist(t *testing.T) {
err := routerOptions.runFabricRouter(&ConfigTemplateValues{})
- assert.EqualError(t, err, expectedErrorMsg, "Error does not match, expected %s but got %s", expectedErrorMsg, err)
+ assert.Error(t, err)
+ assert.Equal(t, errors.Unwrap(err), syscall.ENOENT)
}
func TestDefaultZitiFabricRouterListenerBindPort(t *testing.T) {
diff --git a/ziti/cmd/create/create_config_test.go b/ziti/cmd/create/create_config_test.go
index 69cbb777e..0c06d231e 100644
--- a/ziti/cmd/create/create_config_test.go
+++ b/ziti/cmd/create/create_config_test.go
@@ -1,7 +1,6 @@
package create
import (
- "bytes"
"fmt"
"github.com/stretchr/testify/assert"
"io"
@@ -247,18 +246,61 @@ func contains(s []string, str string) bool {
return false
}
+// captureOutput hot-swaps os.Stdout in order to redirect all output to a memory buffer. Where possible, do not use
+// this function and instead create optional arguments/configuration to redirect output to io.Writer instances. This
+// should only be used for functionality that we do not control. Many instances of its usage are unnecessary and should
+// be remedied with the aforementioned solution where possible.
func captureOutput(function func()) string {
- var buffer bytes.Buffer
oldStdOut := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
+ defer func() {
+ _ = r.Close()
+ }()
+
+ type readResult struct {
+ out []byte
+ err error
+ }
+
+ defer func() {
+ os.Stdout = oldStdOut
+ }()
+
+ var output []byte
+ var outputErr error
+
+ outChan := make(chan *readResult, 1)
+
+ // Start reading before writing, so we do not create backpressure that is never relieved in OSs with smaller buffers
+ // than the resulting configuration file (i.e. Windows). Go will not yield to other routines unless there is
+ // a system call. The fake os.Stdout will never yield and some code paths executed as `function()` may not
+ // have syscalls.
+ go func() {
+ output, outputErr = io.ReadAll(r)
+ outChan <- &readResult{
+ output,
+ outputErr,
+ }
+ }()
+
function()
- _ = w.Close()
os.Stdout = oldStdOut
- _, _ = io.Copy(&buffer, r)
- return buffer.String()
+ _ = w.Close()
+
+ result := <-outChan
+
+ if result == nil {
+ panic("no output")
+ }
+
+ if result.err != nil {
+ panic(result.err)
+ }
+
+ return string(result.out)
}
func setEnvByMap[K string, V string](m map[K]V) {
diff --git a/ziti/cmd/edge/create_enrollment.go b/ziti/cmd/edge/create_enrollment.go
index 4c9dd3952..aa37ea440 100644
--- a/ziti/cmd/edge/create_enrollment.go
+++ b/ziti/cmd/edge/create_enrollment.go
@@ -45,7 +45,8 @@ func newCreateEnrollmentCmd(out io.Writer, errOut io.Writer) *cobra.Command {
type createEnrollmentOptions struct {
api.Options
- duration int64
+ jwtOutputFile string
+ duration int64
}
func newCreateEnrollmentOtt(out io.Writer, errOut io.Writer) *cobra.Command {
@@ -76,6 +77,7 @@ func newCreateEnrollmentOtt(out io.Writer, errOut io.Writer) *cobra.Command {
cmd.Flags().SetInterspersed(true)
options.AddCommonFlags(cmd)
cmd.Flags().Int64VarP(&options.duration, "duration", "d", 30, "the duration of time the enrollment should valid for")
+ cmd.Flags().StringVarP(&options.jwtOutputFile, "jwt-output-file", "o", "", "File to which to output the enrollment JWT ")
return cmd
}
@@ -149,6 +151,11 @@ func runCreateEnrollmentOtt(options *createEnrollmentOptions) error {
panic(err)
}
+ if options.jwtOutputFile != "" {
+ if err = getIdentityJwt(&options.Options, identityId, options.jwtOutputFile, "ott", options.Options.Timeout, options.Options.Verbose); err != nil {
+ return err
+ }
+ }
return err
}
diff --git a/ziti/cmd/edge/create_identity.go b/ziti/cmd/edge/create_identity.go
index e6a675b12..00a2e0977 100644
--- a/ziti/cmd/edge/create_identity.go
+++ b/ziti/cmd/edge/create_identity.go
@@ -18,6 +18,7 @@ package edge
import (
"fmt"
+ "github.com/openziti/ziti/controller/persistence"
"github.com/openziti/ziti/ziti/cmd/api"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
"github.com/pkg/errors"
@@ -109,9 +110,9 @@ func runCreateIdentity(o *createIdentityOptions) error {
o.username = strings.TrimSpace(o.username)
if o.username != "" {
- api.SetJSONValue(entityData, o.username, "enrollment", "updb")
+ api.SetJSONValue(entityData, o.username, "enrollment", persistence.MethodEnrollUpdb)
} else {
- api.SetJSONValue(entityData, true, "enrollment", "ott")
+ api.SetJSONValue(entityData, true, "enrollment", persistence.MethodEnrollOtt)
}
api.SetJSONValue(entityData, o.isAdmin, "isAdmin")
api.SetJSONValue(entityData, o.roleAttributes, "roleAttributes")
@@ -183,15 +184,18 @@ func runCreateIdentity(o *createIdentityOptions) error {
if o.jwtOutputFile != "" {
id := result.S("data", "id").Data().(string)
- if err := getIdentityJwt(o, id, o.Options.Timeout, o.Options.Verbose); err != nil {
+ enrollmentType := persistence.MethodEnrollOtt
+ if o.username != "" {
+ enrollmentType = persistence.MethodEnrollUpdb
+ }
+ if err = getIdentityJwt(&o.Options, id, o.jwtOutputFile, enrollmentType, o.Options.Timeout, o.Options.Verbose); err != nil {
return err
}
}
return err
}
-func getIdentityJwt(o *createIdentityOptions, id string, timeout int, verbose bool) error {
-
+func getIdentityJwt(o *api.Options, id string, outputFile string, enrollmentType string, timeout int, verbose bool) error {
newIdentity, err := DetailEntityOfType("identities", id, o.OutputJSONResponse, o.Out, timeout, verbose)
if err != nil {
return err
@@ -202,10 +206,12 @@ func getIdentityJwt(o *createIdentityOptions, id string, timeout int, verbose bo
}
var dataContainer *gabs.Container
- if o.username != "" {
+ if enrollmentType == persistence.MethodEnrollUpdb {
dataContainer = newIdentity.Path("enrollment.updb.jwt")
- } else {
+ } else if enrollmentType == persistence.MethodEnrollOtt {
dataContainer = newIdentity.Path("enrollment.ott.jwt")
+ } else {
+ return errors.Errorf("unsupported enrollment type '%s'", enrollmentType)
}
data := dataContainer.Data()
@@ -219,8 +225,8 @@ func getIdentityJwt(o *createIdentityOptions, id string, timeout int, verbose bo
return fmt.Errorf("enrollment JWT not present for new identity")
}
- if err := os.WriteFile(o.jwtOutputFile, []byte(jwt), 0600); err != nil {
- fmt.Printf("Failed to write JWT to file(%v)\n", o.jwtOutputFile)
+ if err = os.WriteFile(outputFile, []byte(jwt), 0600); err != nil {
+ fmt.Printf("Failed to write JWT to file(%v)\n", outputFile)
return err
}
diff --git a/ziti/cmd/edge/delete.go b/ziti/cmd/edge/delete.go
index 526a2f5e3..38205b546 100644
--- a/ziti/cmd/edge/delete.go
+++ b/ziti/cmd/edge/delete.go
@@ -30,6 +30,11 @@ import (
"github.com/spf13/cobra"
)
+type deleteOptions struct {
+ *api.Options
+ ignoreMissing bool
+}
+
// newDeleteCmd creates a command object for the "edge controller delete" command
func newDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command {
cmd := &cobra.Command{
@@ -42,11 +47,13 @@ func newDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command {
},
}
- newOptions := func() *api.Options {
- return &api.Options{
- CommonOptions: common.CommonOptions{
- Out: out,
- Err: errOut,
+ newOptions := func() *deleteOptions {
+ return &deleteOptions{
+ Options: &api.Options{
+ CommonOptions: common.CommonOptions{
+ Out: out,
+ Err: errOut,
+ },
},
}
}
@@ -74,7 +81,7 @@ func newDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command {
}
// newDeleteCmdForEntityType creates the delete command for the given entity type
-func newDeleteCmdForEntityType(entityType string, options *api.Options, aliases ...string) *cobra.Command {
+func newDeleteCmdForEntityType(entityType string, options *deleteOptions, aliases ...string) *cobra.Command {
cmd := &cobra.Command{
Use: entityType + " ",
Short: "deletes " + getPlural(entityType) + " managed by the Ziti Edge Controller",
@@ -92,13 +99,14 @@ func newDeleteCmdForEntityType(entityType string, options *api.Options, aliases
// allow interspersing positional args and flags
cmd.Flags().SetInterspersed(true)
options.AddCommonFlags(cmd)
+ cmd.Flags().BoolVar(&options.ignoreMissing, "ignore-missing", false, "don't error if the entity can't be found to be deleted")
cmd.AddCommand(newDeleteWhereCmdForEntityType(entityType, options))
return cmd
}
-func newDeleteWhereCmdForEntityType(entityType string, options *api.Options) *cobra.Command {
+func newDeleteWhereCmdForEntityType(entityType string, options *deleteOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "where ",
Short: "deletes " + getPlural(entityType) + " matching the filter managed by the Ziti Edge Controller",
@@ -120,21 +128,25 @@ func newDeleteWhereCmdForEntityType(entityType string, options *api.Options) *co
}
// runDeleteEntityOfType implements the commands to delete various entity types
-func runDeleteEntityOfType(o *api.Options, entityType string) error {
+func runDeleteEntityOfType(o *deleteOptions, entityType string) error {
var err error
ids := o.Args
if entityType != "terminators" && entityType != "api-sessions" && entityType != "sessions" && entityType != "authenticators" && entityType != "enrollments" {
- if ids, err = mapNamesToIDs(entityType, *o, true, ids...); err != nil {
+ if ids, err = mapNamesToIDs(entityType, *o.Options, true, ids...); err != nil {
return err
}
}
return deleteEntitiesOfType(o, entityType, ids)
}
-func deleteEntitiesOfType(o *api.Options, entityType string, ids []string) error {
+func deleteEntitiesOfType(o *deleteOptions, entityType string, ids []string) error {
for _, id := range ids {
- err := util.ControllerDelete("edge", entityType, id, "", o.Out, o.OutputJSONRequest, o.OutputJSONResponse, o.Timeout, o.Verbose)
+ err, statusCode := util.ControllerDelete("edge", entityType, id, "", o.Out, o.OutputJSONRequest, o.OutputJSONResponse, o.Timeout, o.Verbose)
if err != nil {
+ if statusCode != nil && o.ignoreMissing {
+ o.Printf("delete of %v with id %v: %v\n", boltz.GetSingularEntityType(entityType), id, color.New(color.FgYellow, color.Bold).Sprint("NOT FOUND"))
+ return nil
+ }
o.Printf("delete of %v with id %v: %v\n", boltz.GetSingularEntityType(entityType), id, color.New(color.FgRed, color.Bold).Sprint("FAIL"))
return err
}
@@ -144,7 +156,7 @@ func deleteEntitiesOfType(o *api.Options, entityType string, ids []string) error
}
// runDeleteEntityOfType implements the commands to delete various entity types
-func runDeleteEntityOfTypeWhere(options *api.Options, entityType string) error {
+func runDeleteEntityOfTypeWhere(options *deleteOptions, entityType string) error {
filter := strings.Join(options.Args, " ")
params := url.Values{}
@@ -156,7 +168,7 @@ func runDeleteEntityOfTypeWhere(options *api.Options, entityType string) error {
}
options.Printf("filter returned ")
- pageInfo.Output(options)
+ pageInfo.Output(options.Options)
var ids []string
for _, entity := range children {
diff --git a/ziti/cmd/helpers/env_helpers.go b/ziti/cmd/helpers/env_helpers.go
index b5e8f2a5c..78c90105d 100644
--- a/ziti/cmd/helpers/env_helpers.go
+++ b/ziti/cmd/helpers/env_helpers.go
@@ -28,7 +28,7 @@ import (
func HomeDir() string {
if h := os.Getenv("HOME"); h != "" {
- return h
+ return NormalizePath(h)
}
h := os.Getenv("USERPROFILE") // windows
if h == "" {
diff --git a/ziti/util/rest.go b/ziti/util/rest.go
index 6e4a1b16f..5919e01d8 100644
--- a/ziti/util/rest.go
+++ b/ziti/util/rest.go
@@ -28,8 +28,8 @@ import (
"github.com/go-openapi/strfmt"
"github.com/openziti/edge-api/rest_management_api_client"
"github.com/openziti/edge-api/rest_model"
- fabric_rest_client "github.com/openziti/ziti/controller/rest_client"
"github.com/openziti/ziti/common/version"
+ fabric_rest_client "github.com/openziti/ziti/controller/rest_client"
cmdhelper "github.com/openziti/ziti/ziti/cmd/helpers"
c "github.com/openziti/ziti/ziti/constants"
"gopkg.in/resty.v1"
@@ -546,6 +546,7 @@ func (edgeTransport *edgeTransport) RoundTrip(r *http.Request) (*http.Response,
}
type ApiErrorPayload interface {
+ Error() string
GetPayload() *rest_model.APIErrorEnvelope
}
@@ -573,12 +574,12 @@ func (a RestApiError) Error() string {
if payload := a.ApiErrorPayload.GetPayload(); payload != nil {
if payload.Error == nil {
- return fmt.Sprintf("could not read API error, payload.error was nil: %v", a.Error())
+ return fmt.Sprintf("could not read API error, payload.error was nil: %v", a.ApiErrorPayload.Error())
}
return formatApiError(payload.Error)
}
- return fmt.Sprintf("could not read API error, payload was nil: %v", a.Error())
+ return fmt.Sprintf("could not read API error, payload was nil: %v", a.ApiErrorPayload.Error())
}
func WrapIfApiError(err error) error {
@@ -669,20 +670,20 @@ func ControllerCreate(api API, entityType string, body string, out io.Writer, lo
}
// ControllerDelete will delete entities of the given type in the given Controller
-func ControllerDelete(api API, entityType string, id string, body string, out io.Writer, logRequestJson bool, logResponseJson bool, timeout int, verbose bool) error {
+func ControllerDelete(api API, entityType string, id string, body string, out io.Writer, logRequestJson bool, logResponseJson bool, timeout int, verbose bool) (error, *int) {
restClientIdentity, err := LoadSelectedRWIdentityForApi(api)
if err != nil {
- return err
+ return err, nil
}
baseUrl, err := restClientIdentity.GetBaseUrlForApi(api)
if err != nil {
- return err
+ return err, nil
}
req, err := NewRequest(restClientIdentity, timeout, verbose)
if err != nil {
- return err
+ return err, nil
}
entityPath := entityType + "/" + id
@@ -701,19 +702,20 @@ func ControllerDelete(api API, entityType string, id string, body string, out io
resp, err := req.Delete(fullUrl)
if err != nil {
- return fmt.Errorf("unable to delete %v instance in Ziti Edge Controller at %v. Error: %v", entityPath, baseUrl, err)
+ return fmt.Errorf("unable to delete %v instance in Ziti Edge Controller at %v. Error: %v", entityPath, baseUrl, err), nil
}
if resp.StatusCode() != http.StatusOK {
+ statusCode := resp.StatusCode()
return fmt.Errorf("error deleting %v instance in Ziti Edge Controller at %v. Status code: %v, Server returned: %v",
- entityPath, baseUrl, resp.Status(), PrettyPrintResponse(resp))
+ entityPath, baseUrl, resp.Status(), PrettyPrintResponse(resp)), &statusCode
}
if logResponseJson {
OutputJson(out, resp.Body())
}
- return nil
+ return nil, nil
}
// ControllerUpdate will update entities of the given type in the given Edge Controller
diff --git a/zititest/ami/README.md b/zititest/ami/README.md
deleted file mode 100644
index 4f0bd3816..000000000
--- a/zititest/ami/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Ziti AMI
-
-This folder shows how to use [Packer](https://www.packer.io/) to create an [Amazon Machine
-Image (AMI)](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) that has the necessary prerequisites for running fablab based OpenZiti smoketests installed on top of Ubuntu 22.04.
-
-## Quick start
-
-To build the Ziti AMI:
-
-1. `git clone` this repo to your computer.
-1. Install [Packer](https://www.packer.io/).
-1. Configure your AWS credentials using one of the [options supported by the AWS
- SDK](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html). Usually, the easiest option is to
- set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
-1. Run `packer build ziti-ami.pkr.hcl`.
-
-When the build finishes, it will output the ID of the new AMI.
\ No newline at end of file
diff --git a/zititest/ami/cleanup-old-images.sh b/zititest/ami/cleanup-old-images.sh
deleted file mode 100755
index 0162bce93..000000000
--- a/zititest/ami/cleanup-old-images.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-regions=(
-"us-east-1"
-"us-east-2"
-"us-west-1"
-"us-west-2"
-"ca-central-1"
-"ap-northeast-1"
-"ap-southeast-2"
-"sa-east-1"
-"eu-central-1"
-"af-south-1"
-)
-
-
-for region in ${regions[@]};
-do
- aws ec2 describe-images --region ${region} --owners self --filters Name="name",Values="ziti-tests-*" | jq '[.Images[] | { Id: .ImageId, Date: .CreationDate}] | sort_by(.Date)' | jq -r '.[] | .Id ' | head -n -1 | xargs -t -r -n 1 aws ec2 deregister-image --region ${region} --image-id
-done
diff --git a/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy b/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy
deleted file mode 100644
index ce12e07e0..000000000
--- a/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy
+++ /dev/null
@@ -1,2 +0,0 @@
-Binary::apt::APT::Color "0";
-Binary::apt::DPkg::Progress-Fancy "0";
\ No newline at end of file
diff --git a/zititest/ami/etc/sysctl.d/51-network-tuning.conf b/zititest/ami/etc/sysctl.d/51-network-tuning.conf
deleted file mode 100644
index edc76a389..000000000
--- a/zititest/ami/etc/sysctl.d/51-network-tuning.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# adjust the socket buffer sizes
-net.core.rmem_max = 16777216
-net.core.wmem_max = 16777216
-net.core.rmem_default = 16777216
-net.core.wmem_default = 16777216
-net.ipv4.tcp_rmem = 4096 87380 16777216
-net.ipv4.tcp_wmem = 4096 65536 16777216
-net.ipv4.tcp_mem = 8388608 8388608 16777216
-net.ipv4.udp_mem = 8388608 8388608 16777216
\ No newline at end of file
diff --git a/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf b/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf
deleted file mode 100644
index 0f05e31cc..000000000
--- a/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[Resolve]
-DNS=127.0.0.1
diff --git a/zititest/ami/list-images.sh b/zititest/ami/list-images.sh
deleted file mode 100755
index 11c49393b..000000000
--- a/zititest/ami/list-images.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-regions=(
-"us-east-1"
-"us-west-2"
-)
-
-
-for region in ${regions[@]};
-do
- echo "Region: ${region}"
- aws ec2 describe-images --region ${region} --owners self --filters Name="name",Values="ziti-tests-*" | jq '[.Images[] | { Id: .ImageId, Date: .CreationDate}] | sort_by(.Date)' | jq -r '.[] | (.Id + " " + .Date) '
-done
diff --git a/zititest/ami/ziti-ami.pkr.hcl b/zititest/ami/ziti-ami.pkr.hcl
deleted file mode 100644
index 295da7fe9..000000000
--- a/zititest/ami/ziti-ami.pkr.hcl
+++ /dev/null
@@ -1,76 +0,0 @@
-packer {
- required_version = ">= 1.6.0"
-
- required_plugins {
- amazon = {
- version = ">= 1.1.1"
- source = "github.com/hashicorp/amazon"
- }
- }
-}
-
-source "amazon-ebs" "ziti-tests-ubuntu-ami" {
- ami_description = "An Ubuntu AMI that has everything needed for running fablab smoketests."
- ami_name = "ziti-tests-{{ timestamp }}"
- ami_regions = ["us-east-1", "us-east-2", "us-west-1", "us-west-2", "ca-central-1", "ap-northeast-1", "ap-southeast-2", "sa-east-1", "eu-central-1", "af-south-1"]
- instance_type = "t2.micro"
- region = "us-east-1"
- source_ami_filter {
- filters = {
- architecture = "x86_64"
- name = "ubuntu/images/*/ubuntu-jammy-22.04-amd64-server-*"
- root-device-type = "ebs"
- virtualization-type = "hvm"
- }
- most_recent = true
- owners = ["099720109477"]
- }
- ssh_username = "ubuntu"
-}
-
-build {
- sources = ["source.amazon-ebs.ziti-tests-ubuntu-ami"]
-
- provisioner "file" {
- source = "etc/apt/apt.conf.d/99remote-not-fancy"
- destination = "/home/ubuntu/99remote-not-fancy"
- }
-
- provisioner "file" {
- source = "etc/sysctl.d/51-network-tuning.conf"
- destination = "/home/ubuntu/51-network-tuning.conf"
- }
-
- provisioner "file" {
- source = "etc/systemd/resolved.conf.d/ziti-tunnel.conf"
- destination = "/home/ubuntu/ziti-tunnel.conf"
- }
-
- provisioner "shell" {
- inline = [
- "sudo mv /home/ubuntu/99remote-not-fancy /etc/apt/apt.conf.d/",
- "sudo mv /home/ubuntu/51-network-tuning.conf /etc/sysctl.d/",
- "sudo mkdir /etc/systemd/resolved.conf.d",
- "sudo mv /home/ubuntu/ziti-tunnel.conf /etc/systemd/resolved.conf.d/",
- "sudo chown root.root /etc/systemd/resolved.conf.d/*",
-
- "cloud-init status --wait",
-
- # add metricsbeat sources
- "curl --fail --silent --show-error --location https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor | sudo dd of=/usr/share/keyrings/elasticsearch-archive-keyring.gpg",
- "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/elasticsearch-archive-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main\" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list",
-
- # add consul sources
- "curl --fail --silent --show-error --location https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/hashicorp-archive-keyring.gpg",
- "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee -a /etc/apt/sources.list.d/hashicorp.list",
-
- "sudo apt update",
- "sudo apt upgrade -y",
- "sudo apt install -y iperf3 tcpdump sysstat",
- "sudo apt install -y metricbeat=8.3.2",
- "sudo apt install -y consul",
- "sudo bash -c \"echo 'ubuntu soft nofile 40960' >> /etc/security/limits.conf\"",
- "sudo sed -i 's/ENABLED=\"false\"/ENABLED=\"true\"/g' /etc/default/sysstat",
- ]
- }
-}
diff --git a/zititest/go.mod b/zititest/go.mod
index 93f8522f2..b16ad44e8 100644
--- a/zititest/go.mod
+++ b/zititest/go.mod
@@ -7,24 +7,24 @@ replace github.com/openziti/ziti => ../
require (
github.com/Jeffail/gabs v1.4.0
github.com/Jeffail/gabs/v2 v2.7.0
- github.com/google/go-cmp v0.5.9
- github.com/google/uuid v1.3.1
+ github.com/google/go-cmp v0.6.0
+ github.com/google/uuid v1.4.0
github.com/michaelquigley/pfxlog v0.6.10
- github.com/openziti/agent v1.0.15
- github.com/openziti/channel/v2 v2.0.101
- github.com/openziti/fablab v0.5.16
+ github.com/openziti/agent v1.0.16
+ github.com/openziti/channel/v2 v2.0.105
+ github.com/openziti/fablab v0.5.25
github.com/openziti/foundation/v2 v2.0.33
- github.com/openziti/identity v1.0.64
- github.com/openziti/sdk-golang v0.20.122
- github.com/openziti/storage v0.2.20
- github.com/openziti/transport/v2 v2.0.109
+ github.com/openziti/identity v1.0.66
+ github.com/openziti/sdk-golang v0.20.129
+ github.com/openziti/storage v0.2.23
+ github.com/openziti/transport/v2 v2.0.113
github.com/openziti/ziti v0.28.3
github.com/pkg/errors v0.9.1
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
- go.etcd.io/bbolt v1.3.7
+ go.etcd.io/bbolt v1.3.8
golang.org/x/net v0.17.0
google.golang.org/protobuf v1.31.0
gopkg.in/yaml.v2 v2.4.0
@@ -36,11 +36,11 @@ require (
github.com/MichaelMure/go-term-markdown v0.1.4 // indirect
github.com/MichaelMure/go-term-text v0.3.1 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
- github.com/andybalholm/brotli v1.0.5 // indirect
+ github.com/andybalholm/brotli v1.0.6 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
- github.com/aws/aws-sdk-go v1.45.13 // indirect
+ github.com/aws/aws-sdk-go v1.47.0 // indirect
github.com/biogo/store v0.0.0-20200525035639-8c94ae1e7c9c // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/boltdb/bolt v1.3.1 // indirect
@@ -58,11 +58,11 @@ require (
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
- github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect
github.com/go-acme/lego/v4 v4.14.2 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
- github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
@@ -75,7 +75,7 @@ require (
github.com/go-openapi/strfmt v0.21.7 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
- github.com/go-resty/resty/v2 v2.9.1 // indirect
+ github.com/go-resty/resty/v2 v2.10.0 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect
@@ -94,7 +94,7 @@ require (
github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d // indirect
- github.com/jedib0t/go-pretty/v6 v6.4.8 // indirect
+ github.com/jedib0t/go-pretty/v6 v6.4.9 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/jinzhu/copier v0.4.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@@ -102,16 +102,15 @@ require (
github.com/josharian/native v1.1.0 // indirect
github.com/kataras/go-events v0.0.3 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/klauspost/compress v1.17.0 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/kyokomi/emoji/v2 v2.2.12 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lucsky/cuid v1.2.1 // indirect
- github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
+ github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-tty v0.0.3 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect
@@ -129,11 +128,11 @@ require (
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/openziti/dilithium v0.3.3 // indirect
- github.com/openziti/edge-api v0.25.38 // indirect
+ github.com/openziti/edge-api v0.26.0 // indirect
github.com/openziti/jwks v1.0.3 // indirect
- github.com/openziti/metrics v1.2.36 // indirect
+ github.com/openziti/metrics v1.2.37 // indirect
github.com/openziti/runzmd v1.0.33 // indirect
- github.com/openziti/secretstream v0.1.12 // indirect
+ github.com/openziti/secretstream v0.1.13 // indirect
github.com/openziti/x509-claims v1.0.3 // indirect
github.com/openziti/xweb/v2 v2.1.0 // indirect
github.com/openziti/ziti-db-explorer v1.1.3 // indirect
@@ -194,6 +193,6 @@ require (
gopkg.in/resty.v1 v1.12.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- nhooyr.io/websocket v1.8.7 // indirect
+ nhooyr.io/websocket v1.8.10 // indirect
rsc.io/goversion v1.2.0 // indirect
)
diff --git a/zititest/go.sum b/zititest/go.sum
index 80ab4139e..bd8d036db 100644
--- a/zititest/go.sum
+++ b/zititest/go.sum
@@ -80,8 +80,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
-github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
+github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
@@ -96,8 +96,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/aws/aws-sdk-go v1.45.13 h1:LwD/G+PX7FQnbU8wXekx12e90i1GuKJQC2+pl4IlPAs=
-github.com/aws/aws-sdk-go v1.45.13/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.47.0 h1:/JUg9V1+xh+qBn8A6ec/l15ETPaMaBqxkjz+gg63dNk=
+github.com/aws/aws-sdk-go v1.47.0/go.mod h1:DlEaEbWKZmsITVbqlSVvekPARM1HzeV9PMYg15ymSDA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -192,16 +192,12 @@ github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiD
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
-github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
-github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-acme/lego/v4 v4.14.2 h1:/D/jqRgLi8Cbk33sLGtu2pX2jEg3bGJWHyV8kFuUHGM=
github.com/go-acme/lego/v4 v4.14.2/go.mod h1:kBXxbeTg0x9AgaOYjPSwIeJy3Y33zTz+tMD16O4MO6c=
@@ -217,8 +213,8 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
-github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
+github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
@@ -263,15 +259,8 @@ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogB
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
-github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
-github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
-github.com/go-resty/resty/v2 v2.9.1 h1:PIgGx4VrHvag0juCJ4dDv3MiFRlDmP0vicBucwf+gLM=
-github.com/go-resty/resty/v2 v2.9.1/go.mod h1:4/GYJVjh9nhkhGR6AUNW3XhpDYNUr+Uvy9gV/VGZIy4=
+github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo=
+github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
@@ -297,12 +286,6 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
-github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
-github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
-github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
-github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -363,8 +346,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -386,8 +370,8 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
-github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@@ -402,7 +386,6 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
-github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -464,8 +447,8 @@ github.com/influxdata/influxdb-client-go/v2 v2.2.2/go.mod h1:fa/d1lAdUHxuc1jedx3
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
-github.com/jedib0t/go-pretty/v6 v6.4.8 h1:HiNzyMSEpsBaduKhmK+CwcpulEeBrTmxutz4oX/oWkg=
-github.com/jedib0t/go-pretty/v6 v6.4.8/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
+github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc=
+github.com/jedib0t/go-pretty/v6 v6.4.9/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
@@ -484,7 +467,6 @@ github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2C
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@@ -498,10 +480,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
-github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -523,8 +502,6 @@ github.com/kyokomi/emoji/v2 v2.2.12 h1:sSVA5nH9ebR3Zji1o31wu3yOwD1zKXQA2z0zUyeit
github.com/kyokomi/emoji/v2 v2.2.12/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
-github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
-github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lucas-clemente/quic-go v0.18.0/go.mod h1:yXttHsSNxQi8AWijC/vLP+OJczXqzHSOcJrM5ITUlCg=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
@@ -532,8 +509,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i
github.com/lucsky/cuid v1.2.1 h1:MtJrL2OFhvYufUIn48d35QGXyeTC8tn0upumW9WwTHg=
github.com/lucsky/cuid v1.2.1/go.mod h1:QaaJqckboimOmhRSJXSx/+IT+VTfxfPGSo/6mfgUfmE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
-github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik=
-github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
+github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
+github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@@ -571,8 +548,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
@@ -615,11 +592,9 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM=
github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM=
@@ -649,34 +624,34 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
-github.com/openziti/agent v1.0.15 h1:NW4egpS3Mw1RQBZWfUEvrmBh9kn/SU/dU5fndsyyhZ4=
-github.com/openziti/agent v1.0.15/go.mod h1:zfm53+PVWoGFzjGGgQdKby5749G6VRYHe+eQJmoVKy4=
-github.com/openziti/channel/v2 v2.0.101 h1:UaveW/ogYKVtCQZfwRoMhsZhj/tvs1bD7SvH0aLaYNw=
-github.com/openziti/channel/v2 v2.0.101/go.mod h1:b9CBWpH6tnLqCHInDKL6AzMGqXdbEjsul3yVQUGENVU=
+github.com/openziti/agent v1.0.16 h1:9Saji+8hFE1NpzP2XzDhsVJbCrDlhixoLHfOpFt5Z+U=
+github.com/openziti/agent v1.0.16/go.mod h1:zfm53+PVWoGFzjGGgQdKby5749G6VRYHe+eQJmoVKy4=
+github.com/openziti/channel/v2 v2.0.105 h1:WT2zFF7krZkYUfuXA+4tQxhYiiVWlldD3mKX3qJU9Ww=
+github.com/openziti/channel/v2 v2.0.105/go.mod h1:++bV6FFgGUNxaBu7iOkkCa6rSiueU34Kd6f2LSCrEtU=
github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k=
github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo=
-github.com/openziti/edge-api v0.25.38 h1:aijFEC4pMCi2gR6zL6FYQRkm59SQAwrF0tZS4LZsxi4=
-github.com/openziti/edge-api v0.25.38/go.mod h1:5mmcMgqK1MsBb0K8V1CBfGbtRUji5KYdmhJJJkJBMqY=
-github.com/openziti/fablab v0.5.16 h1:+tqqDR5Sl4qLT3fSC+Dv1AGZuOeeX87h9LNKa1KJS5Y=
-github.com/openziti/fablab v0.5.16/go.mod h1:KiU/NxThNtH9U803Ep0WcSrbov3moZso2oRgIpQq0S0=
+github.com/openziti/edge-api v0.26.0 h1:082hXjj8rnyMBZHYiB6jb4n7mCXtdMXpF2iCqZOv4IM=
+github.com/openziti/edge-api v0.26.0/go.mod h1:/e1pK92L471fvOAwE/hLX5sqBuuo+NwI8vmL04dUHsM=
+github.com/openziti/fablab v0.5.25 h1:KxbhNFeX40TlB1Ot+KnEZos0LYtTs77dNekIMRDLvEg=
+github.com/openziti/fablab v0.5.25/go.mod h1:uUY3gr4IcGL6vsxBX7gA/b/StF0mHsICkW8HZBvkx9o=
github.com/openziti/foundation/v2 v2.0.33 h1:8CP+fi4KsmzA4jDi54jibwFWWxKpd0rSiplzN9Z0Isw=
github.com/openziti/foundation/v2 v2.0.33/go.mod h1:dWR0g3NOka3uKz9MgUHq6dmuRLmSvunkyeuOXEW/5qU=
-github.com/openziti/identity v1.0.64 h1:HwALRY1J/rNNcIAlr1OwCwTHU/rlMRaUi5TXAfZotjw=
-github.com/openziti/identity v1.0.64/go.mod h1:t/mW5mCpCbcRrssj4EpzfrmebI7+UKXGH2twll7IQIo=
+github.com/openziti/identity v1.0.66 h1:wCIVNCoiHmeicC9yM15FC0xe6jSic879ztN63fSD6hM=
+github.com/openziti/identity v1.0.66/go.mod h1:grReHVqBwhECrnrAZCxNw4ZpA2I1ox66tYfPkfGuKJY=
github.com/openziti/jwks v1.0.3 h1:hf8wkb+Cg4nH/HM0KROFd7u+C3DkRVcFZJ7tDV+4icc=
github.com/openziti/jwks v1.0.3/go.mod h1:t4xxq8vlXGsPn29kiQVnZBBDDnEoOFqtJoHibkJunQQ=
-github.com/openziti/metrics v1.2.36 h1:oW5YM9H8IqtFuxIyo0rMC3mTpl3rdSnDKcHp+ZTn+JM=
-github.com/openziti/metrics v1.2.36/go.mod h1:fjYG6sUC/n6VXe0nZbYGEBaopbRThBo/3xt7o9VatRQ=
+github.com/openziti/metrics v1.2.37 h1:5yWvMwQT6X43LDlNVcUtqAPJQXfKtbWSYoCIiOfXztg=
+github.com/openziti/metrics v1.2.37/go.mod h1:jIL9iilxby8tR98C18uZaSe6bRG15ItR8XF2hmMt8vs=
github.com/openziti/runzmd v1.0.33 h1:tOyjRoUuVXIo1z1pNU32jALWkMmhzsSaDrhLtuOn3Ts=
github.com/openziti/runzmd v1.0.33/go.mod h1:8c/uvZR/XWXQNllTq6LuTpfKL2DTNxfI2X2wYhgRwik=
-github.com/openziti/sdk-golang v0.20.122 h1:fuxws2yFEFl4hdq4l96/N23ztC1oUiQIM/lePTI6rBY=
-github.com/openziti/sdk-golang v0.20.122/go.mod h1:n6Ft+Gz7e2JO6DQ6Ixc9oIn06I1MjzkI3V9kilkOBIQ=
-github.com/openziti/secretstream v0.1.12 h1:N78CHxtqWzSyNFOsYtYRWNNTfX1ZDAPkFgzHobpodZU=
-github.com/openziti/secretstream v0.1.12/go.mod h1:gHMH1REH0r4VlmCtuWx8biU7j5ZfOivFjz9mLgwq7mk=
-github.com/openziti/storage v0.2.20 h1:xpLczyF/czIw76M4Rrt2urYn/EvGNor+SPzoixuOkLs=
-github.com/openziti/storage v0.2.20/go.mod h1:UO8D6h4AAf5OT1iJg1sppKoEPC2YWaBGZFLK7rPyk5M=
-github.com/openziti/transport/v2 v2.0.109 h1:12ZdM9R7lETKP7cT2xsGlTX/4w2qBtC8nThxw8RG77Q=
-github.com/openziti/transport/v2 v2.0.109/go.mod h1:r1jay/cSzkw15SJLtbk/I9YZtMIYjhueqAqfWtO5ioE=
+github.com/openziti/sdk-golang v0.20.129 h1:FjvXsGFxEiHq89sNyLSvNymruACFW5tbhkgZ3VCg2pE=
+github.com/openziti/sdk-golang v0.20.129/go.mod h1:ZpJ7HCcIQbp8XiSno3YXkfhoDIbgjCjS2ScK2bda8eo=
+github.com/openziti/secretstream v0.1.13 h1:grp53Q5gCFPXv6okwWHDVvqBBk2BhD0ikHwfV3Adhnc=
+github.com/openziti/secretstream v0.1.13/go.mod h1:M4DYavDc3TVF/eemNqp5Fa+zGuYTNa0HTGSz/GkgUzA=
+github.com/openziti/storage v0.2.23 h1:R5ZBGDGC/LvOz3fE/GlevwbPZ3HL7VxYEvlhKuezvNU=
+github.com/openziti/storage v0.2.23/go.mod h1:NZCrN2dLtRU73McVEflK5prDgYds9J54mMNz5DmgvZE=
+github.com/openziti/transport/v2 v2.0.113 h1:xFPd1W00KqkFb62rRsRXmLqfgr9d9uk0CAVZegvtGhA=
+github.com/openziti/transport/v2 v2.0.113/go.mod h1:TSDHV7RTGg/FinzfOP8cg86O53BCabXedANh3eUNics=
github.com/openziti/x509-claims v1.0.3 h1:HNdQ8Nf1agB3lBs1gahcO6zfkeS4S5xoQ2/PkY4HRX0=
github.com/openziti/x509-claims v1.0.3/go.mod h1:Z0WIpBm6c4ecrpRKrou6Gk2wrLWxJO/+tuUwKh8VewE=
github.com/openziti/xweb/v2 v2.1.0 h1:Xhh3C2pZkq/Prr65V+SfFSibLDYteoc4f62KQCcTZF4=
@@ -872,10 +847,6 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
-github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
-github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
-github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
@@ -910,8 +881,8 @@ github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
github.com/zitadel/oidc/v2 v2.7.0 h1:IGX4EDk6tegTjUSsZDWeTfLseFU0BdJ/Glf1tgys2lU=
github.com/zitadel/oidc/v2 v2.7.0/go.mod h1:zkUkVJS0sDVy9m0UA9RgO3f8i/C0rtjvXU36UJj7T+0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
-go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
+go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
@@ -976,7 +947,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1079,7 +1049,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1195,7 +1164,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1209,7 +1177,6 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1231,8 +1198,8 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1470,8 +1437,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
-nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
+nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
+nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=
rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
diff --git a/zititest/models/db-creation/README.md b/zititest/models/db-creation/README.md
new file mode 100644
index 000000000..b5f37c990
--- /dev/null
+++ b/zititest/models/db-creation/README.md
@@ -0,0 +1,50 @@
+# db-creation model
+
+### This model is designed to be used for GitHub Actions to create a test DB and export the pki/identities/DB to s3 buckets for later testing usage. ###
+
+- Only setup for AWS.
+- Designed to work with the pete-iperf branch of fablab.
+- You will need to supply your own keys/secrets.
+- Infrastructure is configured in the main.go in the model.
+- This is a very alpha release, minimal features.
+
+### There are several files that will likely need to be customized for your setup: ###
+
+- ziti/zititest/models/db-creation/main.go - mainly used to alter the model and also your Rsync and Disposal Actions (removing Route 53 A Record)
+- ziti/zititest/models/db-creation/actions/bootstrap.go - This is where the meat of the actions take place. Sets up AWS remotely from the GH Runner (using Fablab executable), then runs the DB Creation Script.
+- ziti/zititest/models/db-creation/resources/db_creator_script_external.sh - This is the script that interacts with Ziti and creates all the identities, services and policies.
+- ziti/zititest/models/db-creation/resources/aws_setup.sh - This will default to us-east-1 region and use JSON output, if you want to change those values do that here.
+- ziti/.github/workflows/fablab-db-creation.yml - This is where you will setup your GitHub workflow specifics, inserting your custom secret variable names, etc. As you can see at the end, the following 3 Fablab commands are all that is needed to run this:
+ - ```./db-creation create db-creation```
+ - ```./db-creation up```
+ - ```./db-creation dispose```
+
+### Once the DB is saved in s3, you will need to pull that and the pki from the proper buckets via the following steps:
+
+#### Non Fablab import (manual) or something designed by you ####
+- Make sure AWS CLI is configured on the machine you want the DB imported to.
+- cd to the /home/ubuntu/fablab directory which is where the DB lies.
+- Stop any existing Ziti processes.
+- Simply delete the old DB file or rename it.
+- Run the following AWS CLI command to import DB:
+ - ```aws s3 cp s3://db-bucket-name/ctrl.db-filename ctrl.db ```
+- Remove the contents of the entire pki directory using the following:
+ - ```cd pki```
+ - ```sudo rm -rf *```
+ - ```cd ..```
+- Run the following to import the pki directory (replacing pki-s3-bucket-name/pki-folder-name with your names) :
+ - ```aws s3 cp --recursive s3://pki-s3-bucket-name/pki-s3-folder-name/ pki/```
+- Run the following command while replacing the ziti version number in filename to start the controller:
+ - ```nohup /home/ubuntu/fablab/bin/ziti-v0.28.4 controller run --log-formatter pfxlog /home/ubuntu/fablab/cfg/ctrl.yml --cli-agent-alias ctrl > /home/ubuntu/logs/ctrl.log 2>&1 & ```
+
+#### Fablab import ####
+- cd into your local ziti/zititest/models/db-creation/resources folder and then import both the DB and PKI from your s3 buckets:
+ - Command to run for your DB import:
+ - ```aws s3 cp s3://s3-db-bucket-name/s3-ctrl.db-filename ctrl.db```
+ - Commands to run for your PKI import:
+ - ```mkdir pki```
+ - ```aws s3 cp --recursive s3://pki-s3-bucket-name/pki-s3-folder-name/ pki/```
+- Within your main.go for the db-creation model, you should uncomment the 2 following lines within the Distribution portion of the model, around line 123 or so:
+ - ```rsync.NewRsyncHost("#ctrl", "resources/ctrl.db", "/home/ubuntu/fablab/ctrl.db"),```
+ - ```rsync.NewRsyncHost("#ctrl", "resources/pki/", "/home/ubuntu/fablab/pki/"),```
+- Now you should be able to create a fresh db-creation executable by building and run that, which should have the new DB/PKI.
\ No newline at end of file
diff --git a/zititest/models/db-creation/actions/bootstrap.go b/zititest/models/db-creation/actions/bootstrap.go
new file mode 100644
index 000000000..c532913b5
--- /dev/null
+++ b/zititest/models/db-creation/actions/bootstrap.go
@@ -0,0 +1,178 @@
+/*
+ (c) Copyright NetFoundry Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package actions
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/openziti/fablab/kernel/lib/actions"
+ "github.com/openziti/fablab/kernel/lib/actions/component"
+ "github.com/openziti/fablab/kernel/lib/actions/host"
+ "github.com/openziti/fablab/kernel/lib/actions/semaphore"
+ "github.com/openziti/fablab/kernel/model"
+ "github.com/openziti/ziti/zititest/zitilab"
+ zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions"
+ "github.com/openziti/ziti/zititest/zitilab/actions/edge"
+ "github.com/openziti/ziti/zititest/zitilab/models"
+ "os"
+ "time"
+)
+
+const DomainName = "controller.testing.openziti.org"
+const Create = "CREATE"
+const Delete = "DELETE"
+
+type bootstrapAction struct{}
+
+// Define a struct to represent the nested "ResourceRecordSet" object
+type ResourceRecordSet struct {
+ Name string `json:"Name"`
+ Type string `json:"Type"`
+ TTL int `json:"TTL"`
+ ResourceRecords []struct {
+ Value string `json:"Value"`
+ } `json:"ResourceRecords"`
+}
+
+// Define a struct to represent the nested "Changes" object
+type Change struct {
+ Action string `json:"Action"`
+ ResourceRecordSet ResourceRecordSet `json:"ResourceRecordSet"`
+}
+
+// Define the main Payload struct to represent the entire JSON payload
+type Payload struct {
+ Changes []Change `json:"Changes"`
+}
+
+func NewBootstrapAction() model.ActionBinder {
+ action := &bootstrapAction{}
+ return action.bind
+}
+
+func Route53StringCreator(m *model.Model, action string) string {
+ var payload = Payload{
+ Changes: []Change{
+ {
+ Action: action,
+ ResourceRecordSet: ResourceRecordSet{
+ Name: DomainName, // The DNS record name
+ Type: "A", // Type A represents an IPv4 address
+ TTL: 300, // TTL value in seconds
+ ResourceRecords: []struct {
+ Value string `json:"Value"`
+ }{
+ {Value: m.MustSelectHost("#ctrl").PublicIp},
+ },
+ },
+ },
+ },
+ }
+ jsonData, err := json.MarshalIndent(payload, "", " ")
+ if err != nil {
+ fmt.Println("Error marshaling struct to JSON:", err)
+ }
+ dnsAddJsonData := string(jsonData)
+ s := "aws route53 change-resource-record-sets --hosted-zone-id Z09612893W445K5ME8MYS --change-batch '" + dnsAddJsonData + "'"
+ return s
+}
+
+func (a *bootstrapAction) bind(m *model.Model) model.Action {
+ workflow := actions.Workflow()
+ // Set AWS config remotely
+ accessKey := os.Getenv("S3_KEY")
+ if accessKey != "" {
+ fmt.Println("S3_KEY", accessKey)
+ } else {
+ fmt.Println("S3_KEY missing")
+ }
+ accessSecret := os.Getenv("S3_SECRET")
+ if accessSecret != "" {
+ fmt.Println("S3_SECRET", accessSecret)
+ } else {
+ fmt.Println("S3_SECRET missing")
+ }
+ accessKeyIDString := "export AWS_ACCESS_KEY_ID=" + accessKey
+ accessSecretString := "export AWS_SECRET_ACCESS_KEY=" + accessSecret
+ setAccessKeyIDString := "aws configure set aws_access_key_id " + accessKey
+ setAccessSecretString := "aws configure set aws_secret_access_key " + accessSecret
+ workflow.AddAction(host.GroupExec("#ctrl", 1, accessKeyIDString))
+ workflow.AddAction(host.GroupExec("#ctrl", 1, accessSecretString))
+ workflow.AddAction(host.GroupExec("#ctrl", 1, setAccessKeyIDString))
+ workflow.AddAction(host.GroupExec("#ctrl", 1, setAccessSecretString))
+ workflow.AddAction(host.GroupExec("#ctrl", 1, "aws configure set default.region us-east-1"))
+ workflow.AddAction(host.GroupExec("#ctrl", 1, "aws configure set default.output json"))
+
+ // Run aws_setup script - passing in AWS Key and Secret
+ awsScriptExecutionText := "sudo /home/ubuntu/fablab/bin/aws_setup.sh " + accessKey + " " + accessSecret
+ workflow.AddAction(host.GroupExec("#ctrl", 1, "sudo chmod 0755 /home/ubuntu/fablab/bin/aws_setup.sh"))
+ workflow.AddAction(host.GroupExec("#ctrl", 1, awsScriptExecutionText))
+
+ //Add Route53 DNS A Record
+ workflow.AddAction(model.ActionFunc(func(run model.Run) error {
+ m := run.GetModel()
+ s := Route53StringCreator(m, Create)
+ return host.Exec(m.MustSelectHost("#ctrl"), s).Execute(run)
+ }))
+
+ //Start Ziti Controller
+ workflow.AddAction(host.GroupExec("#ctrl", 1, "rm -f logs/*"))
+ workflow.AddAction(component.Stop("#ctrl"))
+ workflow.AddAction(component.Exec("#ctrl", zitilab.ControllerActionInitStandalone))
+ workflow.AddAction(component.Start("#ctrl"))
+ workflow.AddAction(edge.ControllerAvailable("#ctrl", 30*time.Second))
+
+ // Login to Ziti Controller
+ workflow.AddAction(edge.Login("#ctrl"))
+ workflow.AddAction(semaphore.Sleep(2 * time.Second))
+
+ // Setup Ziti Routers
+ workflow.AddAction(component.StopInParallel(models.EdgeRouterTag, 25))
+ workflow.AddAction(edge.InitEdgeRouters(models.EdgeRouterTag, 2))
+ workflow.AddAction(semaphore.Sleep(2 * time.Second))
+
+ // Init Identities
+ workflow.AddAction(edge.InitIdentities(models.SdkAppTag, 2))
+ workflow.AddAction(semaphore.Sleep(2 * time.Second))
+
+ // Create Configs
+ workflow.AddAction(zitilib_actions.Edge("create", "config", "iperf-server", "host.v1", `
+ {
+ "address" : "localhost",
+ "port" : 7001,
+ "protocol" : "tcp"
+ }`))
+ workflow.AddAction(semaphore.Sleep(2 * time.Second))
+ workflow.AddAction(zitilib_actions.Edge("create", "config", "iperf-intercept", "intercept.v1", `
+ {
+ "addresses": ["iperf.service"],
+ "portRanges" : [
+ { "low": 7001, "high": 7001 }
+ ],
+ "protocols": ["tcp"]
+ }`))
+ workflow.AddAction(semaphore.Sleep(2 * time.Second))
+
+ // Start Beats Services
+ workflow.AddAction(host.GroupExec("ctrl", 25, "sudo service filebeat stop; sleep 5; sudo service filebeat start"))
+ workflow.AddAction(host.GroupExec("ctrl", 25, "sudo service metricbeat stop; sleep 5; sudo service metricbeat start"))
+
+ // Run DB Creation Shell script
+ workflow.AddAction(host.GroupExec("ctrl", 1, "sudo chmod 0755 /home/ubuntu/fablab/bin/db_creator_script_external.sh"))
+ workflow.AddAction(host.GroupExec("ctrl", 1, "sudo /home/ubuntu/fablab/bin/db_creator_script_external.sh"))
+ return workflow
+}
diff --git a/zititest/models/db-creation/configs/ctrl.yml.tmpl b/zititest/models/db-creation/configs/ctrl.yml.tmpl
new file mode 100644
index 000000000..8e2f46c7b
--- /dev/null
+++ b/zititest/models/db-creation/configs/ctrl.yml.tmpl
@@ -0,0 +1,194 @@
+v: 3
+
+db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrl.db
+
+identity:
+ cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/certs/{{ .Component.Id }}-server.cert
+ key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/keys/{{ .Component.Id }}-server.key
+ ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/certs/{{ .Component.Id }}-server.chain.pem
+
+# the endpoint that routers will connect to the controller over.
+ctrl:
+ listener: tls:0.0.0.0:6262
+ options:
+ advertiseAddress: tls:{{.Host.PublicIp}}:6262
+ # (optional) settings
+ # set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000)
+ #maxQueuedConnects: 50
+
+ # the maximum number of connects that have begun hello synchronization (1 to 1000, default 16)
+ #maxOutstandingConnects: 100
+
+ # the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms)
+ #connectTimeoutMs: 3000
+
+ # Sets the control channel write timeout. A write timeout will close the control channel, so the router will reconnect
+ #writeTimeout: 15s
+
+ # A listener address which will be sent to connecting routers in order to change their configured controller
+ # address. If defined, routers will update address configuration to immediately use the new address for future
+ # connections. The value of newListener must be resolvable both via DNS and validate via certificates
+ #newListener: tls:localhost:6262
+
+#events:
+# jsonLogger:
+# subscriptions:
+# - type: fabric.routers
+# - type: fabric.terminators
+# - type: metrics
+# sourceFilter: .*
+# metricFilter: .*egress.*m1_rate*
+# - type: fabric.circuits
+# include:
+# - created
+# - type: edge.sessions
+# include:
+# - created
+# - type: edge.apiSessions
+# - type: fabric.usage
+# - type: services
+# - type: fabric.usage
+# - type: edge.entityCounts
+# interval: 5s
+# handler:
+# type: file
+# format: json
+# path: /tmp/ziti-events.log
+
+healthChecks:
+ boltCheck:
+ # How often to try entering a bolt read tx. Defaults to 30 seconds
+ interval: 30s
+ # When to timeout the check. Defaults to 15 seconds
+ timeout: 15s
+ # How long to wait before starting the check. Defaults to 15 seconds
+ initialDelay: 15s
+
+# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this
+# section, commenting out, or altering the name of the section will cause the edge to not run.
+edge:
+ # This section represents the configuration of the Edge API that is served over HTTPS
+ api:
+ #(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted
+ # activityUpdateInterval: 90s
+ #(optional, default 250) The number of API Sessions updated for last activity per transaction
+ # activityUpdateBatchSize: 250
+ # sessionTimeout - optional, default 10m
+ # The number of minutes before an Edge API session will timeout. Timeouts are reset by
+ # API requests and connections that are maintained to Edge Routers
+ sessionTimeout: 30m
+ # address - required
+ # The default address (host:port) to use for enrollment for the Client API. This value must match one of the addresses
+ # defined in a bind point's address field for the `edge-client` API in the web section.
+ address: {{.Host.PublicIp}}:1280
+ # enrollment - required
+ # A section containing settings pertaining to enrollment.
+ enrollment:
+ # signingCert - required
+ # A Ziti Identity configuration section that specifically makes use of the cert and key fields to define
+ # a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert
+ # will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller.
+ signingCert:
+ cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/certs/ctrl.cert
+ key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/keys/ctrl.key
+
+ # edgeIdentity - optional
+ # A section for identity enrollment specific settings
+ edgeIdentity:
+ # duration - optional, default 5m
+ # The length of time that a Ziti Edge Identity enrollment should remain valid. After
+ # this duration, the enrollment will expire and not longer be usable.
+ duration: 5m
+ # edgeRouter - Optional
+ # A section for edge router enrollment specific settings.
+ edgeRouter:
+ # duration - optional, default 5m
+ # The length of time that a Ziti Edge Router enrollment should remain valid. After
+ # this duration, the enrollment will expire and not longer be usable.
+ duration: 5m
+
+
+# web - optional
+# Defines webListeners that will be hosted by the controller. Each webListener can host many APIs and be bound to many
+# bind points.
+web:
+ # name - required
+ # Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested.
+ - name: all-apis-localhost
+ # bindPoints - required
+ # One or more bind points are required. A bind point specifies an interface (interface:port string) that defines
+ # where on the host machine the webListener will listen and the address (host:port) that should be used to
+ # publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for
+ # incoming address resolution as well as used in responses in the API.
+ bindPoints:
+ #interface - required
+ # A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces
+ - interface: 0.0.0.0:1280
+
+ # address - required
+ # The public address that external incoming requests will be able to resolve. Used in request processing and
+ # response content that requires full host:port/path addresses.
+ address: {{.Host.PublicIp}}:1280
+
+ # newAddress - optional
+ # A host:port string which will be sent out as an HTTP header "ziti-new-address" if specified. If the header
+ # is present, clients should update location configuration to immediately use the new address for future
+ # connections. The value of newAddress must be resolvable both via DNS and validate via certificates
+ #newAddress: localhost:1280
+ # identity - optional
+ # Allows the webListener to have a specific identity instead of defaulting to the root `identity` section.
+ # identity:
+ # cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-client.cert.pem
+ # server_cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-server.cert.pem
+ # key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/ctrl.key.pem
+ # ca: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ca-chain.cert.pem
+ # options - optional
+ # Allows the specification of webListener level options - mainly dealing with HTTP/TLS settings. These options are
+ # used for all http servers started by the current webListener.
+ options:
+ # idleTimeout - optional, default 5000ms
+ # The maximum amount of idle time in milliseconds allowed for pipelined HTTP requests. Setting this too high
+ # can cause resources on the host to be consumed as clients remain connected and idle. Lowering this value
+ # will cause clients to reconnect on subsequent HTTPs requests.
+ idleTimeout: 5000ms #http timeouts, new
+
+ # readTimeout - optional, default 5000ms
+ # The maximum amount of time in milliseconds http servers will wait to read the first incoming requests. A higher
+ # value risks consuming resources on the host with clients that are acting bad faith or suffering from high latency
+ # or packet loss. A lower value can risk losing connections to high latency/packet loss clients.
+
+ readTimeout: 5000ms
+ # writeTimeout - optional, default 10000ms
+ # The total maximum time in milliseconds that the http server will wait for a single requests to be received and
+ # responded too. A higher value can allow long running requests to consume resources on the host. A lower value
+ # can risk ending requests before the server has a chance to respond.
+
+ writeTimeout: 100000ms
+ # minTLSVersion - optional, default TSL1.2
+ # The minimum version of TSL to support
+
+ minTLSVersion: TLS1.2
+ # maxTLSVersion - optional, default TSL1.3
+ # The maximum version of TSL to support
+
+ maxTLSVersion: TLS1.3
+ # apis - required
+ # Allows one or more APIs to be bound to this webListener
+ apis:
+ # binding - required
+ # Specifies an API to bind to this webListener. Built-in APIs are
+ # - health-checks
+ # - edge-management
+ # - edge-client
+ # - fabric-management
+ - binding: health-checks
+ options: {}
+ - binding: fabric
+ - binding: edge-management
+ # options - variable optional/required
+ # This section is used to define values that are specified by the API they are associated with.
+ # These settings are per API. The example below is for the `edge-api` and contains both optional values and
+ # required values.
+ options: {}
+ - binding: edge-client
+ options: {}
diff --git a/zititest/models/db-creation/configs/router.yml.tmpl b/zititest/models/db-creation/configs/router.yml.tmpl
new file mode 100644
index 000000000..788799f78
--- /dev/null
+++ b/zititest/models/db-creation/configs/router.yml.tmpl
@@ -0,0 +1,70 @@
+{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}}
+{{$identity := .Component.Id}}
+{{$ctrl_ip := publicIp "component#ctrl"}}
+{{$router_ip := .Host.PublicIp}}
+
+v: 3
+
+enableDebugOps: true
+
+identity:
+ cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-client.cert
+ server_cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.cert
+ key: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}.key
+ ca: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.chain.pem
+
+ctrl:
+ endpoint: tls:{{$ctrl_ip}}:6262
+
+healthChecks:
+ ctrlPingCheck:
+ # How often to ping the controller over the control channel. Defaults to 30 seconds
+ interval: 30s
+ # When to timeout the ping. Defaults to 15 seconds
+ timeout: 15s
+ # How long to wait before pinging the controller. Defaults to 15 seconds
+ initialDelay: 15s
+
+metrics:
+ reportInterval: 15s
+ messageQueueSize: 10
+
+link:
+ listeners:
+ - binding: transport
+ bind: tls:0.0.0.0:6000
+ advertise: tls:{{$router_ip}}:6000
+ dialers:
+ - binding: transport
+
+listeners:
+{{if .Component.HasTag "tunneler"}}
+ - binding: tunnel
+ options:
+ mode: tproxy
+{{end}}
+ - binding: edge
+ address: tls:0.0.0.0:6262
+ options:
+ # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section.
+ advertise: {{ .Host.PublicIp }}:6262
+
+# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this
+# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge
+# Router.
+edge:
+ # (required) Information used to generate the initial registration CSR. For documentation on these fields please
+ # refer to the openssl documentation. These values MUST be supplied and have no defaults.
+ csr:
+ country: US
+ province: NC
+ locality: Charlotte
+ organization: NetFoundry
+ organizationalUnit: Ziti
+
+ # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches
+ # the edge listeners "advertise" value from the "listeners" section.
+ sans:
+ ip:
+ - {{ .Host.PublicIp }}
+
diff --git a/zititest/models/simple/configs/ziti.hcl b/zititest/models/db-creation/configs/ziti.hcl
similarity index 100%
rename from zititest/models/simple/configs/ziti.hcl
rename to zititest/models/db-creation/configs/ziti.hcl
diff --git a/zititest/models/db-creation/main.go b/zititest/models/db-creation/main.go
new file mode 100644
index 000000000..10d8b4146
--- /dev/null
+++ b/zititest/models/db-creation/main.go
@@ -0,0 +1,129 @@
+package main
+
+import (
+ "embed"
+ "github.com/openziti/fablab"
+ "github.com/openziti/fablab/kernel/lib/actions/component"
+ "github.com/openziti/fablab/kernel/lib/actions/host"
+ "github.com/openziti/fablab/kernel/lib/binding"
+ "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key"
+ semaphore_0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore"
+ terraform_0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform"
+ distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution"
+ "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync"
+ aws_ssh_key2 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key"
+ "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform"
+ "github.com/openziti/fablab/kernel/model"
+ "github.com/openziti/fablab/resources"
+ "github.com/openziti/ziti/zititest/models/db-creation/actions"
+ "github.com/openziti/ziti/zititest/models/test_resources"
+ "github.com/openziti/ziti/zititest/zitilab"
+ "github.com/openziti/ziti/zititest/zitilab/actions/edge"
+ "os"
+ "path"
+ "time"
+)
+
+//go:embed configs
+var configResource embed.FS
+
+// Definition of the model, which houses most you need to run things.
+var m = &model.Model{
+ Id: "db-creation",
+ Scope: model.Scope{
+ Defaults: model.Variables{
+ "environment": "db-creation",
+ "credentials": model.Variables{
+ "ssh": model.Variables{
+ "username": "ubuntu",
+ },
+ "edge": model.Variables{
+ "username": "admin",
+ "password": "admin",
+ },
+ "aws": model.Variables{
+ "managed_key": true,
+ },
+ },
+ },
+ },
+
+ StructureFactories: []model.Factory{
+ //model.NewScaleFactoryWithDefaultEntityFactory(scaleStrategy{}),
+ },
+
+ Factories: []model.Factory{
+ //newStageFactory(),
+ },
+
+ Resources: model.Resources{
+ resources.Configs: resources.SubFolder(configResource, "configs"),
+ resources.Binaries: os.DirFS(path.Join(os.Getenv("GOPATH"), "bin")),
+ resources.Terraform: test_resources.TerraformResources(),
+ },
+
+ Regions: model.Regions{
+ "us-east-1": {
+ Region: "us-east-1",
+ Site: "us-east-1a",
+ Hosts: model.Hosts{
+ "ctrl": {
+ InstanceType: "t3.micro",
+ Components: model.Components{
+ "ctrl": {
+ Scope: model.Scope{Tags: model.Tags{"ctrl"}},
+ Type: &zitilab.ControllerType{
+ ConfigSourceFS: nil,
+ ConfigSource: "",
+ ConfigName: "",
+ Version: os.Getenv("ZITI_VERSION"),
+ LocalPath: "",
+ DNSNames: []string{actions.DomainName},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+
+ Actions: model.ActionBinders{
+ "bootstrap": actions.NewBootstrapAction(),
+ "stop": model.Bind(component.StopInParallel("ctrl", 1)),
+ "login": model.Bind(edge.Login("#ctrl")),
+ },
+
+ Infrastructure: model.Stages{
+ aws_ssh_key.Express(),
+ terraform_0.Express(),
+ semaphore_0.Restart(90 * time.Second),
+ },
+
+ Distribution: model.Stages{
+ distribution.DistributeSshKey("*"),
+ distribution.Locations("*", "logs"),
+ rsync.RsyncStaged(),
+ //rsync.NewRsyncHost("#ctrl", "resources/ctrl.db", "/home/ubuntu/fablab/ctrl.db"),
+ //rsync.NewRsyncHost("#ctrl", "resources/pki/", "/home/ubuntu/fablab/pki/"),
+ rsync.NewRsyncHost("#ctrl", "resources/aws_setup.sh", "/home/ubuntu/fablab/bin/aws_setup.sh"),
+ rsync.NewRsyncHost("#ctrl", "resources/db_creator_script_external.sh", "/home/ubuntu/fablab/bin/db_creator_script_external.sh"),
+ },
+
+ Disposal: model.Stages{
+ model.StageActionF(func(run model.Run) error {
+ m := run.GetModel()
+ s := actions.Route53StringCreator(m, actions.Delete)
+ return host.Exec(m.MustSelectHost("#ctrl"), s).Execute(run)
+ }),
+ terraform.Dispose(),
+ aws_ssh_key2.Dispose(),
+ },
+}
+
+func main() {
+ m.AddActivationActions("stop", "bootstrap")
+ model.AddBootstrapExtension(binding.AwsCredentialsLoader)
+ model.AddBootstrapExtension(aws_ssh_key.KeyManager)
+ fablab.InitModel(m)
+ fablab.Run()
+}
diff --git a/zititest/models/db-creation/resources/aws_setup.sh b/zititest/models/db-creation/resources/aws_setup.sh
new file mode 100644
index 000000000..c6a2f6bc9
--- /dev/null
+++ b/zititest/models/db-creation/resources/aws_setup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+if [ $# -ne 2 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+AWS_ACCESS_KEY="$1"
+AWS_SECRET_KEY="$2"
+
+export AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY"
+export AWS_SECRET_ACCESS_KEY="$AWS_SECRET_KEY"
+
+aws configure set aws_access_key_id "${AWS_ACCESS_KEY_ID}"
+aws configure set aws_secret_access_key "${AWS_SECRET_ACCESS_KEY}"
+aws configure set default.region us-east-1
+aws configure set default.output json
diff --git a/zititest/models/db-creation/resources/db_creator_script_external.sh b/zititest/models/db-creation/resources/db_creator_script_external.sh
new file mode 100644
index 000000000..c210740fa
--- /dev/null
+++ b/zititest/models/db-creation/resources/db_creator_script_external.sh
@@ -0,0 +1,149 @@
+#!/bin/bash
+
+exec >> bashlog.txt 2>&1
+
+# Initial sleep to hopefully allow for pulling of ziti exe filename
+sleep 10
+
+# Set Sleep time easily for quick changes
+sleep_time=.01625
+
+# Set the directory path where ziti executable is
+directory="/home/ubuntu/fablab/bin"
+
+# Set search string for 'ziti-'
+search_string="ziti-"
+
+# Search for the file that contains the specified string
+file=$(find "$directory" -type f -name "*$search_string*" -print -quit)
+
+# Check if a file was found
+if [[ -n "$file" ]]; then
+ echo "File found: $file"
+ # Extract the file name from the full path and save it to a variable
+ filename=$(basename "$file")
+ echo "File name: $filename"
+else
+ echo "File not found."
+fi
+
+# cd to ziti bin dir
+cd $directory || exit
+ls -lsa
+
+# Get ziti_version
+ziti_version=$(./${filename} -v)
+echo "ziti_version: $ziti_version"
+# Retrieve the instance metadata to get the public IP
+public_ip=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)
+echo ${public_ip}
+
+# Login to ziti:
+echo "Logging in to Ziti"
+./ziti-${ziti_version} edge login ${public_ip}:1280 -y -u admin -p admin
+echo "Ziti Edge Login Completed"
+
+# Add config variables for the intercept.v1 and host.v1 config types
+json_response=$(./ziti-${ziti_version} edge list configs -j)
+interceptv1=$(echo "$json_response" | jq -r '.data[0].id')
+hostv1=$(echo "$json_response" | jq -r '.data[1].id')
+
+# Create some folder and bucket names
+
+BUCKET_NAME_IDENTITIES="fablab-ziti-identities"
+FOLDER_NAME_IDENTITIES="identities-${ziti_version}"
+BUCKET_NAME_PKI="fablab-ziti-pki"
+FOLDER_NAME_PKI="pki-${ziti_version}"
+
+#Create folders with code version as suffix:
+aws s3api put-object --bucket "$BUCKET_NAME_IDENTITIES" --key "$FOLDER_NAME_IDENTITIES"/
+aws s3api put-object --bucket "$BUCKET_NAME_PKI" --key "$FOLDER_NAME_PKI"/
+
+#Copy the full pki directory into s3:
+# aws s3 sync s3:///
+aws s3 sync /home/ubuntu/fablab/pki s3://$BUCKET_NAME_PKI/$FOLDER_NAME_PKI
+
+# Make directory to store identities
+mkdir identities-${ziti_version}; chmod 0755 identities-${ziti_version}
+
+# Set the name of your S3 buckets and folder
+BUCKET_NAME_DB="fablab-ziti-databases"
+
+# Set document path and s3 key of ziti-db
+DOCUMENT_PATH_DB="/home/ubuntu/fablab/ctrl.db"
+S3_KEY_DB="ctrl.db-${ziti_version}"
+
+for i in {20000..24000}; do
+ ./ziti-${ziti_version} edge create service service$i -c ${interceptv1},${hostv1}
+ ./ziti-${ziti_version} edge create service-policy service${i}Bind Bind --service-roles @service${i} --identity-roles '#iperf-server'
+ ./ziti-${ziti_version} edge create service-policy service${i}Dial Dial --service-roles @service${i} --identity-roles '#iperf-client'
+ ./ziti-${ziti_version} edge create serp service${i} --service-roles @service${i} --edge-router-roles '#all'
+ DOCUMENT_PATH_IDENTITIES="identities-${ziti_version}/identity${i}.json"
+ S3_KEY_IDENTITIES="identity${i}.json"
+ if ((i < 20100)); then
+ ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.100,iperf.service.client.dial.200,iperf.service.client.dial.300,iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000'
+ ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt
+ aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES
+ sleep ${sleep_time}
+ elif ((20101 < i < 20200)); then
+ ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.200,iperf.service.client.dial.300,iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000'
+ ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt
+ aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES
+ sleep ${sleep_time}
+ elif ((20201 < i < 20300)); then
+ ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.300,iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000'
+ ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt
+ aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES
+ sleep ${sleep_time}
+ elif ((20301 < i < 20400)); then
+ ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000'
+ ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt
+ aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES
+ sleep ${sleep_time}
+ elif ((20401 < i < 20500)); then
+ ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000'
+ ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt
+ aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES
+ sleep ${sleep_time}
+ elif ((20501 0 {
+ servicesCount += identityServiceCount
+ hostingIdentities[identityId] = identityServiceCount
+ }
+ }
+
+ regionCount := len(m.Regions)
+
+ perRegion := servicesCount / regionCount
+ idIdx := 0
+
+ avgTunnelsPerHost := 15
+
+ m.RangeSortedRegions(func(regionId string, region *model.Region) {
+ regionServiceCount := 0
+
+ var regionIdentityIds []string
+
+ for {
+ if idIdx >= len(ids) {
+ break
+ }
+ identityId := ids[idIdx]
+ idIdx++
+
+ svcCount, found := hostingIdentities[identityId]
+ if !found {
+ continue
+ }
+ regionServiceCount += svcCount
+ regionIdentityIds = append(regionIdentityIds, identityId)
+ if regionServiceCount > perRegion {
+ break
+ }
+ }
+
+ hostCount := len(regionIdentityIds) / avgTunnelsPerHost
+ var hosts []*model.Host
+
+ for i := 0; i < hostCount; i++ {
+ tunnelsHost := &model.Host{
+ Scope: model.Scope{Tags: model.Tags{}},
+ Region: region,
+ Components: model.Components{},
+ InstanceType: "t3.medium",
+ }
+ hostId := fmt.Sprintf("%s_svc_hosts_%v", regionId, i)
+ region.Hosts[hostId] = tunnelsHost
+ hosts = append(hosts, tunnelsHost)
+ }
+
+ hostIdx := 0
+ for _, identityId := range regionIdentityIds {
+ tunnelHost := hosts[hostIdx%len(hosts)]
+ hostIdx++
+
+ svcCount := hostingIdentities[identityId]
+
+ tunnelComponent := &model.Component{
+ Scope: model.Scope{Tags: model.Tags{"sdk-tunneler", "pre-created", fmt.Sprintf("serviceCount=%v", svcCount)}},
+ Type: &zitilab.ZitiTunnelType{
+ Mode: zitilab.ZitiTunnelModeHost,
+ Version: TargetZitiVersion,
+ },
+ Host: tunnelHost,
+ }
+ tunnelHost.Components[identityId] = tunnelComponent
+ }
+ })
+
+ return nil
+}
+
+var dbStrategyInstance = dbStrategy{}
+
+var m = &model.Model{
+ Id: "router-test",
+ Scope: model.Scope{
+ Defaults: model.Variables{
+ "environment": "sdk-hosting-test",
+ "credentials": model.Variables{
+ "aws": model.Variables{
+ "managed_key": true,
+ },
+ "ssh": model.Variables{
+ "username": "ubuntu",
+ },
+ "edge": model.Variables{
+ "username": "admin",
+ "password": "admin",
+ },
+ },
+ "metrics": model.Variables{
+ "influxdb": model.Variables{
+ "url": "http://localhost:8086",
+ "db": "ziti",
+ },
+ },
+ },
+ },
+ StructureFactories: []model.Factory{
+ model.NewScaleFactoryWithDefaultEntityFactory(scaleStrategy{}),
+ &models.ZitiDbBuilder{Strategy: dbStrategyInstance},
+ },
+ Resources: model.Resources{
+ resources.Configs: resources.SubFolder(configResource, "configs"),
+ resources.Binaries: os.DirFS(path.Join(os.Getenv("GOPATH"), "bin")),
+ resources.Terraform: test_resources.TerraformResources(),
+ },
+ Regions: model.Regions{
+ "us-east-1": {
+ Region: "us-east-1",
+ Site: "us-east-1a",
+ Hosts: model.Hosts{
+ "ctrl": {
+ InstanceType: "c5.large",
+ Components: model.Components{
+ "ctrl": {
+ Scope: model.Scope{Tags: model.Tags{"ctrl"}},
+ Type: &zitilab.ControllerType{
+ Version: TargetZitiVersion,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+
+ Actions: model.ActionBinders{
+ "bootstrap": model.ActionBinder(func(m *model.Model) model.Action {
+ workflow := actions.Workflow()
+
+ //workflow.AddAction(component.Stop("*"))
+ //workflow.AddAction(host.GroupExec("*", 25, "rm -f logs/*"))
+
+ workflow.AddAction(component.Start("#ctrl"))
+ workflow.AddAction(semaphore.Sleep(2 * time.Second))
+
+ workflow.AddAction(edge.Login("#ctrl"))
+
+ workflow.AddAction(edge.ReEnrollEdgeRouters(".edge-router .pre-created", 2))
+ workflow.AddAction(edge.ReEnrollIdentities(".sdk-tunneler .pre-created", 10))
+ return workflow
+ }),
+ "stop": model.Bind(component.StopInParallelHostExclusive("*", 15)),
+ "clean": model.Bind(actions.Workflow(
+ component.StopInParallelHostExclusive("*", 15),
+ host.GroupExec("*", 25, "rm -f logs/*"),
+ )),
+ "login": model.Bind(edge.Login("#ctrl")),
+ },
+
+ Infrastructure: model.Stages{
+ aws_ssh_key.Express(),
+ &terraform_0.Terraform{
+ Retries: 3,
+ ReadyCheck: &semaphore_0.ReadyStage{
+ MaxWait: 90 * time.Second,
+ },
+ },
+ },
+
+ Distribution: model.Stages{
+ distribution.DistributeSshKey("*"),
+ distribution.Locations("*", "logs"),
+ rsync.RsyncStaged(),
+ model.StageActionF(func(run model.Run) error {
+ dbFile := dbStrategyInstance.GetDbFile(run.GetModel())
+ deferred := rsync.NewRsyncHost("#ctrl", dbFile, "/home/ubuntu/fablab/ctrl.db")
+ return deferred.Execute(run)
+ }),
+ },
+
+ Disposal: model.Stages{
+ terraform.Dispose(),
+ aws_ssh_key2.Dispose(),
+ },
+}
+
+func main() {
+ m.AddActivationActions("stop", "bootstrap")
+
+ model.AddBootstrapExtension(binding.AwsCredentialsLoader)
+ model.AddBootstrapExtension(aws_ssh_key.KeyManager)
+
+ fablab.InitModel(m)
+ fablab.Run()
+}
diff --git a/zititest/models/simple/actions/start.go b/zititest/models/simple/actions/start.go
index a1220c129..e26447762 100644
--- a/zititest/models/simple/actions/start.go
+++ b/zititest/models/simple/actions/start.go
@@ -28,11 +28,8 @@ import (
"github.com/openziti/ziti/zititest/zitilab/models"
)
-func NewStartAction(metricbeat MetricbeatConfig, consul ConsulConfig) model.ActionBinder {
- action := &startAction{
- Metricbeat: metricbeat,
- Consul: consul,
- }
+func NewStartAction() model.ActionBinder {
+ action := &startAction{}
return action.bind
}
@@ -43,9 +40,6 @@ func (a *startAction) bind(m *model.Model) model.Action {
workflow.AddAction(component.StartInParallel(models.EdgeRouterTag, 25))
workflow.AddAction(component.StartInParallel(".iperf", 5))
- workflow.AddAction(semaphore.Sleep(2 * time.Second))
- workflow.AddAction(zitilib_actions.StartMetricbeat("*", a.Metricbeat.ConfigPath, a.Metricbeat.DataPath, a.Metricbeat.LogPath))
- workflow.AddAction(zitilib_actions.StartConsul("*", a.Consul.ServerAddr, a.Consul.ConfigDir, a.Consul.DataPath, a.Consul.LogPath))
workflow.AddAction(semaphore.Sleep(2 * time.Second))
workflow.AddAction(component.StartInParallel(".sdk-app", 5))
@@ -56,20 +50,4 @@ func (a *startAction) bind(m *model.Model) model.Action {
return workflow
}
-type startAction struct {
- Metricbeat MetricbeatConfig
- Consul ConsulConfig
-}
-
-type MetricbeatConfig struct {
- ConfigPath string
- DataPath string
- LogPath string
-}
-
-type ConsulConfig struct {
- ConfigDir string
- ServerAddr string
- DataPath string
- LogPath string
-}
+type startAction struct{}
diff --git a/zititest/models/simple/configs/consul.hcl b/zititest/models/simple/configs/consul.hcl
deleted file mode 100644
index 0f333bb3b..000000000
--- a/zititest/models/simple/configs/consul.hcl
+++ /dev/null
@@ -1,24 +0,0 @@
-datacenter = "ziti-build-metrics"
-data_dir = "/opt/consul"
-encrypt = "${encryption_key}"
-advertise_addr="${public_ip}"
-
-
-tls {
- defaults {
- verify_incoming = false
- verify_outgoing = true
-
- ca_file="consul/consul-agent-ca.pem"
- }
-}
-
-auto_encrypt {
- tls = true
-}
-
-acl {
- enabled = true
- default_policy = "allow"
- enable_token_persistence = true
-}
diff --git a/zititest/models/simple/configs/elasticsearch.repo b/zititest/models/simple/configs/elasticsearch.repo
deleted file mode 100644
index e90d3f65d..000000000
--- a/zititest/models/simple/configs/elasticsearch.repo
+++ /dev/null
@@ -1,8 +0,0 @@
-[logstash-6.x]
-name=Elastic repository for 6.x packages
-baseurl=https://artifacts.elastic.co/packages/6.x/yum
-gpgcheck=1
-gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
-enabled=1
-autorefresh=1
-type=rpm-md
\ No newline at end of file
diff --git a/zititest/models/simple/configs/metricbeat.yml b/zititest/models/simple/configs/metricbeat.yml
deleted file mode 100644
index 35c1cc9f6..000000000
--- a/zititest/models/simple/configs/metricbeat.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-fields_under_root: true
-fields:
- build_number: ${build_number}
- ziti_version: ${ziti_version}
-
-processors:
- - add_cloud_metadata: ~
-
-metricbeat.modules:
-- module: system
- metricsets:
- - cpu # CPU usage
- - load # CPU load averages
- - memory # Memory usage
- - network # Network IO
- enabled: true
- period: 30s
- cpu.metrics: ["percentages"] # The other available options are normalized_percentages and ticks.
- core.metrics: ["percentages"] # The other available option is ticks.
-#- module: docker
-# metricsets:
-# - "container"
-# - "cpu"
-# - "diskio"
-# - "healthcheck"
-# - "info"
-# - "image"
-# - "memory"
-# - "network"
-# hosts: ["unix:///var/run/docker.sock"]
-# period: 30s
-# enabled: true
-# # If set to true, replace dots in labels with `_`.
-# labels.dedot: true
-
-
-output.elasticsearch:
- # Array of hosts to connect to.
- hosts: ["${host}"]
-
- # Optional protocol and basic auth credentials.
- protocol: "https"
- username: "${user}"
- password: "${password}"
- index: 'zt-%{[agent.version]}-%{+yyyy.MM.dd}'
-
-setup.template.enabled: true
-setup.template.name: 'zt-%{[agent.version]}'
-setup.template.pattern: 'zt-%{[agent.version]}-*'
-setup.template.fields: "/etc/metricbeat/fields.yml"
-setup.template.settings:
- index.number_of_shards: 1
- index.codec: best_compression
\ No newline at end of file
diff --git a/zititest/models/simple/simple.go b/zititest/models/simple/simple.go
index dee895868..880bee875 100644
--- a/zititest/models/simple/simple.go
+++ b/zititest/models/simple/simple.go
@@ -18,7 +18,6 @@ package simple
import (
"embed"
- "fmt"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/fablab/kernel/lib/actions/component"
"github.com/openziti/fablab/kernel/lib/binding"
@@ -35,22 +34,15 @@ import (
"github.com/openziti/ziti/zititest/models/test_resources"
"github.com/openziti/ziti/zititest/zitilab"
"github.com/openziti/ziti/zititest/zitilab/actions/edge"
- "github.com/sirupsen/logrus"
"os"
"time"
)
+const ZitiEdgeTunnelVersion = "v0.22.12"
+
//go:embed configs
var configResource embed.FS
-func getConfigData(filePath string) []byte {
- data, err := configResource.ReadFile(fmt.Sprintf("configs/%s", filePath))
- if err != nil {
- logrus.Errorf("Unable to read config data from %s: [%s]", filePath, err)
- }
- return data
-}
-
func getUniqueId() string {
if runId := os.Getenv("GITHUB_RUN_ID"); runId != "" {
return "-" + runId + "." + os.Getenv("GITHUB_RUN_ATTEMPT")
@@ -101,6 +93,29 @@ var Model = &model.Model{
return nil
})
}),
+
+ model.FactoryFunc(func(m *model.Model) error {
+ zetPath, useLocalPath := m.GetStringVariable("local_zet_path")
+ return m.ForEachComponent("*", 1, func(c *model.Component) error {
+ if c.Type == nil {
+ return nil
+ }
+
+ if zet, ok := c.Type.(*zitilab.ZitiEdgeTunnelType); ok {
+ if useLocalPath {
+ zet.Version = ""
+ zet.LocalPath = zetPath
+ } else {
+ zet.Version = ZitiEdgeTunnelVersion
+ zet.LocalPath = ""
+ }
+ zet.InitType(c)
+ return nil
+ }
+
+ return nil
+ })
+ }),
},
Resources: model.Resources{
@@ -156,7 +171,7 @@ var Model = &model.Model{
"ziti-edge-tunnel-client": {
Scope: model.Scope{Tags: model.Tags{"sdk-app", "client"}},
Type: &zitilab.ZitiEdgeTunnelType{
- Version: "v0.21.4",
+ Version: ZitiEdgeTunnelVersion,
},
},
},
@@ -206,7 +221,7 @@ var Model = &model.Model{
"ziti-edge-tunnel-host": {
Scope: model.Scope{Tags: model.Tags{"sdk-app", "host", "zet-host"}},
Type: &zitilab.ZitiEdgeTunnelType{
- Version: "v0.21.4",
+ Version: ZitiEdgeTunnelVersion,
},
},
"iperf-server-zet": {
@@ -235,19 +250,9 @@ var Model = &model.Model{
Actions: model.ActionBinders{
"bootstrap": actions.NewBootstrapAction(),
- "start": actions.NewStartAction(actions.MetricbeatConfig{
- ConfigPath: "metricbeat",
- DataPath: "metricbeat/data",
- LogPath: "metricbeat/logs",
- },
- actions.ConsulConfig{
- ServerAddr: os.Getenv("CONSUL_ENDPOINT"),
- ConfigDir: "consul",
- DataPath: "consul/data",
- LogPath: "consul/log.out",
- }),
- "stop": model.Bind(component.StopInParallel("*", 15)),
- "login": model.Bind(edge.Login("#ctrl1")),
+ "start": actions.NewStartAction(),
+ "stop": model.Bind(component.StopInParallel("*", 15)),
+ "login": model.Bind(edge.Login("#ctrl1")),
},
Infrastructure: model.Stages{
@@ -262,68 +267,6 @@ var Model = &model.Model{
Distribution: model.Stages{
distribution.DistributeSshKey("*"),
- distribution.Locations("*", "logs"),
- distribution.DistributeDataWithReplaceCallbacks(
- "*",
- string(getConfigData("metricbeat.yml")),
- "metricbeat/metricbeat.yml",
- os.FileMode(0644),
- map[string]func(*model.Host) string{
- "${host}": func(h *model.Host) string {
- return os.Getenv("ELASTIC_ENDPOINT")
- },
- "${user}": func(h *model.Host) string {
- return os.Getenv("ELASTIC_USERNAME")
- },
- "${password}": func(h *model.Host) string {
- return os.Getenv("ELASTIC_PASSWORD")
- },
- "${build_number}": func(h *model.Host) string {
- return os.Getenv("BUILD_NUMBER")
- },
- "${ziti_version}": func(h *model.Host) string {
- return h.MustStringVariable("ziti_version")
- },
- },
- ),
-
- distribution.DistributeDataWithReplaceCallbacks(
- "*",
- string(getConfigData("consul.hcl")),
- "consul/consul.hcl",
- os.FileMode(0644),
- map[string]func(*model.Host) string{
- "${public_ip}": func(h *model.Host) string {
- return h.PublicIp
- },
- "${encryption_key}": func(h *model.Host) string {
- return os.Getenv("CONSUL_ENCRYPTION_KEY")
- },
- "${build_number}": func(h *model.Host) string {
- return os.Getenv("BUILD_NUMBER")
- },
- "${ziti_version}": func(h *model.Host) string {
- return h.MustStringVariable("ziti_version")
- },
- },
- ),
- distribution.DistributeDataWithReplaceCallbacks(
- "#ctrl",
- string(getConfigData("ziti.hcl")),
- "consul/ziti.hcl",
- os.FileMode(0644),
- map[string]func(*model.Host) string{
- "${build_number}": func(h *model.Host) string {
- return os.Getenv("BUILD_NUMBER")
- },
- "${ziti_version}": func(h *model.Host) string {
- return h.MustStringVariable("ziti_version")
- },
- }),
- distribution.DistributeData(
- "*",
- []byte(os.Getenv("CONSUL_AGENT_CERT")),
- "consul/consul-agent-ca.pem"),
rsync.RsyncStaged(),
},
diff --git a/zititest/tests/echo_test.go b/zititest/tests/echo_test.go
index 4aa844f59..bed362f36 100644
--- a/zititest/tests/echo_test.go
+++ b/zititest/tests/echo_test.go
@@ -19,7 +19,6 @@ package tests
import (
"fmt"
"github.com/google/uuid"
- "github.com/openziti/fablab/kernel/lib"
"github.com/stretchr/testify/require"
"strings"
"testing"
@@ -37,13 +36,12 @@ func TestSdkEcho(t *testing.T) {
}
for _, c := range components {
- ssh := lib.NewSshConfigFactory(c.GetHost())
remoteConfigFile := "/home/ubuntu/fablab/cfg/" + c.Id + ".json"
echoClientCmd := fmt.Sprintf(`echo "%s" | /home/%s/fablab/bin/ziti demo zcat --identity %s ziti:echo 2>&1`,
- string(data), ssh.User(), remoteConfigFile)
+ string(data), c.GetHost().GetSshUser(), remoteConfigFile)
- output, err := lib.RemoteExec(ssh, echoClientCmd)
+ output, err := c.GetHost().ExecLogged(echoClientCmd)
t.Logf("test output:\n%s", output)
req.NoError(err)
//trim the newline ssh added
diff --git a/zititest/tests/files_test.go b/zititest/tests/files_test.go
index 562025bd4..660cb6027 100644
--- a/zititest/tests/files_test.go
+++ b/zititest/tests/files_test.go
@@ -18,7 +18,9 @@ package tests
import (
"fmt"
+ "github.com/google/uuid"
"github.com/openziti/fablab/kernel/lib"
+ "github.com/openziti/fablab/kernel/libssh"
"github.com/openziti/fablab/kernel/model"
"github.com/stretchr/testify/require"
"testing"
@@ -52,7 +54,7 @@ func TestDownloadFiles(t *testing.T) {
t.Run("test-ert-downloads", func(t *testing.T) {
t.Parallel()
- for _, size := range []string{"1KB", "100KB", "20MB"} {
+ for _, size := range []string{"1KB" /* "100KB", "20MB"*/} {
for _, hostType := range []string{"ert", "zet", "ziti-tunnel"} {
for _, client := range []httpClient{ClientCurl, ClientWget} {
for _, encrypted := range []bool{true, false} {
@@ -117,7 +119,7 @@ func testFileDownload(t *testing.T, hostSelector string, client httpClient, host
success := false
- t.Run(fmt.Sprintf("%v-(%s->%s)-%s-%v", client, hostSelector, hostType, fileSize, encDesk), func(t *testing.T) {
+ t.Run(fmt.Sprintf("%v-(%s<-%s)-%s-%v", client, hostSelector, hostType, fileSize, encDesk), func(t *testing.T) {
host, err := model.GetModel().SelectHost("." + hostSelector + "-client")
req := require.New(t)
req.NoError(err)
@@ -130,15 +132,24 @@ func testFileDownload(t *testing.T, hostSelector string, client httpClient, host
url := fmt.Sprintf("https://files-%s%s.s3-us-west-1.amazonaws.ziti/%s.zip", hostType, urlExtra, fileSize)
sshConfigFactory := lib.NewSshConfigFactory(host)
+ filename := uuid.NewString()
+
+ var cmds []string
+ cmds = append(cmds, fmt.Sprintf("echo '%s %s' > checksums", hashes[fileSize], filename))
+
var cmd string
if client == ClientCurl {
- cmd = fmt.Sprintf(`set -o pipefail; curl -k --header "Host: ziti-smoketest-files.s3-us-west-1.amazonaws.com" -fSL -o - %s | md5sum`, url)
+ cmd = fmt.Sprintf(`set -o pipefail; curl -k --header "Host: ziti-smoketest-files.s3-us-west-1.amazonaws.com" --fail-early --fail-with-body -SL -o %s %s`, filename, url)
} else if client == ClientWget {
- cmd = fmt.Sprintf(`set -o pipefail; wget --no-check-certificate --header "Host: ziti-smoketest-files.s3-us-west-1.amazonaws.com" -O - -t 5 -T 5 %s | md5sum`, url)
+ cmd = fmt.Sprintf(`set -o pipefail; wget --no-check-certificate --header "Host: ziti-smoketest-files.s3-us-west-1.amazonaws.com" -O %s -t 5 -T 5 %s`, filename, url)
}
+ cmds = append(cmds, cmd)
+ cmds = append(cmds, "md5sum -c checksums")
timeout := timeouts[fileSize]
- o, err := lib.RemoteExecAllWithTimeout(sshConfigFactory, timeout, cmd)
+ o, err := libssh.RemoteExecAllWithTimeout(sshConfigFactory, timeout, cmds...)
+ t.Log(o)
+
if hostType == "zet" && err != nil {
t.Skipf("zet hosted file transfer failed [%v]", err.Error())
return
@@ -149,9 +160,7 @@ func testFileDownload(t *testing.T, hostSelector string, client httpClient, host
return
}
- t.Log(o)
req.NoError(err)
- req.Equal(hashes[fileSize], o[0:32])
success = true
})
return success
diff --git a/zititest/tests/iperf_test.go b/zititest/tests/iperf_test.go
index 1d339b861..91d139843 100644
--- a/zititest/tests/iperf_test.go
+++ b/zititest/tests/iperf_test.go
@@ -19,6 +19,7 @@ package tests
import (
"fmt"
"github.com/openziti/fablab/kernel/lib"
+ "github.com/openziti/fablab/kernel/libssh"
"github.com/openziti/fablab/kernel/model"
"github.com/stretchr/testify/require"
"testing"
@@ -98,7 +99,7 @@ func testIPerf(t *testing.T, hostSelector string, hostType string, encrypted boo
cmd := fmt.Sprintf(`set -o pipefail; iperf3 -c %s -P 1 -t 10 %s`, addr, extraOptions)
sshConfigFactory := lib.NewSshConfigFactory(host)
- o, err := lib.RemoteExecAllWithTimeout(sshConfigFactory, 20*time.Second, cmd)
+ o, err := libssh.RemoteExecAllWithTimeout(sshConfigFactory, 20*time.Second, cmd)
if hostType == "zet" && err != nil {
t.Skipf("zet hosted iperf test failed [%v]", err.Error())
return
diff --git a/zititest/tests/scp_test.go b/zititest/tests/scp_test.go
index 6cc39f7ae..cde67deb2 100644
--- a/zititest/tests/scp_test.go
+++ b/zititest/tests/scp_test.go
@@ -20,6 +20,7 @@ import (
"fmt"
"github.com/google/uuid"
"github.com/openziti/fablab/kernel/lib"
+ "github.com/openziti/fablab/kernel/libssh"
"github.com/openziti/fablab/kernel/model"
"github.com/stretchr/testify/require"
"testing"
@@ -75,9 +76,7 @@ func TestScp(t *testing.T) {
req := require.New(t)
req.False(allZetHostedFailed, "all zet hosted file transfer should not failed, indicates bigger issue")
-
- // TODO: fix once ZET client tests are working
- req.True(allZetClientsFailed, "all zet client file transfers should not failed, indicates bigger issue")
+ req.False(allZetClientsFailed, "all zet client file transfers should not failed, indicates bigger issue")
}
func testScp(t *testing.T, hostSelector string, hostType string, encrypted bool) bool {
@@ -88,40 +87,44 @@ func testScp(t *testing.T, hostSelector string, hostType string, encrypted bool)
success := false
- t.Run(fmt.Sprintf("(%s->%s)-%v", hostSelector, hostType, encDesk), func(t *testing.T) {
- if hostSelector == "zet" {
- t.Skipf("zet is currently failing as client")
- }
- host, err := model.GetModel().SelectHost("." + hostSelector + "-client")
- req := require.New(t)
- req.NoError(err)
-
- nameExtra := ""
- if !encrypted {
- nameExtra = "-unencrypted"
- }
-
- sshConfigFactory := lib.NewSshConfigFactory(host)
-
- cmds := []string{
- fmt.Sprintf("scp -o StrictHostKeyChecking=no ssh-%s%s.ziti:./fablab/bin/ziti /tmp/ziti-%s", hostType, nameExtra, uuid.NewString()),
- fmt.Sprintf("scp -o StrictHostKeyChecking=no ./fablab/bin/ziti ssh-%s%s.ziti:/tmp/ziti-%s", hostType, nameExtra, uuid.NewString()),
- }
-
- o, err := lib.RemoteExecAllWithTimeout(sshConfigFactory, 30*time.Second, cmds...)
- if hostType == "zet" && err != nil {
- t.Skipf("zet hosted ssh failed [%v]", err.Error())
- return
- }
-
- if hostSelector == "zet" && err != nil {
- t.Skipf("zet client ssh failed [%v]", err.Error())
- return
- }
-
- t.Log(o)
- req.NoError(err)
- success = true
- })
+ nameExtra := ""
+ if !encrypted {
+ nameExtra = "-unencrypted"
+ }
+
+ tests := []struct {
+ direction string
+ cmd string
+ }{
+ {
+ direction: "<-",
+ cmd: fmt.Sprintf("scp -o StrictHostKeyChecking=no scp://ssh-%s%s.ziti:2022/fablab/bin/ziti /tmp/ziti-%s", hostType, nameExtra, uuid.NewString()),
+ }, {
+ direction: "->",
+ cmd: fmt.Sprintf("scp -o StrictHostKeyChecking=no ./fablab/bin/ziti scp://ssh-%s%s.ziti:2022//tmp/ziti-%s", hostType, nameExtra, uuid.NewString()),
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("(%s%s%s)-%v", hostSelector, test.direction, hostType, encDesk), func(t *testing.T) {
+ host, err := model.GetModel().SelectHost("." + hostSelector + "-client")
+ req := require.New(t)
+ req.NoError(err)
+
+ sshConfigFactory := lib.NewSshConfigFactory(host)
+
+ o, err := libssh.RemoteExecAllWithTimeout(sshConfigFactory, 50*time.Second, test.cmd)
+ if hostType == "zet" && err != nil {
+ t.Skipf("zet hosted ssh failed [%v]", err.Error())
+ } else if hostSelector == "zet" && err != nil {
+ t.Skipf("zet client ssh failed [%v]", err.Error())
+ } else {
+ t.Log(o)
+ req.NoError(err)
+ success = true
+ }
+ })
+ }
+
return success
}
diff --git a/zititest/zitilab/actions/consul.go b/zititest/zitilab/actions/consul.go
index eef623a9b..883ef89a4 100644
--- a/zititest/zitilab/actions/consul.go
+++ b/zititest/zitilab/actions/consul.go
@@ -2,8 +2,8 @@ package zitilib_actions
import (
"fmt"
+ "github.com/openziti/fablab/kernel/libssh"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
)
@@ -27,12 +27,12 @@ func StartConsul(hostSpec, consulServer, configDir, dataPath, logFile string) mo
}
func (cs *consulStart) Execute(run model.Run) error {
- return run.GetModel().ForEachHost(cs.hostSpec, 24, func(c *model.Host) error {
- ssh := lib.NewSshConfigFactory(c)
+ return run.GetModel().ForEachHost(cs.hostSpec, 24, func(host *model.Host) error {
+ ssh := host.NewSshConfigFactory()
cmd := fmt.Sprintf("screen -d -m nohup consul agent -join %s -config-dir %s -data-dir %s -log-file %s 2>&1 &", cs.consulServer, cs.configDir, cs.dataPath, cs.logFile)
- if output, err := lib.RemoteExec(ssh, cmd); err != nil {
+ if output, err := libssh.RemoteExec(ssh, cmd); err != nil {
logrus.Errorf("error starting consul service [%s] (%v)", output, err)
return err
}
diff --git a/zititest/zitilab/actions/edge/ctrl_init.go b/zititest/zitilab/actions/edge/ctrl_init.go
index 823798de5..fa4cb0faf 100644
--- a/zititest/zitilab/actions/edge/ctrl_init.go
+++ b/zititest/zitilab/actions/edge/ctrl_init.go
@@ -2,7 +2,6 @@ package edge
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/lib/actions/component"
"github.com/openziti/fablab/kernel/lib/actions/host"
"github.com/openziti/fablab/kernel/model"
@@ -44,7 +43,7 @@ func (init *raftInit) Execute(run model.Run) error {
}
for _, c := range m.SelectComponents(init.componentSpec) {
- sshConfigFactory := lib.NewSshConfigFactory(c.GetHost())
+ sshConfigFactory := c.GetHost().NewSshConfigFactory()
tmpl := "set -o pipefail; /home/%s/fablab/bin/ziti agent controller init %s %s default.admin 2>&1 | tee logs/controller.edge.init.log"
if err := host.Exec(c.GetHost(), fmt.Sprintf(tmpl, sshConfigFactory.User(), username, password)).Execute(run); err != nil {
diff --git a/zititest/zitilab/actions/edge/init_identities.go b/zititest/zitilab/actions/edge/init_identities.go
index 8c8192fc5..3eae38a20 100644
--- a/zititest/zitilab/actions/edge/init_identities.go
+++ b/zititest/zitilab/actions/edge/init_identities.go
@@ -1,7 +1,7 @@
package edge
import (
- "github.com/openziti/fablab/kernel/lib"
+ "github.com/openziti/fablab/kernel/libssh"
"github.com/openziti/fablab/kernel/model"
zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions"
"github.com/openziti/ziti/zititest/zitilab/cli"
@@ -27,7 +27,7 @@ func (action *initIdentitiesAction) Execute(run model.Run) error {
}
func (action *initIdentitiesAction) createAndEnrollIdentity(run model.Run, c *model.Component) error {
- ssh := lib.NewSshConfigFactory(c.GetHost())
+ ssh := c.GetHost().NewSshConfigFactory()
jwtFileName := filepath.Join(run.GetTmpDir(), c.Id+".jwt")
@@ -48,7 +48,7 @@ func (action *initIdentitiesAction) createAndEnrollIdentity(run model.Run, c *mo
}
remoteConfigFile := "/home/ubuntu/fablab/cfg/" + c.Id + ".json"
- return lib.SendFile(ssh, configFileName, remoteConfigFile)
+ return libssh.SendFile(ssh, configFileName, remoteConfigFile)
}
type initIdentitiesAction struct {
diff --git a/zititest/zitilab/actions/edge/raft_join.go b/zititest/zitilab/actions/edge/raft_join.go
index f3c3676f4..ffca42194 100644
--- a/zititest/zitilab/actions/edge/raft_join.go
+++ b/zititest/zitilab/actions/edge/raft_join.go
@@ -2,7 +2,6 @@ package edge
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/lib/actions/host"
"github.com/openziti/fablab/kernel/model"
"github.com/pkg/errors"
@@ -24,7 +23,7 @@ func (self *raftJoin) Execute(run model.Run) error {
return errors.Errorf("no controllers found with spec '%v'", self.componentSpec)
}
primary := ctrls[0]
- sshConfigFactory := lib.NewSshConfigFactory(primary.GetHost())
+ sshConfigFactory := primary.GetHost().NewSshConfigFactory()
for _, c := range ctrls[1:] {
tmpl := "/home/%s/fablab/bin/ziti agent cluster add %v --id %v"
if err := host.Exec(primary.GetHost(), fmt.Sprintf(tmpl, sshConfigFactory.User(), "tls:"+c.Host.PublicIp+":6262", c.Id)).Execute(run); err != nil {
diff --git a/zititest/zitilab/actions/edge/reenroll_identities.go b/zititest/zitilab/actions/edge/reenroll_identities.go
new file mode 100644
index 000000000..67948d3b9
--- /dev/null
+++ b/zititest/zitilab/actions/edge/reenroll_identities.go
@@ -0,0 +1,23 @@
+package edge
+
+import (
+ "github.com/openziti/fablab/kernel/lib/actions/component"
+ "github.com/openziti/fablab/kernel/model"
+ "github.com/openziti/ziti/zititest/zitilab"
+)
+
+func ReEnrollIdentities(componentSpec string, concurrency int) model.Action {
+ return &reEnrollIdentitiesAction{
+ componentSpec: componentSpec,
+ concurrency: concurrency,
+ }
+}
+
+func (action *reEnrollIdentitiesAction) Execute(run model.Run) error {
+ return component.ExecInParallel(action.componentSpec, action.concurrency, zitilab.ZitiTunnelActionsReEnroll).Execute(run)
+}
+
+type reEnrollIdentitiesAction struct {
+ componentSpec string
+ concurrency int
+}
diff --git a/zititest/zitilab/actions/logs.go b/zititest/zitilab/actions/logs.go
index a51dadb62..b3b63d81c 100644
--- a/zititest/zitilab/actions/logs.go
+++ b/zititest/zitilab/actions/logs.go
@@ -18,10 +18,10 @@ package zitilib_actions
import (
"fmt"
+ "github.com/openziti/fablab/kernel/libssh"
"os"
"path/filepath"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/openziti/foundation/v2/info"
"github.com/sirupsen/logrus"
@@ -39,7 +39,7 @@ func (self *logs) Execute(run model.Run) error {
snapshot := fmt.Sprintf("%d", info.NowInMilliseconds())
for rn, r := range run.GetModel().Regions {
for hn, h := range r.Hosts {
- ssh := lib.NewSshConfigFactory(h)
+ ssh := h.NewSshConfigFactory()
if err := self.forHost(snapshot, rn, hn, ssh); err != nil {
return fmt.Errorf("error retrieving logs for [%s/%s] (%w)", rn, hn, err)
}
@@ -48,14 +48,14 @@ func (self *logs) Execute(run model.Run) error {
return nil
}
-func (self *logs) forHost(snapshot, rn, hn string, ssh lib.SshConfigFactory) error {
+func (self *logs) forHost(snapshot, rn, hn string, ssh libssh.SshConfigFactory) error {
path := filepath.Join(model.AllocateForensicScenario(snapshot, "logs"), rn, hn)
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return fmt.Errorf("error creating logs path [%s] for host [%s/%s] (%w)", path, rn, hn, err)
}
logrus.Infof("=> [%s]", path)
- fis, err := lib.RemoteFileList(ssh, ".")
+ fis, err := libssh.RemoteFileList(ssh, ".")
if err != nil {
return fmt.Errorf("error retrieving home directory for host [%s/%s] (%w)", rn, hn, err)
}
@@ -76,8 +76,8 @@ func (self *logs) forHost(snapshot, rn, hn string, ssh lib.SshConfigFactory) err
return nil
}
-func (self *logs) forHostDir(localPath, remotePath string, ssh lib.SshConfigFactory) error {
- fis, err := lib.RemoteFileList(ssh, remotePath)
+func (self *logs) forHostDir(localPath, remotePath string, ssh libssh.SshConfigFactory) error {
+ fis, err := libssh.RemoteFileList(ssh, remotePath)
if err != nil {
return err
}
@@ -97,7 +97,7 @@ func (self *logs) forHostDir(localPath, remotePath string, ssh lib.SshConfigFact
paths = append(paths, filepath.Join(remotePath, fi.Name()))
}
}
- if err := lib.RetrieveRemoteFiles(ssh, localPath, paths...); err != nil {
+ if err := libssh.RetrieveRemoteFiles(ssh, localPath, paths...); err != nil {
return fmt.Errorf("error retrieving from [%s] (%w)", localPath, err)
}
return nil
diff --git a/zititest/zitilab/actions/metricbeat.go b/zititest/zitilab/actions/metricbeat.go
index 79ec78121..dd834e9dc 100644
--- a/zititest/zitilab/actions/metricbeat.go
+++ b/zititest/zitilab/actions/metricbeat.go
@@ -2,8 +2,8 @@ package zitilib_actions
import (
"fmt"
+ "github.com/openziti/fablab/kernel/libssh"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
)
@@ -25,12 +25,12 @@ func StartMetricbeat(hostSpec, configPath, dataPath, logPath string) model.Actio
}
func (mbs *metricbeatStart) Execute(run model.Run) error {
- return run.GetModel().ForEachHost(mbs.hostSpec, 24, func(c *model.Host) error {
- ssh := lib.NewSshConfigFactory(c)
+ return run.GetModel().ForEachHost(mbs.hostSpec, 24, func(host *model.Host) error {
+ ssh := host.NewSshConfigFactory()
cmd := fmt.Sprintf("screen -d -m nohup metricbeat --path.config %s --path.data %s --path.logs %s 2>&1 &", mbs.configPath, mbs.dataPath, mbs.logPath)
- if output, err := lib.RemoteExec(ssh, cmd); err != nil {
+ if output, err := libssh.RemoteExec(ssh, cmd); err != nil {
logrus.Errorf("error starting metricbeat service [%s] (%v)", output, err)
return err
}
diff --git a/zititest/zitilab/actions/stop_all.go b/zititest/zitilab/actions/stop_all.go
new file mode 100644
index 000000000..3e75a1268
--- /dev/null
+++ b/zititest/zitilab/actions/stop_all.go
@@ -0,0 +1,43 @@
+/*
+ Copyright 2019 NetFoundry Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package zitilib_actions
+
+import (
+ "github.com/openziti/fablab/kernel/model"
+)
+
+func StopAll(hostSpec string) model.Action {
+ return StopAllInParallel(hostSpec, 1)
+}
+
+func StopAllInParallel(hostSpec string, concurrency int) model.Action {
+ return &stopAll{
+ hostSpec: hostSpec,
+ concurrency: concurrency,
+ }
+}
+
+func (stop *stopAll) Execute(run model.Run) error {
+ return run.GetModel().ForEachHost(stop.hostSpec, stop.concurrency, func(c *model.Host) error {
+ return nil
+ })
+}
+
+type stopAll struct {
+ hostSpec string
+ concurrency int
+}
diff --git a/zititest/zitilab/component_common.go b/zititest/zitilab/component_common.go
index f30216a9d..7d4df7474 100644
--- a/zititest/zitilab/component_common.go
+++ b/zititest/zitilab/component_common.go
@@ -18,9 +18,10 @@ package zitilab
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
+ zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions"
"github.com/sirupsen/logrus"
+ "path/filepath"
"strings"
)
@@ -39,11 +40,11 @@ func startZitiComponent(c *model.Component, zitiType string, version string, con
binaryName += "-" + version
}
- factory := lib.NewSshConfigFactory(c.GetHost())
+ user := c.GetHost().GetSshUser()
- binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", factory.User(), binaryName)
- configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s", factory.User(), configName)
- logsPath := fmt.Sprintf("/home/%s/logs/%s.log", factory.User(), c.Id)
+ binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", user, binaryName)
+ configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s", user, configName)
+ logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
useSudo := ""
if zitiType == "tunnel" || c.HasTag("tunneler") {
@@ -53,7 +54,7 @@ func startZitiComponent(c *model.Component, zitiType string, version string, con
serviceCmd := fmt.Sprintf("nohup %s %s %s run --log-formatter pfxlog %s --cli-agent-alias %s > %s 2>&1 &",
useSudo, binaryPath, zitiType, configPath, c.Id, logsPath)
- value, err := lib.RemoteExec(factory, serviceCmd)
+ value, err := c.GetHost().ExecLogged(serviceCmd)
if err != nil {
return err
}
@@ -71,3 +72,31 @@ func getPrefixVersion(version string) string {
}
return "v" + version
}
+
+func reEnrollIdentity(run model.Run, c *model.Component, binaryName string, configName string) error {
+ if err := zitilib_actions.EdgeExec(run.GetModel(), "delete", "authenticator", "where", fmt.Sprintf("identity=\"%v\"", c.Id)); err != nil {
+ return err
+ }
+
+ if err := zitilib_actions.EdgeExec(run.GetModel(), "delete", "enrollment", "where", fmt.Sprintf("identity=\"%v\"", c.Id)); err != nil {
+ return err
+ }
+
+ jwtFileName := filepath.Join(model.ConfigBuild(), c.Id+".jwt")
+
+ args := []string{"create", "enrollment", "ott", "--jwt-output-file", jwtFileName, "--", c.Id}
+
+ if err := zitilib_actions.EdgeExec(c.GetModel(), args...); err != nil {
+ return err
+ }
+
+ remoteJwt := "/home/ubuntu/fablab/cfg/" + c.Id + ".jwt"
+ if err := c.GetHost().SendFile(jwtFileName, remoteJwt); err != nil {
+ return err
+ }
+
+ tmpl := "set -o pipefail; /home/ubuntu/fablab/bin/%s edge enroll %s 2>&1 | tee /home/ubuntu/logs/%s.identity.enroll.log "
+ cmd := fmt.Sprintf(tmpl, binaryName, remoteJwt, c.Id)
+
+ return c.GetHost().ExecLogOnlyOnError(cmd)
+}
diff --git a/zititest/zitilab/component_controller.go b/zititest/zitilab/component_controller.go
index b47a94f72..65e6382c7 100644
--- a/zititest/zitilab/component_controller.go
+++ b/zititest/zitilab/component_controller.go
@@ -47,7 +47,7 @@ type ControllerType struct {
}
func (self *ControllerType) InitType(*model.Component) {
- if self.Version != "" && !strings.HasPrefix(self.Version, "v") {
+ if self.Version != "" && self.Version != "latest" && !strings.HasPrefix(self.Version, "v") {
self.Version = "v" + self.Version
}
}
@@ -100,8 +100,7 @@ func (self *ControllerType) getProcessFilter(c *model.Component) func(string) bo
}
func (self *ControllerType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter(c))
if err != nil {
return false, err
}
@@ -113,8 +112,7 @@ func (self *ControllerType) Start(_ model.Run, c *model.Component) error {
}
func (self *ControllerType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillFilterF(factory, self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-TERM", self.getProcessFilter(c))
}
func (self *ControllerType) InitStandalone(run model.Run, c *model.Component) error {
@@ -129,7 +127,7 @@ func (self *ControllerType) InitStandalone(run model.Run, c *model.Component) er
return errors.New("variable credentials/edge/password must be a string")
}
- factory := lib.NewSshConfigFactory(c.GetHost())
+ factory := c.GetHost().NewSshConfigFactory()
binaryName := "ziti"
if self.Version != "" {
diff --git a/zititest/zitilab/component_echo_server.go b/zititest/zitilab/component_echo_server.go
index 0518aa271..b0425c42d 100644
--- a/zititest/zitilab/component_echo_server.go
+++ b/zititest/zitilab/component_echo_server.go
@@ -2,7 +2,6 @@ package zitilab
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/openziti/ziti/zititest/zitilab/stageziti"
"github.com/sirupsen/logrus"
@@ -19,7 +18,7 @@ type EchoServerType struct {
}
func (self *EchoServerType) InitType(*model.Component) {
- if self.Version != "" && !strings.HasPrefix(self.Version, "v") {
+ if self.Version != "" && self.Version != "latest" && !strings.HasPrefix(self.Version, "v") {
self.Version = "v" + self.Version
}
}
@@ -41,8 +40,7 @@ func (self *EchoServerType) getProcessFilter(c *model.Component) func(string) bo
}
func (self *EchoServerType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter(c))
if err != nil {
return false, err
}
@@ -55,16 +53,16 @@ func (self *EchoServerType) Start(_ model.Run, c *model.Component) error {
binaryName += "-" + self.Version
}
- factory := lib.NewSshConfigFactory(c.GetHost())
+ user := c.GetHost().GetSshUser()
- binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", factory.User(), binaryName)
- configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s.json", factory.User(), c.Id)
- logsPath := fmt.Sprintf("/home/%s/logs/%s.log", factory.User(), c.Id)
+ binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", user, binaryName)
+ configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s.json", user, c.Id)
+ logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
serviceCmd := fmt.Sprintf("nohup %s demo echo-server -i %s --cli-agent-alias %s > %s 2>&1 &",
binaryPath, configPath, c.Id, logsPath)
- value, err := lib.RemoteExec(factory, serviceCmd)
+ value, err := c.GetHost().ExecLogged(serviceCmd)
if err != nil {
return err
}
@@ -77,6 +75,5 @@ func (self *EchoServerType) Start(_ model.Run, c *model.Component) error {
}
func (self *EchoServerType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillFilterF(factory, self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-TERM", self.getProcessFilter(c))
}
diff --git a/zititest/zitilab/component_iperf.go b/zititest/zitilab/component_iperf.go
index af20df11d..eedac0073 100644
--- a/zititest/zitilab/component_iperf.go
+++ b/zititest/zitilab/component_iperf.go
@@ -18,7 +18,6 @@ package zitilab
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
"strings"
@@ -44,15 +43,14 @@ func (self *IPerfServerType) GetPort() uint16 {
return self.Port
}
-func (self *IPerfServerType) getProcessFilter(*model.Component) func(string) bool {
+func (self *IPerfServerType) getProcessFilter() func(string) bool {
return func(s string) bool {
return strings.Contains(s, fmt.Sprintf("iperf3 -s -p %v", self.GetPort()))
}
}
func (self *IPerfServerType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter())
if err != nil {
return false, err
}
@@ -60,12 +58,11 @@ func (self *IPerfServerType) IsRunning(_ model.Run, c *model.Component) (bool, e
}
func (self *IPerfServerType) Start(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
-
- logsPath := fmt.Sprintf("/home/%s/logs/%s.log", factory.User(), c.Id)
+ user := c.GetHost().GetSshUser()
+ logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
serviceCmd := fmt.Sprintf("nohup iperf3 -s -p %v > %s 2>&1 &", self.GetPort(), logsPath)
- value, err := lib.RemoteExec(factory, serviceCmd)
+ value, err := c.GetHost().ExecLogged(serviceCmd)
if err != nil {
return err
}
@@ -78,6 +75,5 @@ func (self *IPerfServerType) Start(_ model.Run, c *model.Component) error {
}
func (self *IPerfServerType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillFilterF(factory, self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-TERM", self.getProcessFilter())
}
diff --git a/zititest/zitilab/component_router.go b/zititest/zitilab/component_router.go
index 965c44447..73d1f1f3f 100644
--- a/zititest/zitilab/component_router.go
+++ b/zititest/zitilab/component_router.go
@@ -45,7 +45,7 @@ type RouterType struct {
}
func (self *RouterType) InitType(*model.Component) {
- if self.Version != "" && !strings.HasPrefix(self.Version, "v") {
+ if self.Version != "" && self.Version != "latest" && !strings.HasPrefix(self.Version, "v") {
self.Version = "v" + self.Version
}
}
@@ -120,8 +120,7 @@ func (self *RouterType) getProcessFilter(c *model.Component) func(string) bool {
}
func (self *RouterType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter(c))
if err != nil {
return false, err
}
@@ -133,8 +132,7 @@ func (self *RouterType) Start(_ model.Run, c *model.Component) error {
}
func (self *RouterType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillFilterF(factory, self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-TERM", self.getProcessFilter(c))
}
func (self *RouterType) CreateAndEnroll(run model.Run, c *model.Component) error {
@@ -145,8 +143,6 @@ func (self *RouterType) CreateAndEnroll(run model.Run, c *model.Component) error
Warn("unable to delete router (may not be present")
}
- ssh := lib.NewSshConfigFactory(c.GetHost())
-
jwtFileName := filepath.Join(run.GetTmpDir(), c.Id+".jwt")
attributes := strings.Join(c.Tags, ",")
@@ -173,19 +169,17 @@ func (self *RouterType) CreateAndEnroll(run model.Run, c *model.Component) error
}
remoteJwt := "/home/ubuntu/fablab/cfg/" + c.Id + ".jwt"
- if err := lib.SendFile(ssh, jwtFileName, remoteJwt); err != nil {
+ if err := c.GetHost().SendFile(jwtFileName, remoteJwt); err != nil {
return err
}
tmpl := "set -o pipefail; /home/ubuntu/fablab/bin/%v router enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log "
cmd := fmt.Sprintf(tmpl, self.getBinaryName(), self.getConfigName(c), remoteJwt, c.Id)
- return host.Exec(c.GetHost(), cmd).Execute(run)
+ return c.GetHost().ExecLogOnlyOnError(cmd)
}
-func (self *RouterType) ReEnroll(run model.Run, c *model.Component) error {
- ssh := lib.NewSshConfigFactory(c.GetHost())
-
+func (self *RouterType) ReEnroll(_ model.Run, c *model.Component) error {
jwtFileName := filepath.Join(model.ConfigBuild(), c.Id+".jwt")
args := []string{"re-enroll", "edge-router", c.Id, "-j", "--jwt-output-file", jwtFileName}
@@ -195,12 +189,12 @@ func (self *RouterType) ReEnroll(run model.Run, c *model.Component) error {
}
remoteJwt := "/home/ubuntu/fablab/cfg/" + c.Id + ".jwt"
- if err := lib.SendFile(ssh, jwtFileName, remoteJwt); err != nil {
+ if err := c.GetHost().SendFile(jwtFileName, remoteJwt); err != nil {
return err
}
- tmpl := "set -o pipefail; /home/ubuntu/fablab/bin/%s enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log "
+ tmpl := "set -o pipefail; /home/ubuntu/fablab/bin/%s router enroll /home/ubuntu/fablab/cfg/%s -j %s 2>&1 | tee /home/ubuntu/logs/%s.router.enroll.log "
cmd := fmt.Sprintf(tmpl, self.getBinaryName(), self.getConfigName(c), remoteJwt, c.Id)
- return host.Exec(c.GetHost(), cmd).Execute(run)
+ return c.GetHost().ExecLogOnlyOnError(cmd)
}
diff --git a/zititest/zitilab/component_zcat.go b/zititest/zitilab/component_zcat.go
index 84923ec82..d7e5f3645 100644
--- a/zititest/zitilab/component_zcat.go
+++ b/zititest/zitilab/component_zcat.go
@@ -1,7 +1,6 @@
package zitilab
import (
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/openziti/ziti/zititest/zitilab/stageziti"
"strings"
@@ -17,7 +16,7 @@ type ZCatType struct {
}
func (self *ZCatType) InitType(*model.Component) {
- if self.Version != "" && !strings.HasPrefix(self.Version, "v") {
+ if self.Version != "" && self.Version != "latest" && !strings.HasPrefix(self.Version, "v") {
self.Version = "v" + self.Version
}
}
@@ -34,15 +33,14 @@ func (self *ZCatType) StageFiles(r model.Run, c *model.Component) error {
return stageziti.StageZitiOnce(r, c, self.Version, self.LocalPath)
}
-func (self *ZCatType) getProcessFilter(c *model.Component) func(string) bool {
+func (self *ZCatType) getProcessFilter() func(string) bool {
return func(s string) bool {
return strings.Contains(s, "ziti") && strings.Contains(s, "zcat ")
}
}
func (self *ZCatType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter())
if err != nil {
return false, err
}
@@ -50,6 +48,5 @@ func (self *ZCatType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
}
func (self *ZCatType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillFilterF(factory, self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-TERM", self.getProcessFilter())
}
diff --git a/zititest/zitilab/component_ziti_edge_tunnel.go b/zititest/zitilab/component_ziti_edge_tunnel.go
index eee4694db..b0948b52d 100644
--- a/zititest/zitilab/component_ziti_edge_tunnel.go
+++ b/zititest/zitilab/component_ziti_edge_tunnel.go
@@ -18,7 +18,6 @@ package zitilab
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/openziti/ziti/zititest/zitilab/stageziti"
"github.com/sirupsen/logrus"
@@ -68,8 +67,7 @@ func (self *ZitiEdgeTunnelType) getProcessFilter(c *model.Component) func(string
}
func (self *ZitiEdgeTunnelType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter(c))
if err != nil {
return false, err
}
@@ -77,15 +75,15 @@ func (self *ZitiEdgeTunnelType) IsRunning(_ model.Run, c *model.Component) (bool
}
func (self *ZitiEdgeTunnelType) Start(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
+ user := c.GetHost().GetSshUser()
- binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", factory.User(), self.getBinaryName())
- configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s.json", factory.User(), c.Id)
- logsPath := fmt.Sprintf("/home/%s/logs/%s.log", factory.User(), c.Id)
+ binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", user, self.getBinaryName())
+ configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s.json", user, c.Id)
+ logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
- serviceCmd := fmt.Sprintf("nohup sudo %s run -i %s > %s 2>&1 &", binaryPath, configPath, logsPath)
+ serviceCmd := fmt.Sprintf("sudo %s run -i %s > %s 2>&1 &", binaryPath, configPath, logsPath)
- value, err := lib.RemoteExec(factory, serviceCmd)
+ value, err := c.GetHost().ExecLogged(serviceCmd)
if err != nil {
return err
}
@@ -98,6 +96,5 @@ func (self *ZitiEdgeTunnelType) Start(_ model.Run, c *model.Component) error {
}
func (self *ZitiEdgeTunnelType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillFilterF(factory, self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-TERM", self.getProcessFilter(c))
}
diff --git a/zititest/zitilab/component_ziti_tunnel.go b/zititest/zitilab/component_ziti_tunnel.go
index 6036e3b84..b76151db0 100644
--- a/zititest/zitilab/component_ziti_tunnel.go
+++ b/zititest/zitilab/component_ziti_tunnel.go
@@ -18,8 +18,6 @@ package zitilab
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
- "github.com/openziti/fablab/kernel/lib/actions/host"
"github.com/openziti/fablab/kernel/model"
"github.com/openziti/ziti/zititest/zitilab/stageziti"
"github.com/sirupsen/logrus"
@@ -34,6 +32,8 @@ const (
ZitiTunnelModeTproxy ZitiTunnelMode = 0
ZitiTunnelModeProxy ZitiTunnelMode = 1
ZitiTunnelModeHost ZitiTunnelMode = 2
+
+ ZitiTunnelActionsReEnroll = "reEnroll"
)
func (self ZitiTunnelMode) String() string {
@@ -55,8 +55,14 @@ type ZitiTunnelType struct {
LocalPath string
}
+func (self *ZitiTunnelType) GetActions() map[string]model.ComponentAction {
+ return map[string]model.ComponentAction{
+ ZitiTunnelActionsReEnroll: model.ComponentActionF(self.ReEnroll),
+ }
+}
+
func (self *ZitiTunnelType) InitType(*model.Component) {
- if self.Version != "" && !strings.HasPrefix(self.Version, "v") {
+ if self.Version != "" && self.Version != "latest" && !strings.HasPrefix(self.Version, "v") {
self.Version = "v" + self.Version
}
}
@@ -73,15 +79,15 @@ func (self *ZitiTunnelType) StageFiles(r model.Run, c *model.Component) error {
return stageziti.StageZitiOnce(r, c, self.Version, self.LocalPath)
}
-func (self *ZitiTunnelType) InitializeHost(run model.Run, c *model.Component) error {
- cmds := []string{"mkdir -p /home/ubuntu/logs"}
+func (self *ZitiTunnelType) InitializeHost(_ model.Run, c *model.Component) error {
if self.Mode == ZitiTunnelModeTproxy {
- cmds = append(cmds,
+ cmds := []string{
"sudo sed -i 's/#DNS=/DNS=127.0.0.1/g' /etc/systemd/resolved.conf",
"sudo systemctl restart systemd-resolved",
- )
+ }
+ return c.Host.ExecLogOnlyOnError(cmds...)
}
- return host.Exec(c.GetHost(), cmds...).Execute(run)
+ return nil
}
func (self *ZitiTunnelType) getProcessFilter(c *model.Component) func(string) bool {
@@ -89,37 +95,45 @@ func (self *ZitiTunnelType) getProcessFilter(c *model.Component) func(string) bo
}
func (self *ZitiTunnelType) IsRunning(_ model.Run, c *model.Component) (bool, error) {
- factory := lib.NewSshConfigFactory(c.GetHost())
- pids, err := lib.FindProcesses(factory, self.getProcessFilter(c))
+ pids, err := c.GetHost().FindProcesses(self.getProcessFilter(c))
if err != nil {
return false, err
}
return len(pids) > 0, nil
}
-func (self *ZitiTunnelType) Start(_ model.Run, c *model.Component) error {
+func (self *ZitiTunnelType) GetBinaryName() string {
binaryName := "ziti"
if self.Version != "" {
binaryName += "-" + self.Version
}
+ return binaryName
+}
+
+func (self *ZitiTunnelType) GetConfigName(c *model.Component) string {
+ return fmt.Sprintf("%s.json", c.Id)
+}
+func (self *ZitiTunnelType) Start(_ model.Run, c *model.Component) error {
mode := self.Mode
- factory := lib.NewSshConfigFactory(c.GetHost())
+ user := c.GetHost().GetSshUser()
- binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", factory.User(), binaryName)
- configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s.json", factory.User(), c.Id)
- logsPath := fmt.Sprintf("/home/%s/logs/%s.log", factory.User(), c.Id)
+ binaryPath := fmt.Sprintf("/home/%s/fablab/bin/%s", user, self.GetBinaryName())
+ configPath := fmt.Sprintf("/home/%s/fablab/cfg/%s", user, self.GetConfigName(c))
+ logsPath := fmt.Sprintf("/home/%s/logs/%s.log", user, c.Id)
useSudo := ""
if mode == ZitiTunnelModeTproxy {
useSudo = "sudo"
}
- serviceCmd := fmt.Sprintf("nohup %s %s tunnel %s --log-formatter pfxlog -i %s --cli-agent-alias %s > %s 2>&1 &",
+ serviceCmd := fmt.Sprintf("%s %s tunnel %s --log-formatter pfxlog -i %s --cli-agent-alias %s > %s 2>&1 &",
useSudo, binaryPath, mode.String(), configPath, c.Id, logsPath)
- value, err := lib.RemoteExec(factory, serviceCmd)
+ value, err := c.Host.ExecLogged(
+ "rm -f "+logsPath,
+ serviceCmd)
if err != nil {
return err
}
@@ -132,6 +146,9 @@ func (self *ZitiTunnelType) Start(_ model.Run, c *model.Component) error {
}
func (self *ZitiTunnelType) Stop(_ model.Run, c *model.Component) error {
- factory := lib.NewSshConfigFactory(c.GetHost())
- return lib.RemoteKillSignalFilterF(factory, "-KILL", self.getProcessFilter(c))
+ return c.GetHost().KillProcesses("-KILL", self.getProcessFilter(c))
+}
+
+func (self *ZitiTunnelType) ReEnroll(run model.Run, c *model.Component) error {
+ return reEnrollIdentity(run, c, self.GetBinaryName(), self.GetConfigName(c))
}
diff --git a/zititest/zitilab/models/db_builder.go b/zititest/zitilab/models/db_builder.go
index 86a358149..e78375707 100644
--- a/zititest/zitilab/models/db_builder.go
+++ b/zititest/zitilab/models/db_builder.go
@@ -2,11 +2,11 @@ package models
import (
"fmt"
- "github.com/openziti/ziti/controller/persistence"
"github.com/openziti/fablab/kernel/model"
+ "github.com/openziti/storage/boltz"
"github.com/openziti/ziti/controller/db"
"github.com/openziti/ziti/controller/network"
- "github.com/openziti/storage/boltz"
+ "github.com/openziti/ziti/controller/persistence"
"github.com/openziti/ziti/zititest/zitilab"
"github.com/pkg/errors"
"go.etcd.io/bbolt"
@@ -14,118 +14,120 @@ import (
)
type ZitiDbBuilderStrategy interface {
- GetDbFile() string
+ GetDbFile(m *model.Model) string
GetSite(router *persistence.EdgeRouter) (string, bool)
PostProcess(router *persistence.EdgeRouter, c *model.Component)
+ ProcessDbModel(tx *bbolt.Tx, m *model.Model, builder *ZitiDbBuilder) error
}
type ZitiDbBuilder struct {
- Strategy ZitiDbBuilderStrategy
+ Strategy ZitiDbBuilderStrategy
+ zitiDb boltz.Db
+ stores *db.Stores
+ edgeStores *persistence.Stores
}
-type dbProvider struct {
- zitiDb boltz.Db
- stores *db.Stores
-}
-
-func (self *dbProvider) GetDb() boltz.Db {
+func (self *ZitiDbBuilder) GetDb() boltz.Db {
return self.zitiDb
}
-func (self *dbProvider) GetStores() *db.Stores {
+func (self *ZitiDbBuilder) GetStores() *db.Stores {
return self.stores
}
-func (self *dbProvider) GetManagers() *network.Managers {
+func (self *ZitiDbBuilder) GetEdgeStores() *persistence.Stores {
+ return self.edgeStores
+}
+
+func (self *ZitiDbBuilder) GetManagers() *network.Managers {
panic("should not be needed")
}
func (self *ZitiDbBuilder) Build(m *model.Model) error {
- dbFile := self.Strategy.GetDbFile()
- zitiDb, err := db.Open(dbFile)
+ dbFile := self.Strategy.GetDbFile(m)
+
+ var err error
+ self.zitiDb, err = db.Open(dbFile)
if err != nil {
return errors.Wrapf(err, "unable to open ziti bbolt db [%v]", dbFile)
}
defer func() {
- if err = zitiDb.Close(); err != nil {
+ if err = self.zitiDb.Close(); err != nil {
panic(err)
}
}()
- fabricStore, err := db.InitStores(zitiDb)
+ self.stores, err = db.InitStores(self.zitiDb)
if err != nil {
return errors.Wrapf(err, "unable to init fabric stores using db [%v]", dbFile)
}
- provider := &dbProvider{
- zitiDb: zitiDb,
- stores: fabricStore,
+ self.edgeStores, err = persistence.NewBoltStores(self)
+ if err != nil {
+ return errors.Wrapf(err, "unable to init edge stores using db [%v]", dbFile)
}
- edgeStores, err := persistence.NewBoltStores(provider)
+ return self.zitiDb.View(func(tx *bbolt.Tx) error {
+ return self.Strategy.ProcessDbModel(tx, m, self)
+ })
+}
+
+func (self *ZitiDbBuilder) CreateEdgeRouterHosts(tx *bbolt.Tx, m *model.Model) error {
+ ids, _, err := self.edgeStores.EdgeRouter.QueryIds(tx, "true limit none")
if err != nil {
- return errors.Wrapf(err, "unable to init edge stores using db [%v]", dbFile)
+ return err
}
- err = zitiDb.View(func(tx *bbolt.Tx) error {
- ids, _, err := edgeStores.EdgeRouter.QueryIds(tx, "true limit none")
+ for _, id := range ids {
+ er, err := self.edgeStores.EdgeRouter.LoadOneById(tx, id)
if err != nil {
return err
}
- for _, id := range ids {
- er, err := edgeStores.EdgeRouter.LoadOneById(tx, id)
- if err != nil {
- return err
- }
-
- if site, useEdgeRouter := self.Strategy.GetSite(er); useEdgeRouter {
- regionId := site[:len(site)-1]
+ if site, useEdgeRouter := self.Strategy.GetSite(er); useEdgeRouter {
+ regionId := site[:len(site)-1]
- var region *model.Region
- for _, r := range m.Regions {
- if r.Site == site {
- region = r
- break
- }
+ var region *model.Region
+ for _, r := range m.Regions {
+ if r.Site == site {
+ region = r
+ break
}
+ }
- if region == nil {
- if _, found := m.Regions[site]; found {
- return errors.Errorf("trying to add region for site %v, but one exists, with different site", site)
- }
- region = &model.Region{
- Scope: model.Scope{Tags: model.Tags{}},
- Region: regionId,
- Site: site,
- Hosts: model.Hosts{},
- }
- m.Regions[site] = region
+ if region == nil {
+ if _, found := m.Regions[site]; found {
+ return errors.Errorf("trying to add region for site %v, but one exists, with different site", site)
}
-
- host := &model.Host{
- Scope: model.Scope{Tags: model.Tags{}},
- Region: region,
- Components: model.Components{},
+ region = &model.Region{
+ Scope: model.Scope{Tags: model.Tags{}},
+ Region: regionId,
+ Site: site,
+ Hosts: model.Hosts{},
}
- id := strings.ReplaceAll(er.Id, ".", "_")
- region.Hosts["router_"+id] = host
+ m.Regions[site] = region
+ }
- component := &model.Component{
- Scope: model.Scope{Tags: model.Tags{}},
- Type: &zitilab.RouterType{},
- Host: host,
- }
+ host := &model.Host{
+ Scope: model.Scope{Tags: model.Tags{}},
+ Region: region,
+ Components: model.Components{},
+ }
+ id = strings.ReplaceAll(er.Id, ".", "_")
+ region.Hosts["router_"+id] = host
- host.Components[er.Id] = component
- self.Strategy.PostProcess(er, component)
+ component := &model.Component{
+ Scope: model.Scope{Tags: model.Tags{}},
+ Type: &zitilab.RouterType{},
+ Host: host,
}
- }
- return nil
- })
- return err
+ host.Components[er.Id] = component
+ self.Strategy.PostProcess(er, component)
+ }
+ }
+ return nil
}
func (self *ZitiDbBuilder) DefaultGetSite(er *persistence.EdgeRouter) (string, bool) {
diff --git a/zititest/zitilab/runlevel/0_infrastructure/consul.go b/zititest/zitilab/runlevel/0_infrastructure/consul.go
index beb72a0db..95b76ac62 100644
--- a/zititest/zitilab/runlevel/0_infrastructure/consul.go
+++ b/zititest/zitilab/runlevel/0_infrastructure/consul.go
@@ -2,8 +2,8 @@ package zitilib_runlevel_0_infrastructure
import (
"fmt"
+ "github.com/openziti/fablab/kernel/libssh"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
)
@@ -20,19 +20,19 @@ func InstallConsul(hostSpec string) model.Stage {
func (imb *installConsul) Execute(run model.Run) error {
return run.GetModel().ForEachHost(imb.hostSpec, 25, func(host *model.Host) error {
- ssh := lib.NewSshConfigFactory(host)
+ ssh := host.NewSshConfigFactory()
- if output, err := lib.RemoteExec(ssh, "curl --fail --silent --show-error --location https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/hashicorp-archive-keyring.gpg"); err != nil {
+ if output, err := libssh.RemoteExec(ssh, "curl --fail --silent --show-error --location https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/hashicorp-archive-keyring.gpg"); err != nil {
return fmt.Errorf("error getting hashicorp gpg key on host [%s] %s (%s)", host.PublicIp, output, err)
}
- if output, err := lib.RemoteExec(ssh, "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee -a /etc/apt/sources.list.d/hashicorp.list"); err != nil {
+ if output, err := libssh.RemoteExec(ssh, "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee -a /etc/apt/sources.list.d/hashicorp.list"); err != nil {
return fmt.Errorf("error adding hashicorp repo to apt on host [%s] %s (%s)", host.PublicIp, output, err)
}
cmd := "sudo apt-get update && sudo apt-get install consul -y"
- if output, err := lib.RemoteExec(ssh, cmd); err != nil {
+ if output, err := libssh.RemoteExec(ssh, cmd); err != nil {
return fmt.Errorf("error installing Consul on host [%s] %s (%s)", host.PublicIp, output, err)
}
logrus.Infof("%s => %s", host.PublicIp, "installing Consul")
diff --git a/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go b/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go
index 24f3ab9ba..575aabc5f 100644
--- a/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go
+++ b/zititest/zitilab/runlevel/0_infrastructure/metricbeat.go
@@ -2,8 +2,8 @@ package zitilib_runlevel_0_infrastructure
import (
"fmt"
+ "github.com/openziti/fablab/kernel/libssh"
- "github.com/openziti/fablab/kernel/lib"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
)
@@ -24,13 +24,13 @@ func InstallMetricbeat(hostSpec, version string) model.Stage {
func (imb *installMetricbeat) Execute(run model.Run) error {
return run.GetModel().ForEachHost(imb.hostSpec, 25, func(host *model.Host) error {
- ssh := lib.NewSshConfigFactory(host)
+ ssh := host.NewSshConfigFactory()
- if output, err := lib.RemoteExec(ssh, "wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -"); err != nil {
+ if output, err := libssh.RemoteExec(ssh, "wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -"); err != nil {
return fmt.Errorf("error getting elastic gpg key on host [%s] %s (%s)", host.PublicIp, output, err)
}
- if output, err := lib.RemoteExec(ssh, "echo \"deb https://artifacts.elastic.co/packages/8.x/apt stable main\" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list"); err != nil {
+ if output, err := libssh.RemoteExec(ssh, "echo \"deb https://artifacts.elastic.co/packages/8.x/apt stable main\" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list"); err != nil {
return fmt.Errorf("error adding elastic repo to apt on host [%s] %s (%s)", host.PublicIp, output, err)
}
@@ -41,7 +41,7 @@ func (imb *installMetricbeat) Execute(run model.Run) error {
return ""
}())
- if output, err := lib.RemoteExec(ssh, cmd); err != nil {
+ if output, err := libssh.RemoteExec(ssh, cmd); err != nil {
return fmt.Errorf("error installing metricbeat on host [%s] %s (%s)", host.PublicIp, output, err)
}
logrus.Infof("%s => %s", host.PublicIp, "installing metricbeat")
diff --git a/zititest/zitilab/runlevel/5_operation/loop_dialer.go b/zititest/zitilab/runlevel/5_operation/loop_dialer.go
index 1fe6402a5..a1444ff46 100644
--- a/zititest/zitilab/runlevel/5_operation/loop_dialer.go
+++ b/zititest/zitilab/runlevel/5_operation/loop_dialer.go
@@ -18,7 +18,7 @@ package zitilib_runlevel_5_operation
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
+ "github.com/openziti/fablab/kernel/libssh"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
"strings"
@@ -47,8 +47,8 @@ func LoopDialer(host *model.Host, scenario, endpoint string, joiner chan struct{
}
func (self *loopDialer) Execute(run model.Run) error {
- ssh := lib.NewSshConfigFactory(self.host)
- if err := lib.RemoteKill(ssh, fmt.Sprintf("ziti-fabric-test %v dialer", self.subcmd)); err != nil {
+ ssh := self.host.NewSshConfigFactory()
+ if err := libssh.RemoteKill(ssh, fmt.Sprintf("ziti-fabric-test %v dialer", self.subcmd)); err != nil {
return fmt.Errorf("error killing %v listeners (%w)", self.subcmd, err)
}
@@ -64,11 +64,11 @@ func (self *loopDialer) run(ctx model.Run) {
}
}()
- ssh := lib.NewSshConfigFactory(self.host)
+ ssh := self.host.NewSshConfigFactory()
logFile := fmt.Sprintf("/home/%s/logs/%v-dialer-%s.log", ssh.User(), self.subcmd, ctx.GetId())
dialerCmd := fmt.Sprintf("/home/%s/fablab/bin/ziti-fabric-test %v dialer /home/%s/fablab/cfg/%s -e %s -s %s %s >> %s 2>&1",
ssh.User(), self.subcmd, ssh.User(), self.scenario, self.endpoint, self.host.GetId(), strings.Join(self.extraArgs, " "), logFile)
- if output, err := lib.RemoteExec(ssh, dialerCmd); err != nil {
+ if output, err := libssh.RemoteExec(ssh, dialerCmd); err != nil {
logrus.Errorf("error starting loop dialer [%s] (%v)", output, err)
}
}
diff --git a/zititest/zitilab/runlevel/5_operation/loop_listener.go b/zititest/zitilab/runlevel/5_operation/loop_listener.go
index efc85a087..b9cf8319c 100644
--- a/zititest/zitilab/runlevel/5_operation/loop_listener.go
+++ b/zititest/zitilab/runlevel/5_operation/loop_listener.go
@@ -2,7 +2,7 @@ package zitilib_runlevel_5_operation
import (
"fmt"
- "github.com/openziti/fablab/kernel/lib"
+ "github.com/openziti/fablab/kernel/libssh"
"github.com/openziti/fablab/kernel/model"
"github.com/sirupsen/logrus"
"strings"
@@ -29,8 +29,8 @@ func LoopListener(host *model.Host, joiner chan struct{}, bindAddress string, ex
}
func (self *loopListener) Execute(run model.Run) error {
- ssh := lib.NewSshConfigFactory(self.host)
- if err := lib.RemoteKill(ssh, fmt.Sprintf("ziti-fabric-test %v listener", self.subcmd)); err != nil {
+ ssh := self.host.NewSshConfigFactory()
+ if err := libssh.RemoteKill(ssh, fmt.Sprintf("ziti-fabric-test %v listener", self.subcmd)); err != nil {
return fmt.Errorf("error killing %v listeners (%w)", self.subcmd, err)
}
@@ -46,12 +46,12 @@ func (self *loopListener) run(run model.Run) {
}
}()
- ssh := lib.NewSshConfigFactory(self.host)
+ ssh := self.host.NewSshConfigFactory()
logFile := fmt.Sprintf("/home/%s/logs/%v-listener-%s.log", ssh.User(), self.subcmd, run.GetId())
listenerCmd := fmt.Sprintf("/home/%s/fablab/bin/ziti-fabric-test %v listener -b %v %v >> %s 2>&1",
ssh.User(), self.subcmd, self.bindAddress, strings.Join(self.extraArgs, " "), logFile)
- if output, err := lib.RemoteExec(ssh, listenerCmd); err != nil {
+ if output, err := libssh.RemoteExec(ssh, listenerCmd); err != nil {
logrus.Errorf("error starting loop listener [%s] (%v)", output, err)
}
}