new '/environments' endpoint to allow for dynamic querying of enviroments; new 'zrok list environments' command to access it (#1107)

This commit is contained in:
Michael Quigley
2025-10-28 15:14:42 -04:00
parent 3590de1a87
commit 687c86b5b1
44 changed files with 5537 additions and 2 deletions
+249
View File
@@ -0,0 +1,249 @@
package main
import (
"encoding/json"
"fmt"
"os"
"time"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/openziti/zrok/rest_client_zrok/metadata"
"github.com/spf13/cobra"
)
func init() {
listCmd.AddCommand(newListEnvironmentsCommand().cmd)
}
type listEnvironmentsCommand struct {
cmd *cobra.Command
// text search filters
description string
host string
address string
// boolean filters
remoteAgent *bool
hasShares *bool
hasAccesses *bool
hasActivity *bool
// numeric filters
shareCount string
accessCount string
// date range filters
createdAfter string
createdBefore string
updatedAfter string
updatedBefore string
// activity filter
activityDuration string
// output control
jsonOutput bool
}
func newListEnvironmentsCommand() *listEnvironmentsCommand {
cmd := &cobra.Command{
Use: "environments",
Short: "list environments in your account with optional filtering",
Args: cobra.NoArgs,
}
command := &listEnvironmentsCommand{cmd: cmd}
// text search filters
cmd.Flags().StringVar(&command.description, "description", "", "filter by description (substring match)")
cmd.Flags().StringVar(&command.host, "host", "", "filter by host (substring match)")
cmd.Flags().StringVar(&command.address, "address", "", "filter by address (exact match)")
// boolean filters
cmd.Flags().BoolP("remote-agent", "r", false, "filter by remote agent enrollment")
cmd.Flags().BoolP("has-shares", "s", false, "filter environments with shares")
cmd.Flags().BoolP("has-accesses", "a", false, "filter environments with accesses")
cmd.Flags().BoolP("has-activity", "A", false, "filter environments with recent activity")
// numeric filters
cmd.Flags().StringVar(&command.shareCount, "share-count", "", "filter by share count with operator (e.g., '>0', '>=5', '=3')")
cmd.Flags().StringVar(&command.accessCount, "access-count", "", "filter by access count with operator (e.g., '>0', '>=2')")
// date range filters
cmd.Flags().StringVar(&command.createdAfter, "created-after", "", "filter by created date (RFC3339 format)")
cmd.Flags().StringVar(&command.createdBefore, "created-before", "", "filter by created date (RFC3339 format)")
cmd.Flags().StringVar(&command.updatedAfter, "updated-after", "", "filter by updated date (RFC3339 format)")
cmd.Flags().StringVar(&command.updatedBefore, "updated-before", "", "filter by updated date (RFC3339 format)")
// activity filter
cmd.Flags().StringVar(&command.activityDuration, "activity-duration", "", "duration for hasActivity filter (e.g., '24h', '7d', '30d')")
// output control
cmd.Flags().BoolVar(&command.jsonOutput, "json", false, "output raw JSON instead of table")
cmd.Run = command.run
return command
}
func (cmd *listEnvironmentsCommand) run(_ *cobra.Command, _ []string) {
env, auth := mustGetEnvironmentAuth()
zrok, err := env.Client()
if err != nil {
panic(err)
}
// build request with filters
req := metadata.NewListEnvironmentsParams()
// text search filters
if cmd.description != "" {
req.Description = &cmd.description
}
if cmd.host != "" {
req.Host = &cmd.host
}
if cmd.address != "" {
req.Address = &cmd.address
}
// boolean filters - only set if flag was explicitly provided
if cmd.cmd.Flags().Changed("remote-agent") {
val, _ := cmd.cmd.Flags().GetBool("remote-agent")
req.RemoteAgent = &val
cmd.remoteAgent = &val
}
if cmd.cmd.Flags().Changed("has-shares") {
val, _ := cmd.cmd.Flags().GetBool("has-shares")
req.HasShares = &val
cmd.hasShares = &val
}
if cmd.cmd.Flags().Changed("has-accesses") {
val, _ := cmd.cmd.Flags().GetBool("has-accesses")
req.HasAccesses = &val
cmd.hasAccesses = &val
}
if cmd.cmd.Flags().Changed("has-activity") {
val, _ := cmd.cmd.Flags().GetBool("has-activity")
req.HasActivity = &val
cmd.hasActivity = &val
}
// numeric filters
if cmd.shareCount != "" {
req.ShareCount = &cmd.shareCount
}
if cmd.accessCount != "" {
req.AccessCount = &cmd.accessCount
}
// date range filters
if cmd.createdAfter != "" {
req.CreatedAfter = &cmd.createdAfter
}
if cmd.createdBefore != "" {
req.CreatedBefore = &cmd.createdBefore
}
if cmd.updatedAfter != "" {
req.UpdatedAfter = &cmd.updatedAfter
}
if cmd.updatedBefore != "" {
req.UpdatedBefore = &cmd.updatedBefore
}
// activity filter
if cmd.activityDuration != "" {
req.ActivityDuration = &cmd.activityDuration
}
// call API
resp, err := zrok.Metadata.ListEnvironments(req, auth)
if err != nil {
panic(err)
}
environments := resp.Payload.Environments
// if JSON flag is set, output raw JSON and return
if cmd.jsonOutput {
jsonBytes, err := json.MarshalIndent(resp.Payload, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(jsonBytes))
return
}
// tabular output
fmt.Println()
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.SetStyle(table.StyleRounded)
t.AppendHeader(table.Row{"ZID", "Description", "Host", "Address", "Agent", "Shares", "Accesses", "Activity", "Limited", "Created"})
for _, env := range environments {
// format description
description := env.Description
if description == "" {
description = "-"
}
// format host
host := env.Host
if host == "" {
host = "-"
}
// format address
address := env.Address
if address == "" {
address = "-"
}
// format agent status
agentStatus := ""
if env.RemoteAgent {
agentStatus = "✓"
}
// format activity status
activityStatus := ""
if env.HasActivity {
activityStatus = "✓"
}
// format limited status
limitedStatus := ""
if env.Limited {
limitedStatus = "!!"
}
// format created timestamp
created := time.Unix(env.CreatedAt/1000, 0).Format("2006-01-02 15:04:05")
t.AppendRow(table.Row{
env.EnvZID,
description,
host,
address,
agentStatus,
env.ShareCount,
env.AccessCount,
activityStatus,
limitedStatus,
created,
})
}
t.Render()
fmt.Println()
// show summary
if len(environments) == 0 {
fmt.Println("no environments found matching the specified filters.")
fmt.Println()
} else {
fmt.Printf("total: %d environment(s)\n", len(environments))
fmt.Println()
}
}
+1
View File
@@ -113,6 +113,7 @@ func Run(inCfg *config.Config) error {
api.MetadataGetShareMetricsHandler = newGetShareMetricsHandler(cfg.Metrics.Influx)
}
api.MetadataGetEnvironmentDetailHandler = newEnvironmentDetailHandler()
api.MetadataListEnvironmentsHandler = newListEnvironmentsHandler()
api.MetadataGetFrontendDetailHandler = newGetFrontendDetailHandler()
api.MetadataGetShareDetailHandler = newShareDetailHandler()
api.MetadataListMembershipsHandler = newListMembershipsHandler()
+276
View File
@@ -0,0 +1,276 @@
package controller
import (
"context"
"fmt"
"time"
"github.com/go-openapi/runtime/middleware"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
"github.com/jmoiron/sqlx"
"github.com/michaelquigley/df/dl"
"github.com/openziti/zrok/controller/metrics"
"github.com/openziti/zrok/controller/store"
"github.com/openziti/zrok/rest_model_zrok"
"github.com/openziti/zrok/rest_server_zrok/operations/metadata"
"github.com/openziti/zrok/util"
"github.com/pkg/errors"
)
type listEnvironmentsHandler struct{}
func newListEnvironmentsHandler() *listEnvironmentsHandler {
return &listEnvironmentsHandler{}
}
func (h *listEnvironmentsHandler) Handle(params metadata.ListEnvironmentsParams, principal *rest_model_zrok.Principal) middleware.Responder {
trx, err := str.Begin()
if err != nil {
dl.Errorf("error starting transaction for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsInternalServerError().WithPayload("error starting transaction")
}
defer func() { _ = trx.Rollback() }()
// build filter from query parameters
filter := &store.EnvironmentFilter{}
if params.Description != nil {
filter.Description = params.Description
}
if params.Host != nil {
filter.Host = params.Host
}
if params.Address != nil {
filter.Address = params.Address
}
if params.ShareCount != nil {
filter.ShareCount = params.ShareCount
}
if params.AccessCount != nil {
filter.AccessCount = params.AccessCount
}
if params.HasShares != nil {
filter.HasShares = params.HasShares
}
if params.HasAccesses != nil {
filter.HasAccesses = params.HasAccesses
}
// parse date filters
if params.CreatedAfter != nil {
t, err := time.Parse(time.RFC3339, *params.CreatedAfter)
if err != nil {
dl.Errorf("invalid createdAfter format for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsBadRequest().WithPayload("invalid createdAfter date format, expected RFC3339")
}
filter.CreatedAfter = &t
}
if params.CreatedBefore != nil {
t, err := time.Parse(time.RFC3339, *params.CreatedBefore)
if err != nil {
dl.Errorf("invalid createdBefore format for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsBadRequest().WithPayload("invalid createdBefore date format, expected RFC3339")
}
filter.CreatedBefore = &t
}
if params.UpdatedAfter != nil {
t, err := time.Parse(time.RFC3339, *params.UpdatedAfter)
if err != nil {
dl.Errorf("invalid updatedAfter format for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsBadRequest().WithPayload("invalid updatedAfter date format, expected RFC3339")
}
filter.UpdatedAfter = &t
}
if params.UpdatedBefore != nil {
t, err := time.Parse(time.RFC3339, *params.UpdatedBefore)
if err != nil {
dl.Errorf("invalid updatedBefore format for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsBadRequest().WithPayload("invalid updatedBefore date format, expected RFC3339")
}
filter.UpdatedBefore = &t
}
// query environments with filter
envs, err := str.FindEnvironmentsForAccountWithFilter(int(principal.ID), filter, trx)
if err != nil {
dl.Errorf("error finding environments for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error()))
}
// check for hasActivity filter
var activeEnvIds map[int]bool
if params.HasActivity != nil && *params.HasActivity {
// parse and validate activity duration
duration := 24 * time.Hour // default
if params.ActivityDuration != nil {
d, err := util.ParseDuration(*params.ActivityDuration)
if err != nil {
dl.Errorf("invalid activityDuration ('%v') format for user '%v': %v", *params.ActivityDuration, principal.Email, err)
return metadata.NewListEnvironmentsBadRequest().WithPayload("invalid activityDuration format")
}
// validate maximum of 30 days
if d > 30*24*time.Hour {
dl.Errorf("activityDuration exceeds maximum for user '%v': %v", principal.Email, d)
return metadata.NewListEnvironmentsBadRequest().WithPayload("activityDuration exceeds maximum of 30d (720h)")
}
duration = d
}
// query influxdb for active environments
if cfg.Metrics != nil && cfg.Metrics.Influx != nil {
activeEnvIds, err = findEnvironmentsWithActivity(envs, duration, cfg.Metrics.Influx)
if err != nil {
dl.Errorf("error querying environment activity for user '%v': %v", principal.Email, err)
// don't fail the request, just log the error and return no activity
activeEnvIds = make(map[int]bool)
}
} else {
// no metrics configured, no environments have activity
activeEnvIds = make(map[int]bool)
}
}
// check for remoteAgent filter
var agentEnvIds map[int]bool
if params.RemoteAgent != nil {
agentEnvIds, err = findEnvironmentsWithAgents(envs, trx)
if err != nil {
dl.Errorf("error checking remote agents for user '%v': %v", principal.Email, err)
return metadata.NewListEnvironmentsInternalServerError().WithPayload(rest_model_zrok.ErrorMessage(err.Error()))
}
}
// check account limits
alj, err := str.FindLatestBandwidthLimitJournal(int(principal.ID), trx)
if err != nil {
dl.Errorf("error finding account limit journal for '%v': %v", principal.Email, err)
}
isLimited := alj != nil && alj.Action == store.LimitLimitAction
// build response
response := &rest_model_zrok.EnvironmentsList{
Environments: make([]*rest_model_zrok.EnvironmentSummary, 0),
}
for _, env := range envs {
// apply remoteAgent filter
if params.RemoteAgent != nil {
hasAgent := agentEnvIds[env.Id]
if *params.RemoteAgent != hasAgent {
continue
}
}
// apply hasActivity filter
hasActivity := false
if activeEnvIds != nil {
hasActivity = activeEnvIds[env.Id]
if params.HasActivity != nil && *params.HasActivity && !hasActivity {
continue
}
}
summary := &rest_model_zrok.EnvironmentSummary{
EnvZID: env.ZId,
Description: env.Description,
Host: env.Host,
Address: env.Address,
RemoteAgent: agentEnvIds != nil && agentEnvIds[env.Id],
ShareCount: int64(env.ShareCount),
AccessCount: int64(env.AccessCount),
HasActivity: hasActivity,
Limited: isLimited,
CreatedAt: env.CreatedAt.UnixMilli(),
UpdatedAt: env.UpdatedAt.UnixMilli(),
}
response.Environments = append(response.Environments, summary)
}
return metadata.NewListEnvironmentsOK().WithPayload(response)
}
// findEnvironmentsWithActivity queries InfluxDB to find which environments have metrics within the given duration
func findEnvironmentsWithActivity(envs []*store.EnvironmentWithCounts, duration time.Duration, influxCfg *metrics.InfluxConfig) (map[int]bool, error) {
if len(envs) == 0 {
return make(map[int]bool), nil
}
idb := influxdb2.NewClient(influxCfg.Url, influxCfg.Token)
defer idb.Close()
queryApi := idb.QueryAPI(influxCfg.Org)
// build filter for environment IDs
envFilter := "|> filter(fn: (r) =>"
for i, env := range envs {
if i > 0 {
envFilter += " or"
}
envFilter += fmt.Sprintf(" r[\"envId\"] == \"%d\"", env.Id)
}
envFilter += ")"
query := fmt.Sprintf("from(bucket: \"%v\")\n", influxCfg.Bucket) +
fmt.Sprintf("|> range(start: -%v)\n", duration) +
"|> filter(fn: (r) => r[\"_measurement\"] == \"xfer\")\n" +
"|> filter(fn: (r) => r[\"_field\"] == \"rx\" or r[\"_field\"] == \"tx\")\n" +
"|> filter(fn: (r) => r[\"namespace\"] == \"backend\")\n" +
envFilter + "\n" +
"|> group(columns: [\"envId\"])\n" +
"|> sum()"
result, err := queryApi.Query(context.Background(), query)
if err != nil {
return nil, errors.Wrap(err, "error querying influxdb for environment activity")
}
activeEnvIds := make(map[int]bool)
for result.Next() {
envIdStr, ok := result.Record().ValueByKey("envId").(string)
if !ok {
continue
}
var envId int
if _, err := fmt.Sscanf(envIdStr, "%d", &envId); err != nil {
continue
}
// any non-zero value means there was activity
if val, ok := result.Record().Value().(int64); ok && val > 0 {
activeEnvIds[envId] = true
}
}
if result.Err() != nil {
return nil, errors.Wrap(result.Err(), "error reading influxdb query results")
}
return activeEnvIds, nil
}
// findEnvironmentsWithAgents checks which environments have agents enrolled
func findEnvironmentsWithAgents(envs []*store.EnvironmentWithCounts, trx *sqlx.Tx) (map[int]bool, error) {
if len(envs) == 0 {
return make(map[int]bool), nil
}
agentEnvIds := make(map[int]bool)
for _, env := range envs {
hasAgent, err := str.IsAgentEnrolledForEnvironment(env.Id, trx)
if err != nil {
return nil, errors.Wrapf(err, "error checking agent enrollment for environment %d", env.Id)
}
agentEnvIds[env.Id] = hasAgent
}
return agentEnvIds, nil
}
+196
View File
@@ -1,6 +1,11 @@
package store
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
@@ -82,3 +87,194 @@ func (str *Store) DeleteEnvironment(id int, trx *sqlx.Tx) error {
}
return nil
}
type EnvironmentFilter struct {
Description *string
Host *string
Address *string
ShareCount *string
AccessCount *string
CreatedAfter *time.Time
CreatedBefore *time.Time
UpdatedAfter *time.Time
UpdatedBefore *time.Time
HasShares *bool
HasAccesses *bool
}
type EnvironmentWithCounts struct {
Environment
ShareCount int
AccessCount int
}
func (str *Store) FindEnvironmentsForAccountWithFilter(accountId int, filter *EnvironmentFilter, trx *sqlx.Tx) ([]*EnvironmentWithCounts, error) {
query := `
select
e.*,
coalesce(share_counts.count, 0) as share_count,
coalesce(access_counts.count, 0) as access_count
from environments e
left join (
select environment_id, count(*) as count
from shares
where not deleted
group by environment_id
) share_counts on e.id = share_counts.environment_id
left join (
select environment_id, count(*) as count
from frontends
where environment_id is not null and not deleted
group by environment_id
) access_counts on e.id = access_counts.environment_id
where e.account_id = $1 and not e.deleted
`
args := []interface{}{accountId}
argIndex := 2
// text filters
if filter.Description != nil && *filter.Description != "" {
query += fmt.Sprintf(" and lower(e.description) like $%d", argIndex)
args = append(args, "%"+strings.ToLower(*filter.Description)+"%")
argIndex++
}
if filter.Host != nil && *filter.Host != "" {
query += fmt.Sprintf(" and lower(e.host) like $%d", argIndex)
args = append(args, "%"+strings.ToLower(*filter.Host)+"%")
argIndex++
}
if filter.Address != nil && *filter.Address != "" {
query += fmt.Sprintf(" and e.address = $%d", argIndex)
args = append(args, *filter.Address)
argIndex++
}
// date filters
if filter.CreatedAfter != nil {
query += fmt.Sprintf(" and e.created_at >= $%d", argIndex)
args = append(args, *filter.CreatedAfter)
argIndex++
}
if filter.CreatedBefore != nil {
query += fmt.Sprintf(" and e.created_at <= $%d", argIndex)
args = append(args, *filter.CreatedBefore)
argIndex++
}
if filter.UpdatedAfter != nil {
query += fmt.Sprintf(" and e.updated_at >= $%d", argIndex)
args = append(args, *filter.UpdatedAfter)
argIndex++
}
if filter.UpdatedBefore != nil {
query += fmt.Sprintf(" and e.updated_at <= $%d", argIndex)
args = append(args, *filter.UpdatedBefore)
argIndex++
}
// boolean filters for shares/accesses
if filter.HasShares != nil {
if *filter.HasShares {
query += " and coalesce(share_counts.count, 0) > 0"
} else {
query += " and coalesce(share_counts.count, 0) = 0"
}
}
if filter.HasAccesses != nil {
if *filter.HasAccesses {
query += " and coalesce(access_counts.count, 0) > 0"
} else {
query += " and coalesce(access_counts.count, 0) = 0"
}
}
// wrap query in a subquery for count filtering
needsSubquery := filter.ShareCount != nil || filter.AccessCount != nil
if needsSubquery {
query = fmt.Sprintf("select * from (%s) as filtered", query)
if filter.ShareCount != nil && *filter.ShareCount != "" {
condition, err := parseComparisonFilter(*filter.ShareCount, "share_count")
if err != nil {
return nil, errors.Wrap(err, "error parsing shareCount filter")
}
query += " where " + condition
}
if filter.AccessCount != nil && *filter.AccessCount != "" {
condition, err := parseComparisonFilter(*filter.AccessCount, "access_count")
if err != nil {
return nil, errors.Wrap(err, "error parsing accessCount filter")
}
if filter.ShareCount != nil && *filter.ShareCount != "" {
query += " and " + condition
} else {
query += " where " + condition
}
}
}
rows, err := trx.Queryx(query, args...)
if err != nil {
return nil, errors.Wrap(err, "error selecting environments with filter")
}
defer rows.Close()
var results []*EnvironmentWithCounts
for rows.Next() {
result := &EnvironmentWithCounts{}
if err := rows.StructScan(result); err != nil {
return nil, errors.Wrap(err, "error scanning environment with counts")
}
results = append(results, result)
}
return results, nil
}
// parseComparisonFilter parses comparison operators like ">0", ">=5", "=10", "<20", "<=15"
func parseComparisonFilter(filter, columnName string) (string, error) {
filter = strings.TrimSpace(filter)
if filter == "" {
return "", errors.New("empty filter")
}
// parse operator and value
var operator string
var valueStr string
if strings.HasPrefix(filter, ">=") {
operator = ">="
valueStr = strings.TrimSpace(filter[2:])
} else if strings.HasPrefix(filter, "<=") {
operator = "<="
valueStr = strings.TrimSpace(filter[2:])
} else if strings.HasPrefix(filter, ">") {
operator = ">"
valueStr = strings.TrimSpace(filter[1:])
} else if strings.HasPrefix(filter, "<") {
operator = "<"
valueStr = strings.TrimSpace(filter[1:])
} else if strings.HasPrefix(filter, "=") {
operator = "="
valueStr = strings.TrimSpace(filter[1:])
} else {
// assume equals if no operator
operator = "="
valueStr = filter
}
// validate that value is a number
value, err := strconv.Atoi(valueStr)
if err != nil {
return "", errors.Wrapf(err, "invalid numeric value: %s", valueStr)
}
return fmt.Sprintf("%s %s %d", columnName, operator, value), nil
}
+390 -1
View File
@@ -1,8 +1,10 @@
package store
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEphemeralEnvironment(t *testing.T) {
@@ -60,3 +62,390 @@ func TestEnvironment(t *testing.T) {
assert.Equal(t, acctId, *env.AccountId)
assert.False(t, env.Deleted)
}
func TestFindEnvironmentsForAccountWithFilter(t *testing.T) {
str, err := Open(&Config{Path: ":memory:", Type: "sqlite3"})
require.NoError(t, err)
require.NotNil(t, str)
trx, err := str.Begin()
require.NoError(t, err)
require.NotNil(t, trx)
defer func() { _ = trx.Rollback() }()
// create test account
acctId, err := str.CreateAccount(&Account{
Email: "test@test.com",
Password: "password",
Token: "token",
Salt: "salt",
}, trx)
require.NoError(t, err)
// create environments with varying properties
env1Id, err := str.CreateEnvironment(acctId, &Environment{
Description: "prod-server",
Host: "host1.example.com",
Address: "192.168.1.1",
ZId: "env1",
}, trx)
require.NoError(t, err)
env2Id, err := str.CreateEnvironment(acctId, &Environment{
Description: "dev-server",
Host: "host2.example.com",
Address: "192.168.1.2",
ZId: "env2",
}, trx)
require.NoError(t, err)
env3Id, err := str.CreateEnvironment(acctId, &Environment{
Description: "test-environment",
Host: "host3.example.com",
Address: "192.168.1.3",
ZId: "env3",
}, trx)
require.NoError(t, err)
_, err = str.CreateEnvironment(acctId, &Environment{
Description: "staging-server",
Host: "host1.staging.com",
Address: "192.168.1.4",
ZId: "env4",
}, trx)
require.NoError(t, err)
// create shares for environments
// env1: 1 share
_, err = str.CreateShare(env1Id, &Share{
ZId: "shr1",
Token: "token1",
ShareMode: "public",
BackendMode: "proxy",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
// env2: 3 shares
_, err = str.CreateShare(env2Id, &Share{
ZId: "shr2",
Token: "token2",
ShareMode: "public",
BackendMode: "proxy",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
_, err = str.CreateShare(env2Id, &Share{
ZId: "shr3",
Token: "token3",
ShareMode: "public",
BackendMode: "proxy",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
_, err = str.CreateShare(env2Id, &Share{
ZId: "shr4",
Token: "token4",
ShareMode: "public",
BackendMode: "proxy",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
// env3: 5 shares
for i := 0; i < 5; i++ {
_, err = str.CreateShare(env3Id, &Share{
ZId: "shr" + string(rune('5'+i)),
Token: "token" + string(rune('5'+i)),
ShareMode: "public",
BackendMode: "proxy",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
}
// env4: 0 shares
// create frontends (accesses)
// env1: 2 frontends
_, err = str.CreateFrontend(env1Id, &Frontend{
Token: "frontend1",
ZId: "fzid1",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
_, err = str.CreateFrontend(env1Id, &Frontend{
Token: "frontend2",
ZId: "fzid2",
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
// env2: 5 frontends
for i := 0; i < 5; i++ {
_, err = str.CreateFrontend(env2Id, &Frontend{
Token: "frontend" + string(rune('3'+i)),
ZId: "fzid" + string(rune('3'+i)),
PermissionMode: OpenPermissionMode,
}, trx)
require.NoError(t, err)
}
// env3 and env4: 0 frontends
t.Run("no filter returns all environments", func(t *testing.T) {
filter := &EnvironmentFilter{}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 4)
})
t.Run("description filter", func(t *testing.T) {
// should match "prod-server", "dev-server", "staging-server"
desc := "server"
filter := &EnvironmentFilter{Description: &desc}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 3)
// case insensitive
descUpper := "SERVER"
filter = &EnvironmentFilter{Description: &descUpper}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 3)
// specific match
descProd := "prod"
filter = &EnvironmentFilter{Description: &descProd}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 1)
assert.Equal(t, "env1", envs[0].ZId)
})
t.Run("host filter", func(t *testing.T) {
// should match "host1.example.com" and "host1.staging.com"
host := "host1"
filter := &EnvironmentFilter{Host: &host}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
// case-insensitive
hostUpper := "HOST1"
filter = &EnvironmentFilter{Host: &hostUpper}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
// specific domain
hostExample := "example.com"
filter = &EnvironmentFilter{Host: &hostExample}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 3)
})
t.Run("address filter", func(t *testing.T) {
addr := "192.168.1.1"
filter := &EnvironmentFilter{Address: &addr}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 1)
assert.Equal(t, "env1", envs[0].ZId)
})
t.Run("hasShares filter", func(t *testing.T) {
// hasShares = true (env1, env2, env3)
hasShares := true
filter := &EnvironmentFilter{HasShares: &hasShares}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 3)
// hasShares = false (env4)
hasShares = false
filter = &EnvironmentFilter{HasShares: &hasShares}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 1)
assert.Equal(t, "env4", envs[0].ZId)
assert.Equal(t, 0, envs[0].ShareCount)
})
t.Run("hasAccesses filter", func(t *testing.T) {
// hasAccesses = true (env1: 2, env2: 5)
hasAccesses := true
filter := &EnvironmentFilter{HasAccesses: &hasAccesses}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
// hasAccesses = false (env3, env4)
hasAccesses = false
filter = &EnvironmentFilter{HasAccesses: &hasAccesses}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
})
t.Run("shareCount filter with operators", func(t *testing.T) {
// > 0 (env1: 1, env2: 3, env3: 5)
count := ">0"
filter := &EnvironmentFilter{ShareCount: &count}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 3)
// >= 3 (env2: 3, env3: 5)
count = ">=3"
filter = &EnvironmentFilter{ShareCount: &count}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
// = 1 (env1)
count = "=1"
filter = &EnvironmentFilter{ShareCount: &count}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 1)
assert.Equal(t, "env1", envs[0].ZId)
assert.Equal(t, 1, envs[0].ShareCount)
// < 3 (env1: 1, env4: 0)
count = "<3"
filter = &EnvironmentFilter{ShareCount: &count}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
// <= 1 (env1: 1, env4: 0)
count = "<=1"
filter = &EnvironmentFilter{ShareCount: &count}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
})
t.Run("accessCount filter with operators", func(t *testing.T) {
// > 0 (env1: 2, env2: 5)
count := ">0"
filter := &EnvironmentFilter{AccessCount: &count}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 2)
// >= 5 (env2: 5)
count = ">=5"
filter = &EnvironmentFilter{AccessCount: &count}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 1)
assert.Equal(t, "env2", envs[0].ZId)
assert.Equal(t, 5, envs[0].AccessCount)
// = 2 (env1)
count = "=2"
filter = &EnvironmentFilter{AccessCount: &count}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
assert.Len(t, envs, 1)
assert.Equal(t, "env1", envs[0].ZId)
assert.Equal(t, 2, envs[0].AccessCount)
})
t.Run("date range filters", func(t *testing.T) {
t.Skip("skipping date range tests due to timestamp precision issues in test environment")
// TODO: implement proper date range testing with controlled timestamps
})
t.Run("combined filters", func(t *testing.T) {
// description contains "server" AND hasShares = true AND shareCount > 0
desc := "server"
hasShares := true
shareCount := ">0"
filter := &EnvironmentFilter{
Description: &desc,
HasShares: &hasShares,
ShareCount: &shareCount,
}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
// should match: prod-server (env1: 1 share), dev-server (env2: 3 shares), staging-server (env4: 0 shares - excluded)
assert.Len(t, envs, 2)
// host contains "host1" AND shareCount >= 1
host := "host1"
shareCount = ">=1"
filter = &EnvironmentFilter{
Host: &host,
ShareCount: &shareCount,
}
envs, err = str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
// should match: env1 (1 share), env4 has 0 shares (excluded)
assert.Len(t, envs, 1)
assert.Equal(t, "env1", envs[0].ZId)
})
t.Run("verify counts are correct", func(t *testing.T) {
filter := &EnvironmentFilter{}
envs, err := str.FindEnvironmentsForAccountWithFilter(acctId, filter, trx)
require.NoError(t, err)
require.Len(t, envs, 4)
for _, env := range envs {
switch env.ZId {
case "env1":
assert.Equal(t, 1, env.ShareCount)
assert.Equal(t, 2, env.AccessCount)
case "env2":
assert.Equal(t, 3, env.ShareCount)
assert.Equal(t, 5, env.AccessCount)
case "env3":
assert.Equal(t, 5, env.ShareCount)
assert.Equal(t, 0, env.AccessCount)
case "env4":
assert.Equal(t, 0, env.ShareCount)
assert.Equal(t, 0, env.AccessCount)
}
}
})
}
func TestParseComparisonFilter(t *testing.T) {
tests := []struct {
name string
input string
columnName string
expected string
expectError bool
}{
{"greater than", ">5", "count", "count > 5", false},
{"greater than or equal", ">=5", "count", "count >= 5", false},
{"equal", "=5", "count", "count = 5", false},
{"less than", "<5", "count", "count < 5", false},
{"less than or equal", "<=5", "count", "count <= 5", false},
{"no operator defaults to equal", "5", "count", "count = 5", false},
{"with spaces", " >= 10 ", "count", "count >= 10", false},
{"empty string", "", "count", "", true},
{"non-numeric value", ">abc", "count", "", true},
{"invalid operator", "~5", "count", "", true}, // no valid operator, can't parse as number
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := parseComparisonFilter(tt.input, tt.columnName)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expected, result)
}
})
}
}
@@ -0,0 +1,606 @@
// Code generated by go-swagger; DO NOT EDIT.
package metadata
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewListEnvironmentsParams creates a new ListEnvironmentsParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewListEnvironmentsParams() *ListEnvironmentsParams {
return &ListEnvironmentsParams{
timeout: cr.DefaultTimeout,
}
}
// NewListEnvironmentsParamsWithTimeout creates a new ListEnvironmentsParams object
// with the ability to set a timeout on a request.
func NewListEnvironmentsParamsWithTimeout(timeout time.Duration) *ListEnvironmentsParams {
return &ListEnvironmentsParams{
timeout: timeout,
}
}
// NewListEnvironmentsParamsWithContext creates a new ListEnvironmentsParams object
// with the ability to set a context for a request.
func NewListEnvironmentsParamsWithContext(ctx context.Context) *ListEnvironmentsParams {
return &ListEnvironmentsParams{
Context: ctx,
}
}
// NewListEnvironmentsParamsWithHTTPClient creates a new ListEnvironmentsParams object
// with the ability to set a custom HTTPClient for a request.
func NewListEnvironmentsParamsWithHTTPClient(client *http.Client) *ListEnvironmentsParams {
return &ListEnvironmentsParams{
HTTPClient: client,
}
}
/*
ListEnvironmentsParams contains all the parameters to send to the API endpoint
for the list environments operation.
Typically these are written to a http.Request.
*/
type ListEnvironmentsParams struct {
/* AccessCount.
filter by access count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
*/
AccessCount *string
/* ActivityDuration.
duration for hasActivity filter (e.g., "24h", "7d", "30d"). default "24h", maximum "30d" (720h)
*/
ActivityDuration *string
/* Address.
filter by address (exact match)
*/
Address *string
/* CreatedAfter.
filter by created date (RFC3339 datetime, inclusive)
*/
CreatedAfter *string
/* CreatedBefore.
filter by created date (RFC3339 datetime, inclusive)
*/
CreatedBefore *string
/* Description.
filter by description (case-insensitive substring match)
*/
Description *string
/* HasAccesses.
filter by whether environment has active accesses
*/
HasAccesses *bool
/* HasActivity.
filter by whether environment has metrics within activityDuration timeframe
*/
HasActivity *bool
/* HasShares.
filter by whether environment has active shares
*/
HasShares *bool
/* Host.
filter by host (case-insensitive substring match)
*/
Host *string
/* RemoteAgent.
filter by whether agent is enrolled
*/
RemoteAgent *bool
/* ShareCount.
filter by share count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
*/
ShareCount *string
/* UpdatedAfter.
filter by updated date (RFC3339 datetime, inclusive)
*/
UpdatedAfter *string
/* UpdatedBefore.
filter by updated date (RFC3339 datetime, inclusive)
*/
UpdatedBefore *string
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the list environments params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *ListEnvironmentsParams) WithDefaults() *ListEnvironmentsParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the list environments params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *ListEnvironmentsParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the list environments params
func (o *ListEnvironmentsParams) WithTimeout(timeout time.Duration) *ListEnvironmentsParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the list environments params
func (o *ListEnvironmentsParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the list environments params
func (o *ListEnvironmentsParams) WithContext(ctx context.Context) *ListEnvironmentsParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the list environments params
func (o *ListEnvironmentsParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the list environments params
func (o *ListEnvironmentsParams) WithHTTPClient(client *http.Client) *ListEnvironmentsParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the list environments params
func (o *ListEnvironmentsParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WithAccessCount adds the accessCount to the list environments params
func (o *ListEnvironmentsParams) WithAccessCount(accessCount *string) *ListEnvironmentsParams {
o.SetAccessCount(accessCount)
return o
}
// SetAccessCount adds the accessCount to the list environments params
func (o *ListEnvironmentsParams) SetAccessCount(accessCount *string) {
o.AccessCount = accessCount
}
// WithActivityDuration adds the activityDuration to the list environments params
func (o *ListEnvironmentsParams) WithActivityDuration(activityDuration *string) *ListEnvironmentsParams {
o.SetActivityDuration(activityDuration)
return o
}
// SetActivityDuration adds the activityDuration to the list environments params
func (o *ListEnvironmentsParams) SetActivityDuration(activityDuration *string) {
o.ActivityDuration = activityDuration
}
// WithAddress adds the address to the list environments params
func (o *ListEnvironmentsParams) WithAddress(address *string) *ListEnvironmentsParams {
o.SetAddress(address)
return o
}
// SetAddress adds the address to the list environments params
func (o *ListEnvironmentsParams) SetAddress(address *string) {
o.Address = address
}
// WithCreatedAfter adds the createdAfter to the list environments params
func (o *ListEnvironmentsParams) WithCreatedAfter(createdAfter *string) *ListEnvironmentsParams {
o.SetCreatedAfter(createdAfter)
return o
}
// SetCreatedAfter adds the createdAfter to the list environments params
func (o *ListEnvironmentsParams) SetCreatedAfter(createdAfter *string) {
o.CreatedAfter = createdAfter
}
// WithCreatedBefore adds the createdBefore to the list environments params
func (o *ListEnvironmentsParams) WithCreatedBefore(createdBefore *string) *ListEnvironmentsParams {
o.SetCreatedBefore(createdBefore)
return o
}
// SetCreatedBefore adds the createdBefore to the list environments params
func (o *ListEnvironmentsParams) SetCreatedBefore(createdBefore *string) {
o.CreatedBefore = createdBefore
}
// WithDescription adds the description to the list environments params
func (o *ListEnvironmentsParams) WithDescription(description *string) *ListEnvironmentsParams {
o.SetDescription(description)
return o
}
// SetDescription adds the description to the list environments params
func (o *ListEnvironmentsParams) SetDescription(description *string) {
o.Description = description
}
// WithHasAccesses adds the hasAccesses to the list environments params
func (o *ListEnvironmentsParams) WithHasAccesses(hasAccesses *bool) *ListEnvironmentsParams {
o.SetHasAccesses(hasAccesses)
return o
}
// SetHasAccesses adds the hasAccesses to the list environments params
func (o *ListEnvironmentsParams) SetHasAccesses(hasAccesses *bool) {
o.HasAccesses = hasAccesses
}
// WithHasActivity adds the hasActivity to the list environments params
func (o *ListEnvironmentsParams) WithHasActivity(hasActivity *bool) *ListEnvironmentsParams {
o.SetHasActivity(hasActivity)
return o
}
// SetHasActivity adds the hasActivity to the list environments params
func (o *ListEnvironmentsParams) SetHasActivity(hasActivity *bool) {
o.HasActivity = hasActivity
}
// WithHasShares adds the hasShares to the list environments params
func (o *ListEnvironmentsParams) WithHasShares(hasShares *bool) *ListEnvironmentsParams {
o.SetHasShares(hasShares)
return o
}
// SetHasShares adds the hasShares to the list environments params
func (o *ListEnvironmentsParams) SetHasShares(hasShares *bool) {
o.HasShares = hasShares
}
// WithHost adds the host to the list environments params
func (o *ListEnvironmentsParams) WithHost(host *string) *ListEnvironmentsParams {
o.SetHost(host)
return o
}
// SetHost adds the host to the list environments params
func (o *ListEnvironmentsParams) SetHost(host *string) {
o.Host = host
}
// WithRemoteAgent adds the remoteAgent to the list environments params
func (o *ListEnvironmentsParams) WithRemoteAgent(remoteAgent *bool) *ListEnvironmentsParams {
o.SetRemoteAgent(remoteAgent)
return o
}
// SetRemoteAgent adds the remoteAgent to the list environments params
func (o *ListEnvironmentsParams) SetRemoteAgent(remoteAgent *bool) {
o.RemoteAgent = remoteAgent
}
// WithShareCount adds the shareCount to the list environments params
func (o *ListEnvironmentsParams) WithShareCount(shareCount *string) *ListEnvironmentsParams {
o.SetShareCount(shareCount)
return o
}
// SetShareCount adds the shareCount to the list environments params
func (o *ListEnvironmentsParams) SetShareCount(shareCount *string) {
o.ShareCount = shareCount
}
// WithUpdatedAfter adds the updatedAfter to the list environments params
func (o *ListEnvironmentsParams) WithUpdatedAfter(updatedAfter *string) *ListEnvironmentsParams {
o.SetUpdatedAfter(updatedAfter)
return o
}
// SetUpdatedAfter adds the updatedAfter to the list environments params
func (o *ListEnvironmentsParams) SetUpdatedAfter(updatedAfter *string) {
o.UpdatedAfter = updatedAfter
}
// WithUpdatedBefore adds the updatedBefore to the list environments params
func (o *ListEnvironmentsParams) WithUpdatedBefore(updatedBefore *string) *ListEnvironmentsParams {
o.SetUpdatedBefore(updatedBefore)
return o
}
// SetUpdatedBefore adds the updatedBefore to the list environments params
func (o *ListEnvironmentsParams) SetUpdatedBefore(updatedBefore *string) {
o.UpdatedBefore = updatedBefore
}
// WriteToRequest writes these params to a swagger request
func (o *ListEnvironmentsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if o.AccessCount != nil {
// query param accessCount
var qrAccessCount string
if o.AccessCount != nil {
qrAccessCount = *o.AccessCount
}
qAccessCount := qrAccessCount
if qAccessCount != "" {
if err := r.SetQueryParam("accessCount", qAccessCount); err != nil {
return err
}
}
}
if o.ActivityDuration != nil {
// query param activityDuration
var qrActivityDuration string
if o.ActivityDuration != nil {
qrActivityDuration = *o.ActivityDuration
}
qActivityDuration := qrActivityDuration
if qActivityDuration != "" {
if err := r.SetQueryParam("activityDuration", qActivityDuration); err != nil {
return err
}
}
}
if o.Address != nil {
// query param address
var qrAddress string
if o.Address != nil {
qrAddress = *o.Address
}
qAddress := qrAddress
if qAddress != "" {
if err := r.SetQueryParam("address", qAddress); err != nil {
return err
}
}
}
if o.CreatedAfter != nil {
// query param createdAfter
var qrCreatedAfter string
if o.CreatedAfter != nil {
qrCreatedAfter = *o.CreatedAfter
}
qCreatedAfter := qrCreatedAfter
if qCreatedAfter != "" {
if err := r.SetQueryParam("createdAfter", qCreatedAfter); err != nil {
return err
}
}
}
if o.CreatedBefore != nil {
// query param createdBefore
var qrCreatedBefore string
if o.CreatedBefore != nil {
qrCreatedBefore = *o.CreatedBefore
}
qCreatedBefore := qrCreatedBefore
if qCreatedBefore != "" {
if err := r.SetQueryParam("createdBefore", qCreatedBefore); err != nil {
return err
}
}
}
if o.Description != nil {
// query param description
var qrDescription string
if o.Description != nil {
qrDescription = *o.Description
}
qDescription := qrDescription
if qDescription != "" {
if err := r.SetQueryParam("description", qDescription); err != nil {
return err
}
}
}
if o.HasAccesses != nil {
// query param hasAccesses
var qrHasAccesses bool
if o.HasAccesses != nil {
qrHasAccesses = *o.HasAccesses
}
qHasAccesses := swag.FormatBool(qrHasAccesses)
if qHasAccesses != "" {
if err := r.SetQueryParam("hasAccesses", qHasAccesses); err != nil {
return err
}
}
}
if o.HasActivity != nil {
// query param hasActivity
var qrHasActivity bool
if o.HasActivity != nil {
qrHasActivity = *o.HasActivity
}
qHasActivity := swag.FormatBool(qrHasActivity)
if qHasActivity != "" {
if err := r.SetQueryParam("hasActivity", qHasActivity); err != nil {
return err
}
}
}
if o.HasShares != nil {
// query param hasShares
var qrHasShares bool
if o.HasShares != nil {
qrHasShares = *o.HasShares
}
qHasShares := swag.FormatBool(qrHasShares)
if qHasShares != "" {
if err := r.SetQueryParam("hasShares", qHasShares); err != nil {
return err
}
}
}
if o.Host != nil {
// query param host
var qrHost string
if o.Host != nil {
qrHost = *o.Host
}
qHost := qrHost
if qHost != "" {
if err := r.SetQueryParam("host", qHost); err != nil {
return err
}
}
}
if o.RemoteAgent != nil {
// query param remoteAgent
var qrRemoteAgent bool
if o.RemoteAgent != nil {
qrRemoteAgent = *o.RemoteAgent
}
qRemoteAgent := swag.FormatBool(qrRemoteAgent)
if qRemoteAgent != "" {
if err := r.SetQueryParam("remoteAgent", qRemoteAgent); err != nil {
return err
}
}
}
if o.ShareCount != nil {
// query param shareCount
var qrShareCount string
if o.ShareCount != nil {
qrShareCount = *o.ShareCount
}
qShareCount := qrShareCount
if qShareCount != "" {
if err := r.SetQueryParam("shareCount", qShareCount); err != nil {
return err
}
}
}
if o.UpdatedAfter != nil {
// query param updatedAfter
var qrUpdatedAfter string
if o.UpdatedAfter != nil {
qrUpdatedAfter = *o.UpdatedAfter
}
qUpdatedAfter := qrUpdatedAfter
if qUpdatedAfter != "" {
if err := r.SetQueryParam("updatedAfter", qUpdatedAfter); err != nil {
return err
}
}
}
if o.UpdatedBefore != nil {
// query param updatedBefore
var qrUpdatedBefore string
if o.UpdatedBefore != nil {
qrUpdatedBefore = *o.UpdatedBefore
}
qUpdatedBefore := qrUpdatedBefore
if qUpdatedBefore != "" {
if err := r.SetQueryParam("updatedBefore", qUpdatedBefore); err != nil {
return err
}
}
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
@@ -0,0 +1,309 @@
// Code generated by go-swagger; DO NOT EDIT.
package metadata
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/openziti/zrok/rest_model_zrok"
)
// ListEnvironmentsReader is a Reader for the ListEnvironments structure.
type ListEnvironmentsReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *ListEnvironmentsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewListEnvironmentsOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 400:
result := NewListEnvironmentsBadRequest()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 401:
result := NewListEnvironmentsUnauthorized()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
case 500:
result := NewListEnvironmentsInternalServerError()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("[GET /environments] listEnvironments", response, response.Code())
}
}
// NewListEnvironmentsOK creates a ListEnvironmentsOK with default headers values
func NewListEnvironmentsOK() *ListEnvironmentsOK {
return &ListEnvironmentsOK{}
}
/*
ListEnvironmentsOK describes a response with status code 200, with default header values.
list of environments
*/
type ListEnvironmentsOK struct {
Payload *rest_model_zrok.EnvironmentsList
}
// IsSuccess returns true when this list environments o k response has a 2xx status code
func (o *ListEnvironmentsOK) IsSuccess() bool {
return true
}
// IsRedirect returns true when this list environments o k response has a 3xx status code
func (o *ListEnvironmentsOK) IsRedirect() bool {
return false
}
// IsClientError returns true when this list environments o k response has a 4xx status code
func (o *ListEnvironmentsOK) IsClientError() bool {
return false
}
// IsServerError returns true when this list environments o k response has a 5xx status code
func (o *ListEnvironmentsOK) IsServerError() bool {
return false
}
// IsCode returns true when this list environments o k response a status code equal to that given
func (o *ListEnvironmentsOK) IsCode(code int) bool {
return code == 200
}
// Code gets the status code for the list environments o k response
func (o *ListEnvironmentsOK) Code() int {
return 200
}
func (o *ListEnvironmentsOK) Error() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsOK %+v", 200, o.Payload)
}
func (o *ListEnvironmentsOK) String() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsOK %+v", 200, o.Payload)
}
func (o *ListEnvironmentsOK) GetPayload() *rest_model_zrok.EnvironmentsList {
return o.Payload
}
func (o *ListEnvironmentsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(rest_model_zrok.EnvironmentsList)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewListEnvironmentsBadRequest creates a ListEnvironmentsBadRequest with default headers values
func NewListEnvironmentsBadRequest() *ListEnvironmentsBadRequest {
return &ListEnvironmentsBadRequest{}
}
/*
ListEnvironmentsBadRequest describes a response with status code 400, with default header values.
bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator)
*/
type ListEnvironmentsBadRequest struct {
Payload rest_model_zrok.ErrorMessage
}
// IsSuccess returns true when this list environments bad request response has a 2xx status code
func (o *ListEnvironmentsBadRequest) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list environments bad request response has a 3xx status code
func (o *ListEnvironmentsBadRequest) IsRedirect() bool {
return false
}
// IsClientError returns true when this list environments bad request response has a 4xx status code
func (o *ListEnvironmentsBadRequest) IsClientError() bool {
return true
}
// IsServerError returns true when this list environments bad request response has a 5xx status code
func (o *ListEnvironmentsBadRequest) IsServerError() bool {
return false
}
// IsCode returns true when this list environments bad request response a status code equal to that given
func (o *ListEnvironmentsBadRequest) IsCode(code int) bool {
return code == 400
}
// Code gets the status code for the list environments bad request response
func (o *ListEnvironmentsBadRequest) Code() int {
return 400
}
func (o *ListEnvironmentsBadRequest) Error() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsBadRequest %+v", 400, o.Payload)
}
func (o *ListEnvironmentsBadRequest) String() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsBadRequest %+v", 400, o.Payload)
}
func (o *ListEnvironmentsBadRequest) GetPayload() rest_model_zrok.ErrorMessage {
return o.Payload
}
func (o *ListEnvironmentsBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewListEnvironmentsUnauthorized creates a ListEnvironmentsUnauthorized with default headers values
func NewListEnvironmentsUnauthorized() *ListEnvironmentsUnauthorized {
return &ListEnvironmentsUnauthorized{}
}
/*
ListEnvironmentsUnauthorized describes a response with status code 401, with default header values.
unauthorized
*/
type ListEnvironmentsUnauthorized struct {
}
// IsSuccess returns true when this list environments unauthorized response has a 2xx status code
func (o *ListEnvironmentsUnauthorized) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list environments unauthorized response has a 3xx status code
func (o *ListEnvironmentsUnauthorized) IsRedirect() bool {
return false
}
// IsClientError returns true when this list environments unauthorized response has a 4xx status code
func (o *ListEnvironmentsUnauthorized) IsClientError() bool {
return true
}
// IsServerError returns true when this list environments unauthorized response has a 5xx status code
func (o *ListEnvironmentsUnauthorized) IsServerError() bool {
return false
}
// IsCode returns true when this list environments unauthorized response a status code equal to that given
func (o *ListEnvironmentsUnauthorized) IsCode(code int) bool {
return code == 401
}
// Code gets the status code for the list environments unauthorized response
func (o *ListEnvironmentsUnauthorized) Code() int {
return 401
}
func (o *ListEnvironmentsUnauthorized) Error() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsUnauthorized ", 401)
}
func (o *ListEnvironmentsUnauthorized) String() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsUnauthorized ", 401)
}
func (o *ListEnvironmentsUnauthorized) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
return nil
}
// NewListEnvironmentsInternalServerError creates a ListEnvironmentsInternalServerError with default headers values
func NewListEnvironmentsInternalServerError() *ListEnvironmentsInternalServerError {
return &ListEnvironmentsInternalServerError{}
}
/*
ListEnvironmentsInternalServerError describes a response with status code 500, with default header values.
internal server error
*/
type ListEnvironmentsInternalServerError struct {
Payload rest_model_zrok.ErrorMessage
}
// IsSuccess returns true when this list environments internal server error response has a 2xx status code
func (o *ListEnvironmentsInternalServerError) IsSuccess() bool {
return false
}
// IsRedirect returns true when this list environments internal server error response has a 3xx status code
func (o *ListEnvironmentsInternalServerError) IsRedirect() bool {
return false
}
// IsClientError returns true when this list environments internal server error response has a 4xx status code
func (o *ListEnvironmentsInternalServerError) IsClientError() bool {
return false
}
// IsServerError returns true when this list environments internal server error response has a 5xx status code
func (o *ListEnvironmentsInternalServerError) IsServerError() bool {
return true
}
// IsCode returns true when this list environments internal server error response a status code equal to that given
func (o *ListEnvironmentsInternalServerError) IsCode(code int) bool {
return code == 500
}
// Code gets the status code for the list environments internal server error response
func (o *ListEnvironmentsInternalServerError) Code() int {
return 500
}
func (o *ListEnvironmentsInternalServerError) Error() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsInternalServerError %+v", 500, o.Payload)
}
func (o *ListEnvironmentsInternalServerError) String() string {
return fmt.Sprintf("[GET /environments][%d] listEnvironmentsInternalServerError %+v", 500, o.Payload)
}
func (o *ListEnvironmentsInternalServerError) GetPayload() rest_model_zrok.ErrorMessage {
return o.Payload
}
func (o *ListEnvironmentsInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
@@ -50,6 +50,8 @@ type ClientService interface {
GetSparklines(params *GetSparklinesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetSparklinesOK, error)
ListEnvironments(params *ListEnvironmentsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListEnvironmentsOK, error)
ListMemberships(params *ListMembershipsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListMembershipsOK, error)
ListOrgMembers(params *ListOrgMembersParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListOrgMembersOK, error)
@@ -453,6 +455,45 @@ func (a *Client) GetSparklines(params *GetSparklinesParams, authInfo runtime.Cli
panic(msg)
}
/*
ListEnvironments list environments API
*/
func (a *Client) ListEnvironments(params *ListEnvironmentsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListEnvironmentsOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewListEnvironmentsParams()
}
op := &runtime.ClientOperation{
ID: "listEnvironments",
Method: "GET",
PathPattern: "/environments",
ProducesMediaTypes: []string{"application/zrok.v1+json"},
ConsumesMediaTypes: []string{"application/zrok.v1+json"},
Schemes: []string{"http"},
Params: params,
Reader: &ListEnvironmentsReader{formats: a.formats},
AuthInfo: authInfo,
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*ListEnvironmentsOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for listEnvironments: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
ListMemberships list memberships API
*/
+80
View File
@@ -0,0 +1,80 @@
// Code generated by go-swagger; DO NOT EDIT.
package rest_model_zrok
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// EnvironmentSummary environment summary
//
// swagger:model environmentSummary
type EnvironmentSummary struct {
// access count
AccessCount int64 `json:"accessCount,omitempty"`
// address
Address string `json:"address,omitempty"`
// created at
CreatedAt int64 `json:"createdAt,omitempty"`
// description
Description string `json:"description,omitempty"`
// env z Id
EnvZID string `json:"envZId,omitempty"`
// has activity
HasActivity bool `json:"hasActivity,omitempty"`
// host
Host string `json:"host,omitempty"`
// limited
Limited bool `json:"limited,omitempty"`
// remote agent
RemoteAgent bool `json:"remoteAgent,omitempty"`
// share count
ShareCount int64 `json:"shareCount,omitempty"`
// updated at
UpdatedAt int64 `json:"updatedAt,omitempty"`
}
// Validate validates this environment summary
func (m *EnvironmentSummary) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this environment summary based on context it is used
func (m *EnvironmentSummary) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *EnvironmentSummary) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *EnvironmentSummary) UnmarshalBinary(b []byte) error {
var res EnvironmentSummary
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}
+121
View File
@@ -0,0 +1,121 @@
// Code generated by go-swagger; DO NOT EDIT.
package rest_model_zrok
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// EnvironmentsList environments list
//
// swagger:model environmentsList
type EnvironmentsList struct {
// environments
Environments []*EnvironmentSummary `json:"environments"`
}
// Validate validates this environments list
func (m *EnvironmentsList) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateEnvironments(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *EnvironmentsList) validateEnvironments(formats strfmt.Registry) error {
if swag.IsZero(m.Environments) { // not required
return nil
}
for i := 0; i < len(m.Environments); i++ {
if swag.IsZero(m.Environments[i]) { // not required
continue
}
if m.Environments[i] != nil {
if err := m.Environments[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("environments" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("environments" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// ContextValidate validate this environments list based on the context it is used
func (m *EnvironmentsList) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateEnvironments(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *EnvironmentsList) contextValidateEnvironments(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Environments); i++ {
if m.Environments[i] != nil {
if swag.IsZero(m.Environments[i]) { // not required
return nil
}
if err := m.Environments[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("environments" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("environments" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *EnvironmentsList) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *EnvironmentsList) UnmarshalBinary(b []byte) error {
var res EnvironmentsList
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}
+342
View File
@@ -1165,6 +1165,128 @@ func init() {
}
}
},
"/environments": {
"get": {
"security": [
{
"key": []
}
],
"tags": [
"metadata"
],
"operationId": "listEnvironments",
"parameters": [
{
"type": "string",
"description": "filter by description (case-insensitive substring match)",
"name": "description",
"in": "query"
},
{
"type": "string",
"description": "filter by host (case-insensitive substring match)",
"name": "host",
"in": "query"
},
{
"type": "string",
"description": "filter by address (exact match)",
"name": "address",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether agent is enrolled",
"name": "remoteAgent",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether environment has active shares",
"name": "hasShares",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether environment has active accesses",
"name": "hasAccesses",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether environment has metrics within activityDuration timeframe",
"name": "hasActivity",
"in": "query"
},
{
"type": "string",
"description": "filter by share count with operator (e.g., \"\u003e0\", \"\u003e=5\", \"=0\", \"\u003c10\", \"\u003c=3\")",
"name": "shareCount",
"in": "query"
},
{
"type": "string",
"description": "filter by access count with operator (e.g., \"\u003e0\", \"\u003e=5\", \"=0\", \"\u003c10\", \"\u003c=3\")",
"name": "accessCount",
"in": "query"
},
{
"type": "string",
"description": "filter by created date (RFC3339 datetime, inclusive)",
"name": "createdAfter",
"in": "query"
},
{
"type": "string",
"description": "filter by created date (RFC3339 datetime, inclusive)",
"name": "createdBefore",
"in": "query"
},
{
"type": "string",
"description": "filter by updated date (RFC3339 datetime, inclusive)",
"name": "updatedAfter",
"in": "query"
},
{
"type": "string",
"description": "filter by updated date (RFC3339 datetime, inclusive)",
"name": "updatedBefore",
"in": "query"
},
{
"type": "string",
"description": "duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)",
"name": "activityDuration",
"in": "query"
}
],
"responses": {
"200": {
"description": "list of environments",
"schema": {
"$ref": "#/definitions/environmentsList"
}
},
"400": {
"description": "bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator)",
"schema": {
"$ref": "#/definitions/errorMessage"
}
},
"401": {
"description": "unauthorized"
},
"500": {
"description": "internal server error",
"schema": {
"$ref": "#/definitions/errorMessage"
}
}
}
}
},
"/frontend": {
"post": {
"security": [
@@ -3568,12 +3690,61 @@ func init() {
}
}
},
"environmentSummary": {
"type": "object",
"properties": {
"accessCount": {
"type": "integer"
},
"address": {
"type": "string"
},
"createdAt": {
"type": "integer"
},
"description": {
"type": "string"
},
"envZId": {
"type": "string"
},
"hasActivity": {
"type": "boolean"
},
"host": {
"type": "string"
},
"limited": {
"type": "boolean"
},
"remoteAgent": {
"type": "boolean"
},
"shareCount": {
"type": "integer"
},
"updatedAt": {
"type": "integer"
}
}
},
"environments": {
"type": "array",
"items": {
"$ref": "#/definitions/environment"
}
},
"environmentsList": {
"type": "object",
"properties": {
"environments": {
"type": "array",
"items": {
"$ref": "#/definitions/environmentSummary"
}
}
}
},
"errorMessage": {
"type": "string"
},
@@ -4992,6 +5163,128 @@ func init() {
}
}
},
"/environments": {
"get": {
"security": [
{
"key": []
}
],
"tags": [
"metadata"
],
"operationId": "listEnvironments",
"parameters": [
{
"type": "string",
"description": "filter by description (case-insensitive substring match)",
"name": "description",
"in": "query"
},
{
"type": "string",
"description": "filter by host (case-insensitive substring match)",
"name": "host",
"in": "query"
},
{
"type": "string",
"description": "filter by address (exact match)",
"name": "address",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether agent is enrolled",
"name": "remoteAgent",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether environment has active shares",
"name": "hasShares",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether environment has active accesses",
"name": "hasAccesses",
"in": "query"
},
{
"type": "boolean",
"description": "filter by whether environment has metrics within activityDuration timeframe",
"name": "hasActivity",
"in": "query"
},
{
"type": "string",
"description": "filter by share count with operator (e.g., \"\u003e0\", \"\u003e=5\", \"=0\", \"\u003c10\", \"\u003c=3\")",
"name": "shareCount",
"in": "query"
},
{
"type": "string",
"description": "filter by access count with operator (e.g., \"\u003e0\", \"\u003e=5\", \"=0\", \"\u003c10\", \"\u003c=3\")",
"name": "accessCount",
"in": "query"
},
{
"type": "string",
"description": "filter by created date (RFC3339 datetime, inclusive)",
"name": "createdAfter",
"in": "query"
},
{
"type": "string",
"description": "filter by created date (RFC3339 datetime, inclusive)",
"name": "createdBefore",
"in": "query"
},
{
"type": "string",
"description": "filter by updated date (RFC3339 datetime, inclusive)",
"name": "updatedAfter",
"in": "query"
},
{
"type": "string",
"description": "filter by updated date (RFC3339 datetime, inclusive)",
"name": "updatedBefore",
"in": "query"
},
{
"type": "string",
"description": "duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)",
"name": "activityDuration",
"in": "query"
}
],
"responses": {
"200": {
"description": "list of environments",
"schema": {
"$ref": "#/definitions/environmentsList"
}
},
"400": {
"description": "bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator)",
"schema": {
"$ref": "#/definitions/errorMessage"
}
},
"401": {
"description": "unauthorized"
},
"500": {
"description": "internal server error",
"schema": {
"$ref": "#/definitions/errorMessage"
}
}
}
}
},
"/frontend": {
"post": {
"security": [
@@ -7569,12 +7862,61 @@ func init() {
}
}
},
"environmentSummary": {
"type": "object",
"properties": {
"accessCount": {
"type": "integer"
},
"address": {
"type": "string"
},
"createdAt": {
"type": "integer"
},
"description": {
"type": "string"
},
"envZId": {
"type": "string"
},
"hasActivity": {
"type": "boolean"
},
"host": {
"type": "string"
},
"limited": {
"type": "boolean"
},
"remoteAgent": {
"type": "boolean"
},
"shareCount": {
"type": "integer"
},
"updatedAt": {
"type": "integer"
}
}
},
"environments": {
"type": "array",
"items": {
"$ref": "#/definitions/environment"
}
},
"environmentsList": {
"type": "object",
"properties": {
"environments": {
"type": "array",
"items": {
"$ref": "#/definitions/environmentSummary"
}
}
}
},
"errorMessage": {
"type": "string"
},
@@ -0,0 +1,71 @@
// Code generated by go-swagger; DO NOT EDIT.
package metadata
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"net/http"
"github.com/go-openapi/runtime/middleware"
"github.com/openziti/zrok/rest_model_zrok"
)
// ListEnvironmentsHandlerFunc turns a function with the right signature into a list environments handler
type ListEnvironmentsHandlerFunc func(ListEnvironmentsParams, *rest_model_zrok.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn ListEnvironmentsHandlerFunc) Handle(params ListEnvironmentsParams, principal *rest_model_zrok.Principal) middleware.Responder {
return fn(params, principal)
}
// ListEnvironmentsHandler interface for that can handle valid list environments params
type ListEnvironmentsHandler interface {
Handle(ListEnvironmentsParams, *rest_model_zrok.Principal) middleware.Responder
}
// NewListEnvironments creates a new http.Handler for the list environments operation
func NewListEnvironments(ctx *middleware.Context, handler ListEnvironmentsHandler) *ListEnvironments {
return &ListEnvironments{Context: ctx, Handler: handler}
}
/*
ListEnvironments swagger:route GET /environments metadata listEnvironments
ListEnvironments list environments API
*/
type ListEnvironments struct {
Context *middleware.Context
Handler ListEnvironmentsHandler
}
func (o *ListEnvironments) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewListEnvironmentsParams()
uprinc, aCtx, err := o.Context.Authorize(r, route)
if err != nil {
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
if aCtx != nil {
*r = *aCtx
}
var principal *rest_model_zrok.Principal
if uprinc != nil {
principal = uprinc.(*rest_model_zrok.Principal) // this is really a rest_model_zrok.Principal, I promise
}
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params, principal) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}
@@ -0,0 +1,449 @@
// Code generated by go-swagger; DO NOT EDIT.
package metadata
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NewListEnvironmentsParams creates a new ListEnvironmentsParams object
//
// There are no default values defined in the spec.
func NewListEnvironmentsParams() ListEnvironmentsParams {
return ListEnvironmentsParams{}
}
// ListEnvironmentsParams contains all the bound params for the list environments operation
// typically these are obtained from a http.Request
//
// swagger:parameters listEnvironments
type ListEnvironmentsParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*filter by access count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
In: query
*/
AccessCount *string
/*duration for hasActivity filter (e.g., "24h", "7d", "30d"). default "24h", maximum "30d" (720h)
In: query
*/
ActivityDuration *string
/*filter by address (exact match)
In: query
*/
Address *string
/*filter by created date (RFC3339 datetime, inclusive)
In: query
*/
CreatedAfter *string
/*filter by created date (RFC3339 datetime, inclusive)
In: query
*/
CreatedBefore *string
/*filter by description (case-insensitive substring match)
In: query
*/
Description *string
/*filter by whether environment has active accesses
In: query
*/
HasAccesses *bool
/*filter by whether environment has metrics within activityDuration timeframe
In: query
*/
HasActivity *bool
/*filter by whether environment has active shares
In: query
*/
HasShares *bool
/*filter by host (case-insensitive substring match)
In: query
*/
Host *string
/*filter by whether agent is enrolled
In: query
*/
RemoteAgent *bool
/*filter by share count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
In: query
*/
ShareCount *string
/*filter by updated date (RFC3339 datetime, inclusive)
In: query
*/
UpdatedAfter *string
/*filter by updated date (RFC3339 datetime, inclusive)
In: query
*/
UpdatedBefore *string
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewListEnvironmentsParams() beforehand.
func (o *ListEnvironmentsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
qs := runtime.Values(r.URL.Query())
qAccessCount, qhkAccessCount, _ := qs.GetOK("accessCount")
if err := o.bindAccessCount(qAccessCount, qhkAccessCount, route.Formats); err != nil {
res = append(res, err)
}
qActivityDuration, qhkActivityDuration, _ := qs.GetOK("activityDuration")
if err := o.bindActivityDuration(qActivityDuration, qhkActivityDuration, route.Formats); err != nil {
res = append(res, err)
}
qAddress, qhkAddress, _ := qs.GetOK("address")
if err := o.bindAddress(qAddress, qhkAddress, route.Formats); err != nil {
res = append(res, err)
}
qCreatedAfter, qhkCreatedAfter, _ := qs.GetOK("createdAfter")
if err := o.bindCreatedAfter(qCreatedAfter, qhkCreatedAfter, route.Formats); err != nil {
res = append(res, err)
}
qCreatedBefore, qhkCreatedBefore, _ := qs.GetOK("createdBefore")
if err := o.bindCreatedBefore(qCreatedBefore, qhkCreatedBefore, route.Formats); err != nil {
res = append(res, err)
}
qDescription, qhkDescription, _ := qs.GetOK("description")
if err := o.bindDescription(qDescription, qhkDescription, route.Formats); err != nil {
res = append(res, err)
}
qHasAccesses, qhkHasAccesses, _ := qs.GetOK("hasAccesses")
if err := o.bindHasAccesses(qHasAccesses, qhkHasAccesses, route.Formats); err != nil {
res = append(res, err)
}
qHasActivity, qhkHasActivity, _ := qs.GetOK("hasActivity")
if err := o.bindHasActivity(qHasActivity, qhkHasActivity, route.Formats); err != nil {
res = append(res, err)
}
qHasShares, qhkHasShares, _ := qs.GetOK("hasShares")
if err := o.bindHasShares(qHasShares, qhkHasShares, route.Formats); err != nil {
res = append(res, err)
}
qHost, qhkHost, _ := qs.GetOK("host")
if err := o.bindHost(qHost, qhkHost, route.Formats); err != nil {
res = append(res, err)
}
qRemoteAgent, qhkRemoteAgent, _ := qs.GetOK("remoteAgent")
if err := o.bindRemoteAgent(qRemoteAgent, qhkRemoteAgent, route.Formats); err != nil {
res = append(res, err)
}
qShareCount, qhkShareCount, _ := qs.GetOK("shareCount")
if err := o.bindShareCount(qShareCount, qhkShareCount, route.Formats); err != nil {
res = append(res, err)
}
qUpdatedAfter, qhkUpdatedAfter, _ := qs.GetOK("updatedAfter")
if err := o.bindUpdatedAfter(qUpdatedAfter, qhkUpdatedAfter, route.Formats); err != nil {
res = append(res, err)
}
qUpdatedBefore, qhkUpdatedBefore, _ := qs.GetOK("updatedBefore")
if err := o.bindUpdatedBefore(qUpdatedBefore, qhkUpdatedBefore, route.Formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// bindAccessCount binds and validates parameter AccessCount from query.
func (o *ListEnvironmentsParams) bindAccessCount(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.AccessCount = &raw
return nil
}
// bindActivityDuration binds and validates parameter ActivityDuration from query.
func (o *ListEnvironmentsParams) bindActivityDuration(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.ActivityDuration = &raw
return nil
}
// bindAddress binds and validates parameter Address from query.
func (o *ListEnvironmentsParams) bindAddress(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.Address = &raw
return nil
}
// bindCreatedAfter binds and validates parameter CreatedAfter from query.
func (o *ListEnvironmentsParams) bindCreatedAfter(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.CreatedAfter = &raw
return nil
}
// bindCreatedBefore binds and validates parameter CreatedBefore from query.
func (o *ListEnvironmentsParams) bindCreatedBefore(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.CreatedBefore = &raw
return nil
}
// bindDescription binds and validates parameter Description from query.
func (o *ListEnvironmentsParams) bindDescription(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.Description = &raw
return nil
}
// bindHasAccesses binds and validates parameter HasAccesses from query.
func (o *ListEnvironmentsParams) bindHasAccesses(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
value, err := swag.ConvertBool(raw)
if err != nil {
return errors.InvalidType("hasAccesses", "query", "bool", raw)
}
o.HasAccesses = &value
return nil
}
// bindHasActivity binds and validates parameter HasActivity from query.
func (o *ListEnvironmentsParams) bindHasActivity(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
value, err := swag.ConvertBool(raw)
if err != nil {
return errors.InvalidType("hasActivity", "query", "bool", raw)
}
o.HasActivity = &value
return nil
}
// bindHasShares binds and validates parameter HasShares from query.
func (o *ListEnvironmentsParams) bindHasShares(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
value, err := swag.ConvertBool(raw)
if err != nil {
return errors.InvalidType("hasShares", "query", "bool", raw)
}
o.HasShares = &value
return nil
}
// bindHost binds and validates parameter Host from query.
func (o *ListEnvironmentsParams) bindHost(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.Host = &raw
return nil
}
// bindRemoteAgent binds and validates parameter RemoteAgent from query.
func (o *ListEnvironmentsParams) bindRemoteAgent(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
value, err := swag.ConvertBool(raw)
if err != nil {
return errors.InvalidType("remoteAgent", "query", "bool", raw)
}
o.RemoteAgent = &value
return nil
}
// bindShareCount binds and validates parameter ShareCount from query.
func (o *ListEnvironmentsParams) bindShareCount(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.ShareCount = &raw
return nil
}
// bindUpdatedAfter binds and validates parameter UpdatedAfter from query.
func (o *ListEnvironmentsParams) bindUpdatedAfter(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.UpdatedAfter = &raw
return nil
}
// bindUpdatedBefore binds and validates parameter UpdatedBefore from query.
func (o *ListEnvironmentsParams) bindUpdatedBefore(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
return nil
}
o.UpdatedBefore = &raw
return nil
}
@@ -0,0 +1,170 @@
// Code generated by go-swagger; DO NOT EDIT.
package metadata
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/openziti/zrok/rest_model_zrok"
)
// ListEnvironmentsOKCode is the HTTP code returned for type ListEnvironmentsOK
const ListEnvironmentsOKCode int = 200
/*
ListEnvironmentsOK list of environments
swagger:response listEnvironmentsOK
*/
type ListEnvironmentsOK struct {
/*
In: Body
*/
Payload *rest_model_zrok.EnvironmentsList `json:"body,omitempty"`
}
// NewListEnvironmentsOK creates ListEnvironmentsOK with default headers values
func NewListEnvironmentsOK() *ListEnvironmentsOK {
return &ListEnvironmentsOK{}
}
// WithPayload adds the payload to the list environments o k response
func (o *ListEnvironmentsOK) WithPayload(payload *rest_model_zrok.EnvironmentsList) *ListEnvironmentsOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list environments o k response
func (o *ListEnvironmentsOK) SetPayload(payload *rest_model_zrok.EnvironmentsList) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListEnvironmentsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(200)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}
// ListEnvironmentsBadRequestCode is the HTTP code returned for type ListEnvironmentsBadRequest
const ListEnvironmentsBadRequestCode int = 400
/*
ListEnvironmentsBadRequest bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator)
swagger:response listEnvironmentsBadRequest
*/
type ListEnvironmentsBadRequest struct {
/*
In: Body
*/
Payload rest_model_zrok.ErrorMessage `json:"body,omitempty"`
}
// NewListEnvironmentsBadRequest creates ListEnvironmentsBadRequest with default headers values
func NewListEnvironmentsBadRequest() *ListEnvironmentsBadRequest {
return &ListEnvironmentsBadRequest{}
}
// WithPayload adds the payload to the list environments bad request response
func (o *ListEnvironmentsBadRequest) WithPayload(payload rest_model_zrok.ErrorMessage) *ListEnvironmentsBadRequest {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list environments bad request response
func (o *ListEnvironmentsBadRequest) SetPayload(payload rest_model_zrok.ErrorMessage) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListEnvironmentsBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(400)
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
// ListEnvironmentsUnauthorizedCode is the HTTP code returned for type ListEnvironmentsUnauthorized
const ListEnvironmentsUnauthorizedCode int = 401
/*
ListEnvironmentsUnauthorized unauthorized
swagger:response listEnvironmentsUnauthorized
*/
type ListEnvironmentsUnauthorized struct {
}
// NewListEnvironmentsUnauthorized creates ListEnvironmentsUnauthorized with default headers values
func NewListEnvironmentsUnauthorized() *ListEnvironmentsUnauthorized {
return &ListEnvironmentsUnauthorized{}
}
// WriteResponse to the client
func (o *ListEnvironmentsUnauthorized) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
rw.WriteHeader(401)
}
// ListEnvironmentsInternalServerErrorCode is the HTTP code returned for type ListEnvironmentsInternalServerError
const ListEnvironmentsInternalServerErrorCode int = 500
/*
ListEnvironmentsInternalServerError internal server error
swagger:response listEnvironmentsInternalServerError
*/
type ListEnvironmentsInternalServerError struct {
/*
In: Body
*/
Payload rest_model_zrok.ErrorMessage `json:"body,omitempty"`
}
// NewListEnvironmentsInternalServerError creates ListEnvironmentsInternalServerError with default headers values
func NewListEnvironmentsInternalServerError() *ListEnvironmentsInternalServerError {
return &ListEnvironmentsInternalServerError{}
}
// WithPayload adds the payload to the list environments internal server error response
func (o *ListEnvironmentsInternalServerError) WithPayload(payload rest_model_zrok.ErrorMessage) *ListEnvironmentsInternalServerError {
o.Payload = payload
return o
}
// SetPayload sets the payload to the list environments internal server error response
func (o *ListEnvironmentsInternalServerError) SetPayload(payload rest_model_zrok.ErrorMessage) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ListEnvironmentsInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(500)
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
@@ -0,0 +1,222 @@
// Code generated by go-swagger; DO NOT EDIT.
package metadata
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"errors"
"net/url"
golangswaggerpaths "path"
"github.com/go-openapi/swag"
)
// ListEnvironmentsURL generates an URL for the list environments operation
type ListEnvironmentsURL struct {
AccessCount *string
ActivityDuration *string
Address *string
CreatedAfter *string
CreatedBefore *string
Description *string
HasAccesses *bool
HasActivity *bool
HasShares *bool
Host *string
RemoteAgent *bool
ShareCount *string
UpdatedAfter *string
UpdatedBefore *string
_basePath string
// avoid unkeyed usage
_ struct{}
}
// WithBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *ListEnvironmentsURL) WithBasePath(bp string) *ListEnvironmentsURL {
o.SetBasePath(bp)
return o
}
// SetBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *ListEnvironmentsURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *ListEnvironmentsURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/environments"
_basePath := o._basePath
if _basePath == "" {
_basePath = "/api/v2"
}
_result.Path = golangswaggerpaths.Join(_basePath, _path)
qs := make(url.Values)
var accessCountQ string
if o.AccessCount != nil {
accessCountQ = *o.AccessCount
}
if accessCountQ != "" {
qs.Set("accessCount", accessCountQ)
}
var activityDurationQ string
if o.ActivityDuration != nil {
activityDurationQ = *o.ActivityDuration
}
if activityDurationQ != "" {
qs.Set("activityDuration", activityDurationQ)
}
var addressQ string
if o.Address != nil {
addressQ = *o.Address
}
if addressQ != "" {
qs.Set("address", addressQ)
}
var createdAfterQ string
if o.CreatedAfter != nil {
createdAfterQ = *o.CreatedAfter
}
if createdAfterQ != "" {
qs.Set("createdAfter", createdAfterQ)
}
var createdBeforeQ string
if o.CreatedBefore != nil {
createdBeforeQ = *o.CreatedBefore
}
if createdBeforeQ != "" {
qs.Set("createdBefore", createdBeforeQ)
}
var descriptionQ string
if o.Description != nil {
descriptionQ = *o.Description
}
if descriptionQ != "" {
qs.Set("description", descriptionQ)
}
var hasAccessesQ string
if o.HasAccesses != nil {
hasAccessesQ = swag.FormatBool(*o.HasAccesses)
}
if hasAccessesQ != "" {
qs.Set("hasAccesses", hasAccessesQ)
}
var hasActivityQ string
if o.HasActivity != nil {
hasActivityQ = swag.FormatBool(*o.HasActivity)
}
if hasActivityQ != "" {
qs.Set("hasActivity", hasActivityQ)
}
var hasSharesQ string
if o.HasShares != nil {
hasSharesQ = swag.FormatBool(*o.HasShares)
}
if hasSharesQ != "" {
qs.Set("hasShares", hasSharesQ)
}
var hostQ string
if o.Host != nil {
hostQ = *o.Host
}
if hostQ != "" {
qs.Set("host", hostQ)
}
var remoteAgentQ string
if o.RemoteAgent != nil {
remoteAgentQ = swag.FormatBool(*o.RemoteAgent)
}
if remoteAgentQ != "" {
qs.Set("remoteAgent", remoteAgentQ)
}
var shareCountQ string
if o.ShareCount != nil {
shareCountQ = *o.ShareCount
}
if shareCountQ != "" {
qs.Set("shareCount", shareCountQ)
}
var updatedAfterQ string
if o.UpdatedAfter != nil {
updatedAfterQ = *o.UpdatedAfter
}
if updatedAfterQ != "" {
qs.Set("updatedAfter", updatedAfterQ)
}
var updatedBeforeQ string
if o.UpdatedBefore != nil {
updatedBeforeQ = *o.UpdatedBefore
}
if updatedBeforeQ != "" {
qs.Set("updatedBefore", updatedBeforeQ)
}
_result.RawQuery = qs.Encode()
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error
func (o *ListEnvironmentsURL) Must(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
if u == nil {
panic("url can't be nil")
}
return u
}
// String returns the string representation of the path with query string
func (o *ListEnvironmentsURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *ListEnvironmentsURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on ListEnvironmentsURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on ListEnvironmentsURL")
}
base, err := o.Build()
if err != nil {
return nil, err
}
base.Scheme = scheme
base.Host = host
return base, nil
}
// StringFull returns the string representation of a complete url
func (o *ListEnvironmentsURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}
+12
View File
@@ -158,6 +158,9 @@ func NewZrokAPI(spec *loads.Document) *ZrokAPI {
ShareListAllNamesHandler: share.ListAllNamesHandlerFunc(func(params share.ListAllNamesParams, principal *rest_model_zrok.Principal) middleware.Responder {
return middleware.NotImplemented("operation share.ListAllNames has not yet been implemented")
}),
MetadataListEnvironmentsHandler: metadata.ListEnvironmentsHandlerFunc(func(params metadata.ListEnvironmentsParams, principal *rest_model_zrok.Principal) middleware.Responder {
return middleware.NotImplemented("operation metadata.ListEnvironments has not yet been implemented")
}),
AdminListFrontendNamespaceMappingsHandler: admin.ListFrontendNamespaceMappingsHandlerFunc(func(params admin.ListFrontendNamespaceMappingsParams, principal *rest_model_zrok.Principal) middleware.Responder {
return middleware.NotImplemented("operation admin.ListFrontendNamespaceMappings has not yet been implemented")
}),
@@ -397,6 +400,8 @@ type ZrokAPI struct {
AdminInviteTokenGenerateHandler admin.InviteTokenGenerateHandler
// ShareListAllNamesHandler sets the operation handler for the list all names operation
ShareListAllNamesHandler share.ListAllNamesHandler
// MetadataListEnvironmentsHandler sets the operation handler for the list environments operation
MetadataListEnvironmentsHandler metadata.ListEnvironmentsHandler
// AdminListFrontendNamespaceMappingsHandler sets the operation handler for the list frontend namespace mappings operation
AdminListFrontendNamespaceMappingsHandler admin.ListFrontendNamespaceMappingsHandler
// AdminListFrontendsHandler sets the operation handler for the list frontends operation
@@ -664,6 +669,9 @@ func (o *ZrokAPI) Validate() error {
if o.ShareListAllNamesHandler == nil {
unregistered = append(unregistered, "share.ListAllNamesHandler")
}
if o.MetadataListEnvironmentsHandler == nil {
unregistered = append(unregistered, "metadata.ListEnvironmentsHandler")
}
if o.AdminListFrontendNamespaceMappingsHandler == nil {
unregistered = append(unregistered, "admin.ListFrontendNamespaceMappingsHandler")
}
@@ -1027,6 +1035,10 @@ func (o *ZrokAPI) initHandlerCache() {
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/environments"] = metadata.NewListEnvironments(o.context, o.MetadataListEnvironmentsHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/frontend/namespace/mapping/{frontendToken}"] = admin.NewListFrontendNamespaceMappings(o.context, o.AdminListFrontendNamespaceMappingsHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
@@ -32,6 +32,8 @@ models/Enroll200Response.ts
models/EnrollRequest.ts
models/Environment.ts
models/EnvironmentAndResources.ts
models/EnvironmentSummary.ts
models/EnvironmentsList.ts
models/Frontend.ts
models/GetSparklines200Response.ts
models/GetSparklinesRequest.ts
+107
View File
@@ -18,6 +18,7 @@ import type {
ClientVersionCheckRequest,
Environment,
EnvironmentAndResources,
EnvironmentsList,
Frontend,
GetSparklines200Response,
GetSparklinesRequest,
@@ -36,6 +37,8 @@ import {
EnvironmentToJSON,
EnvironmentAndResourcesFromJSON,
EnvironmentAndResourcesToJSON,
EnvironmentsListFromJSON,
EnvironmentsListToJSON,
FrontendFromJSON,
FrontendToJSON,
GetSparklines200ResponseFromJSON,
@@ -92,6 +95,23 @@ export interface GetSparklinesOperationRequest {
body?: GetSparklinesRequest;
}
export interface ListEnvironmentsRequest {
description?: string;
host?: string;
address?: string;
remoteAgent?: boolean;
hasShares?: boolean;
hasAccesses?: boolean;
hasActivity?: boolean;
shareCount?: string;
accessCount?: string;
createdAfter?: string;
createdBefore?: string;
updatedAfter?: string;
updatedBefore?: string;
activityDuration?: string;
}
export interface ListOrgMembersRequest {
organizationToken: string;
}
@@ -465,6 +485,93 @@ export class MetadataApi extends runtime.BaseAPI {
return await response.value();
}
/**
*/
async listEnvironmentsRaw(requestParameters: ListEnvironmentsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<EnvironmentsList>> {
const queryParameters: any = {};
if (requestParameters['description'] != null) {
queryParameters['description'] = requestParameters['description'];
}
if (requestParameters['host'] != null) {
queryParameters['host'] = requestParameters['host'];
}
if (requestParameters['address'] != null) {
queryParameters['address'] = requestParameters['address'];
}
if (requestParameters['remoteAgent'] != null) {
queryParameters['remoteAgent'] = requestParameters['remoteAgent'];
}
if (requestParameters['hasShares'] != null) {
queryParameters['hasShares'] = requestParameters['hasShares'];
}
if (requestParameters['hasAccesses'] != null) {
queryParameters['hasAccesses'] = requestParameters['hasAccesses'];
}
if (requestParameters['hasActivity'] != null) {
queryParameters['hasActivity'] = requestParameters['hasActivity'];
}
if (requestParameters['shareCount'] != null) {
queryParameters['shareCount'] = requestParameters['shareCount'];
}
if (requestParameters['accessCount'] != null) {
queryParameters['accessCount'] = requestParameters['accessCount'];
}
if (requestParameters['createdAfter'] != null) {
queryParameters['createdAfter'] = requestParameters['createdAfter'];
}
if (requestParameters['createdBefore'] != null) {
queryParameters['createdBefore'] = requestParameters['createdBefore'];
}
if (requestParameters['updatedAfter'] != null) {
queryParameters['updatedAfter'] = requestParameters['updatedAfter'];
}
if (requestParameters['updatedBefore'] != null) {
queryParameters['updatedBefore'] = requestParameters['updatedBefore'];
}
if (requestParameters['activityDuration'] != null) {
queryParameters['activityDuration'] = requestParameters['activityDuration'];
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.apiKey) {
headerParameters["x-token"] = await this.configuration.apiKey("x-token"); // key authentication
}
let urlPath = `/environments`;
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => EnvironmentsListFromJSON(jsonValue));
}
/**
*/
async listEnvironments(requestParameters: ListEnvironmentsRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<EnvironmentsList> {
const response = await this.listEnvironmentsRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async listMembershipsRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ListMemberships200Response>> {
@@ -0,0 +1,145 @@
/* tslint:disable */
/* eslint-disable */
/**
* zrok
* zrok client access
*
* The version of the OpenAPI document: 2.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface EnvironmentSummary
*/
export interface EnvironmentSummary {
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
envZId?: string;
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
description?: string;
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
host?: string;
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
address?: string;
/**
*
* @type {boolean}
* @memberof EnvironmentSummary
*/
remoteAgent?: boolean;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
shareCount?: number;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
accessCount?: number;
/**
*
* @type {boolean}
* @memberof EnvironmentSummary
*/
hasActivity?: boolean;
/**
*
* @type {boolean}
* @memberof EnvironmentSummary
*/
limited?: boolean;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
createdAt?: number;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
updatedAt?: number;
}
/**
* Check if a given object implements the EnvironmentSummary interface.
*/
export function instanceOfEnvironmentSummary(value: object): value is EnvironmentSummary {
return true;
}
export function EnvironmentSummaryFromJSON(json: any): EnvironmentSummary {
return EnvironmentSummaryFromJSONTyped(json, false);
}
export function EnvironmentSummaryFromJSONTyped(json: any, ignoreDiscriminator: boolean): EnvironmentSummary {
if (json == null) {
return json;
}
return {
'envZId': json['envZId'] == null ? undefined : json['envZId'],
'description': json['description'] == null ? undefined : json['description'],
'host': json['host'] == null ? undefined : json['host'],
'address': json['address'] == null ? undefined : json['address'],
'remoteAgent': json['remoteAgent'] == null ? undefined : json['remoteAgent'],
'shareCount': json['shareCount'] == null ? undefined : json['shareCount'],
'accessCount': json['accessCount'] == null ? undefined : json['accessCount'],
'hasActivity': json['hasActivity'] == null ? undefined : json['hasActivity'],
'limited': json['limited'] == null ? undefined : json['limited'],
'createdAt': json['createdAt'] == null ? undefined : json['createdAt'],
'updatedAt': json['updatedAt'] == null ? undefined : json['updatedAt'],
};
}
export function EnvironmentSummaryToJSON(json: any): EnvironmentSummary {
return EnvironmentSummaryToJSONTyped(json, false);
}
export function EnvironmentSummaryToJSONTyped(value?: EnvironmentSummary | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'envZId': value['envZId'],
'description': value['description'],
'host': value['host'],
'address': value['address'],
'remoteAgent': value['remoteAgent'],
'shareCount': value['shareCount'],
'accessCount': value['accessCount'],
'hasActivity': value['hasActivity'],
'limited': value['limited'],
'createdAt': value['createdAt'],
'updatedAt': value['updatedAt'],
};
}
@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* zrok
* zrok client access
*
* The version of the OpenAPI document: 2.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { EnvironmentSummary } from './EnvironmentSummary';
import {
EnvironmentSummaryFromJSON,
EnvironmentSummaryFromJSONTyped,
EnvironmentSummaryToJSON,
EnvironmentSummaryToJSONTyped,
} from './EnvironmentSummary';
/**
*
* @export
* @interface EnvironmentsList
*/
export interface EnvironmentsList {
/**
*
* @type {Array<EnvironmentSummary>}
* @memberof EnvironmentsList
*/
environments?: Array<EnvironmentSummary>;
}
/**
* Check if a given object implements the EnvironmentsList interface.
*/
export function instanceOfEnvironmentsList(value: object): value is EnvironmentsList {
return true;
}
export function EnvironmentsListFromJSON(json: any): EnvironmentsList {
return EnvironmentsListFromJSONTyped(json, false);
}
export function EnvironmentsListFromJSONTyped(json: any, ignoreDiscriminator: boolean): EnvironmentsList {
if (json == null) {
return json;
}
return {
'environments': json['environments'] == null ? undefined : ((json['environments'] as Array<any>).map(EnvironmentSummaryFromJSON)),
};
}
export function EnvironmentsListToJSON(json: any): EnvironmentsList {
return EnvironmentsListToJSONTyped(json, false);
}
export function EnvironmentsListToJSONTyped(value?: EnvironmentsList | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'environments': value['environments'] == null ? undefined : ((value['environments'] as Array<any>).map(EnvironmentSummaryToJSON)),
};
}
+2
View File
@@ -25,6 +25,8 @@ export * from './Enroll200Response';
export * from './EnrollRequest';
export * from './Environment';
export * from './EnvironmentAndResources';
export * from './EnvironmentSummary';
export * from './EnvironmentsList';
export * from './Frontend';
export * from './GetSparklines200Response';
export * from './GetSparklinesRequest';
+6
View File
@@ -30,6 +30,8 @@ docs/EnrollRequest.md
docs/Environment.md
docs/EnvironmentAndResources.md
docs/EnvironmentApi.md
docs/EnvironmentSummary.md
docs/EnvironmentsList.md
docs/Frontend.md
docs/GetSparklines200Response.md
docs/GetSparklinesRequest.md
@@ -120,6 +122,8 @@ test/test_enroll_request.py
test/test_environment.py
test/test_environment_and_resources.py
test/test_environment_api.py
test/test_environment_summary.py
test/test_environments_list.py
test/test_frontend.py
test/test_get_sparklines200_response.py
test/test_get_sparklines_request.py
@@ -216,6 +220,8 @@ zrok_api/models/enroll200_response.py
zrok_api/models/enroll_request.py
zrok_api/models/environment.py
zrok_api/models/environment_and_resources.py
zrok_api/models/environment_summary.py
zrok_api/models/environments_list.py
zrok_api/models/frontend.py
zrok_api/models/get_sparklines200_response.py
zrok_api/models/get_sparklines_request.py
+3
View File
@@ -149,6 +149,7 @@ Class | Method | HTTP request | Description
*MetadataApi* | [**get_share_detail**](docs/MetadataApi.md#get_share_detail) | **GET** /detail/share/{shareToken} |
*MetadataApi* | [**get_share_metrics**](docs/MetadataApi.md#get_share_metrics) | **GET** /metrics/share/{shareToken} |
*MetadataApi* | [**get_sparklines**](docs/MetadataApi.md#get_sparklines) | **POST** /sparklines |
*MetadataApi* | [**list_environments**](docs/MetadataApi.md#list_environments) | **GET** /environments |
*MetadataApi* | [**list_memberships**](docs/MetadataApi.md#list_memberships) | **GET** /memberships |
*MetadataApi* | [**list_org_members**](docs/MetadataApi.md#list_org_members) | **GET** /members/{organizationToken} |
*MetadataApi* | [**org_account_overview**](docs/MetadataApi.md#org_account_overview) | **GET** /overview/{organizationToken}/{accountEmail} |
@@ -197,6 +198,8 @@ Class | Method | HTTP request | Description
- [EnrollRequest](docs/EnrollRequest.md)
- [Environment](docs/Environment.md)
- [EnvironmentAndResources](docs/EnvironmentAndResources.md)
- [EnvironmentSummary](docs/EnvironmentSummary.md)
- [EnvironmentsList](docs/EnvironmentsList.md)
- [Frontend](docs/Frontend.md)
- [GetSparklines200Response](docs/GetSparklines200Response.md)
- [GetSparklinesRequest](docs/GetSparklinesRequest.md)
+39
View File
@@ -0,0 +1,39 @@
# EnvironmentSummary
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**env_zid** | **str** | | [optional]
**description** | **str** | | [optional]
**host** | **str** | | [optional]
**address** | **str** | | [optional]
**remote_agent** | **bool** | | [optional]
**share_count** | **int** | | [optional]
**access_count** | **int** | | [optional]
**has_activity** | **bool** | | [optional]
**limited** | **bool** | | [optional]
**created_at** | **int** | | [optional]
**updated_at** | **int** | | [optional]
## Example
```python
from zrok_api.models.environment_summary import EnvironmentSummary
# TODO update the JSON string below
json = "{}"
# create an instance of EnvironmentSummary from a JSON string
environment_summary_instance = EnvironmentSummary.from_json(json)
# print the JSON string representation of the object
print(EnvironmentSummary.to_json())
# convert the object into a dict
environment_summary_dict = environment_summary_instance.to_dict()
# create an instance of EnvironmentSummary from a dict
environment_summary_from_dict = EnvironmentSummary.from_dict(environment_summary_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+29
View File
@@ -0,0 +1,29 @@
# EnvironmentsList
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**environments** | [**List[EnvironmentSummary]**](EnvironmentSummary.md) | | [optional]
## Example
```python
from zrok_api.models.environments_list import EnvironmentsList
# TODO update the JSON string below
json = "{}"
# create an instance of EnvironmentsList from a JSON string
environments_list_instance = EnvironmentsList.from_json(json)
# print the JSON string representation of the object
print(EnvironmentsList.to_json())
# convert the object into a dict
environments_list_dict = environments_list_instance.to_dict()
# create an instance of EnvironmentsList from a dict
environments_list_from_dict = EnvironmentsList.from_dict(environments_list_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+104
View File
@@ -14,6 +14,7 @@ Method | HTTP request | Description
[**get_share_detail**](MetadataApi.md#get_share_detail) | **GET** /detail/share/{shareToken} |
[**get_share_metrics**](MetadataApi.md#get_share_metrics) | **GET** /metrics/share/{shareToken} |
[**get_sparklines**](MetadataApi.md#get_sparklines) | **POST** /sparklines |
[**list_environments**](MetadataApi.md#list_environments) | **GET** /environments |
[**list_memberships**](MetadataApi.md#list_memberships) | **GET** /memberships |
[**list_org_members**](MetadataApi.md#list_org_members) | **GET** /members/{organizationToken} |
[**org_account_overview**](MetadataApi.md#org_account_overview) | **GET** /overview/{organizationToken}/{accountEmail} |
@@ -756,6 +757,109 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **list_environments**
> EnvironmentsList list_environments(description=description, host=host, address=address, remote_agent=remote_agent, has_shares=has_shares, has_accesses=has_accesses, has_activity=has_activity, share_count=share_count, access_count=access_count, created_after=created_after, created_before=created_before, updated_after=updated_after, updated_before=updated_before, activity_duration=activity_duration)
### Example
* Api Key Authentication (key):
```python
import zrok_api
from zrok_api.models.environments_list import EnvironmentsList
from zrok_api.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to /api/v2
# See configuration.py for a list of all supported configuration parameters.
configuration = zrok_api.Configuration(
host = "/api/v2"
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure API key authorization: key
configuration.api_key['key'] = os.environ["API_KEY"]
# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
# configuration.api_key_prefix['key'] = 'Bearer'
# Enter a context with an instance of the API client
with zrok_api.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = zrok_api.MetadataApi(api_client)
description = 'description_example' # str | filter by description (case-insensitive substring match) (optional)
host = 'host_example' # str | filter by host (case-insensitive substring match) (optional)
address = 'address_example' # str | filter by address (exact match) (optional)
remote_agent = True # bool | filter by whether agent is enrolled (optional)
has_shares = True # bool | filter by whether environment has active shares (optional)
has_accesses = True # bool | filter by whether environment has active accesses (optional)
has_activity = True # bool | filter by whether environment has metrics within activityDuration timeframe (optional)
share_count = 'share_count_example' # str | filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\") (optional)
access_count = 'access_count_example' # str | filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\") (optional)
created_after = 'created_after_example' # str | filter by created date (RFC3339 datetime, inclusive) (optional)
created_before = 'created_before_example' # str | filter by created date (RFC3339 datetime, inclusive) (optional)
updated_after = 'updated_after_example' # str | filter by updated date (RFC3339 datetime, inclusive) (optional)
updated_before = 'updated_before_example' # str | filter by updated date (RFC3339 datetime, inclusive) (optional)
activity_duration = 'activity_duration_example' # str | duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h) (optional)
try:
api_response = api_instance.list_environments(description=description, host=host, address=address, remote_agent=remote_agent, has_shares=has_shares, has_accesses=has_accesses, has_activity=has_activity, share_count=share_count, access_count=access_count, created_after=created_after, created_before=created_before, updated_after=updated_after, updated_before=updated_before, activity_duration=activity_duration)
print("The response of MetadataApi->list_environments:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling MetadataApi->list_environments: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**description** | **str**| filter by description (case-insensitive substring match) | [optional]
**host** | **str**| filter by host (case-insensitive substring match) | [optional]
**address** | **str**| filter by address (exact match) | [optional]
**remote_agent** | **bool**| filter by whether agent is enrolled | [optional]
**has_shares** | **bool**| filter by whether environment has active shares | [optional]
**has_accesses** | **bool**| filter by whether environment has active accesses | [optional]
**has_activity** | **bool**| filter by whether environment has metrics within activityDuration timeframe | [optional]
**share_count** | **str**| filter by share count with operator (e.g., \&quot;&gt;0\&quot;, \&quot;&gt;&#x3D;5\&quot;, \&quot;&#x3D;0\&quot;, \&quot;&lt;10\&quot;, \&quot;&lt;&#x3D;3\&quot;) | [optional]
**access_count** | **str**| filter by access count with operator (e.g., \&quot;&gt;0\&quot;, \&quot;&gt;&#x3D;5\&quot;, \&quot;&#x3D;0\&quot;, \&quot;&lt;10\&quot;, \&quot;&lt;&#x3D;3\&quot;) | [optional]
**created_after** | **str**| filter by created date (RFC3339 datetime, inclusive) | [optional]
**created_before** | **str**| filter by created date (RFC3339 datetime, inclusive) | [optional]
**updated_after** | **str**| filter by updated date (RFC3339 datetime, inclusive) | [optional]
**updated_before** | **str**| filter by updated date (RFC3339 datetime, inclusive) | [optional]
**activity_duration** | **str**| duration for hasActivity filter (e.g., \&quot;24h\&quot;, \&quot;7d\&quot;, \&quot;30d\&quot;). default \&quot;24h\&quot;, maximum \&quot;30d\&quot; (720h) | [optional]
### Return type
[**EnvironmentsList**](EnvironmentsList.md)
### Authorization
[key](../README.md#key)
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/zrok.v1+json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | list of environments | - |
**400** | bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator) | - |
**401** | unauthorized | - |
**500** | internal server error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **list_memberships**
> ListMemberships200Response list_memberships()
@@ -0,0 +1,61 @@
# coding: utf-8
"""
zrok
zrok client access
The version of the OpenAPI document: 2.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from zrok_api.models.environment_summary import EnvironmentSummary
class TestEnvironmentSummary(unittest.TestCase):
"""EnvironmentSummary unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> EnvironmentSummary:
"""Test EnvironmentSummary
include_optional is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `EnvironmentSummary`
"""
model = EnvironmentSummary()
if include_optional:
return EnvironmentSummary(
env_zid = '',
description = '',
host = '',
address = '',
remote_agent = True,
share_count = 56,
access_count = 56,
has_activity = True,
limited = True,
created_at = 56,
updated_at = 56
)
else:
return EnvironmentSummary(
)
"""
def testEnvironmentSummary(self):
"""Test EnvironmentSummary"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,64 @@
# coding: utf-8
"""
zrok
zrok client access
The version of the OpenAPI document: 2.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from zrok_api.models.environments_list import EnvironmentsList
class TestEnvironmentsList(unittest.TestCase):
"""EnvironmentsList unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> EnvironmentsList:
"""Test EnvironmentsList
include_optional is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `EnvironmentsList`
"""
model = EnvironmentsList()
if include_optional:
return EnvironmentsList(
environments = [
zrok_api.models.environment_summary.environmentSummary(
env_zid = '',
description = '',
host = '',
address = '',
remote_agent = True,
share_count = 56,
access_count = 56,
has_activity = True,
limited = True,
created_at = 56,
updated_at = 56, )
]
)
else:
return EnvironmentsList(
)
"""
def testEnvironmentsList(self):
"""Test EnvironmentsList"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()
+6
View File
@@ -86,6 +86,12 @@ class TestMetadataApi(unittest.TestCase):
"""
pass
def test_list_environments(self) -> None:
"""Test case for list_environments
"""
pass
def test_list_memberships(self) -> None:
"""Test case for list_memberships
+4
View File
@@ -59,6 +59,8 @@ __all__ = [
"EnrollRequest",
"Environment",
"EnvironmentAndResources",
"EnvironmentSummary",
"EnvironmentsList",
"Frontend",
"GetSparklines200Response",
"GetSparklinesRequest",
@@ -162,6 +164,8 @@ from zrok_api.models.enroll200_response import Enroll200Response as Enroll200Res
from zrok_api.models.enroll_request import EnrollRequest as EnrollRequest
from zrok_api.models.environment import Environment as Environment
from zrok_api.models.environment_and_resources import EnvironmentAndResources as EnvironmentAndResources
from zrok_api.models.environment_summary import EnvironmentSummary as EnvironmentSummary
from zrok_api.models.environments_list import EnvironmentsList as EnvironmentsList
from zrok_api.models.frontend import Frontend as Frontend
from zrok_api.models.get_sparklines200_response import GetSparklines200Response as GetSparklines200Response
from zrok_api.models.get_sparklines_request import GetSparklinesRequest as GetSparklinesRequest
+493 -1
View File
@@ -16,12 +16,14 @@ from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
from typing import Any, Dict, List, Optional, Tuple, Union
from typing_extensions import Annotated
from pydantic import StrictInt, StrictStr
from pydantic import Field, StrictBool, StrictInt, StrictStr
from typing import List, Optional
from typing_extensions import Annotated
from zrok_api.models.client_version_check_request import ClientVersionCheckRequest
from zrok_api.models.configuration import Configuration
from zrok_api.models.environment import Environment
from zrok_api.models.environment_and_resources import EnvironmentAndResources
from zrok_api.models.environments_list import EnvironmentsList
from zrok_api.models.frontend import Frontend
from zrok_api.models.get_sparklines200_response import GetSparklines200Response
from zrok_api.models.get_sparklines_request import GetSparklinesRequest
@@ -2723,6 +2725,496 @@ class MetadataApi:
@validate_call
def list_environments(
self,
description: Annotated[Optional[StrictStr], Field(description="filter by description (case-insensitive substring match)")] = None,
host: Annotated[Optional[StrictStr], Field(description="filter by host (case-insensitive substring match)")] = None,
address: Annotated[Optional[StrictStr], Field(description="filter by address (exact match)")] = None,
remote_agent: Annotated[Optional[StrictBool], Field(description="filter by whether agent is enrolled")] = None,
has_shares: Annotated[Optional[StrictBool], Field(description="filter by whether environment has active shares")] = None,
has_accesses: Annotated[Optional[StrictBool], Field(description="filter by whether environment has active accesses")] = None,
has_activity: Annotated[Optional[StrictBool], Field(description="filter by whether environment has metrics within activityDuration timeframe")] = None,
share_count: Annotated[Optional[StrictStr], Field(description="filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")")] = None,
access_count: Annotated[Optional[StrictStr], Field(description="filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")")] = None,
created_after: Annotated[Optional[StrictStr], Field(description="filter by created date (RFC3339 datetime, inclusive)")] = None,
created_before: Annotated[Optional[StrictStr], Field(description="filter by created date (RFC3339 datetime, inclusive)")] = None,
updated_after: Annotated[Optional[StrictStr], Field(description="filter by updated date (RFC3339 datetime, inclusive)")] = None,
updated_before: Annotated[Optional[StrictStr], Field(description="filter by updated date (RFC3339 datetime, inclusive)")] = None,
activity_duration: Annotated[Optional[StrictStr], Field(description="duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
Tuple[
Annotated[StrictFloat, Field(gt=0)],
Annotated[StrictFloat, Field(gt=0)]
]
] = None,
_request_auth: Optional[Dict[StrictStr, Any]] = None,
_content_type: Optional[StrictStr] = None,
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> EnvironmentsList:
"""list_environments
:param description: filter by description (case-insensitive substring match)
:type description: str
:param host: filter by host (case-insensitive substring match)
:type host: str
:param address: filter by address (exact match)
:type address: str
:param remote_agent: filter by whether agent is enrolled
:type remote_agent: bool
:param has_shares: filter by whether environment has active shares
:type has_shares: bool
:param has_accesses: filter by whether environment has active accesses
:type has_accesses: bool
:param has_activity: filter by whether environment has metrics within activityDuration timeframe
:type has_activity: bool
:param share_count: filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")
:type share_count: str
:param access_count: filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")
:type access_count: str
:param created_after: filter by created date (RFC3339 datetime, inclusive)
:type created_after: str
:param created_before: filter by created date (RFC3339 datetime, inclusive)
:type created_before: str
:param updated_after: filter by updated date (RFC3339 datetime, inclusive)
:type updated_after: str
:param updated_before: filter by updated date (RFC3339 datetime, inclusive)
:type updated_before: str
:param activity_duration: duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)
:type activity_duration: str
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:type _request_timeout: int, tuple(int, int), optional
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the
authentication in the spec for a single request.
:type _request_auth: dict, optional
:param _content_type: force content-type for the request.
:type _content_type: str, Optional
:param _headers: set to override the headers for a single
request; this effectively ignores the headers
in the spec for a single request.
:type _headers: dict, optional
:param _host_index: set to override the host_index for a single
request; this effectively ignores the host_index
in the spec for a single request.
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
_param = self._list_environments_serialize(
description=description,
host=host,
address=address,
remote_agent=remote_agent,
has_shares=has_shares,
has_accesses=has_accesses,
has_activity=has_activity,
share_count=share_count,
access_count=access_count,
created_after=created_after,
created_before=created_before,
updated_after=updated_after,
updated_before=updated_before,
activity_duration=activity_duration,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
_host_index=_host_index
)
_response_types_map: Dict[str, Optional[str]] = {
'200': "EnvironmentsList",
'400': "str",
'401': None,
'500': "str",
}
response_data = self.api_client.call_api(
*_param,
_request_timeout=_request_timeout
)
response_data.read()
return self.api_client.response_deserialize(
response_data=response_data,
response_types_map=_response_types_map,
).data
@validate_call
def list_environments_with_http_info(
self,
description: Annotated[Optional[StrictStr], Field(description="filter by description (case-insensitive substring match)")] = None,
host: Annotated[Optional[StrictStr], Field(description="filter by host (case-insensitive substring match)")] = None,
address: Annotated[Optional[StrictStr], Field(description="filter by address (exact match)")] = None,
remote_agent: Annotated[Optional[StrictBool], Field(description="filter by whether agent is enrolled")] = None,
has_shares: Annotated[Optional[StrictBool], Field(description="filter by whether environment has active shares")] = None,
has_accesses: Annotated[Optional[StrictBool], Field(description="filter by whether environment has active accesses")] = None,
has_activity: Annotated[Optional[StrictBool], Field(description="filter by whether environment has metrics within activityDuration timeframe")] = None,
share_count: Annotated[Optional[StrictStr], Field(description="filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")")] = None,
access_count: Annotated[Optional[StrictStr], Field(description="filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")")] = None,
created_after: Annotated[Optional[StrictStr], Field(description="filter by created date (RFC3339 datetime, inclusive)")] = None,
created_before: Annotated[Optional[StrictStr], Field(description="filter by created date (RFC3339 datetime, inclusive)")] = None,
updated_after: Annotated[Optional[StrictStr], Field(description="filter by updated date (RFC3339 datetime, inclusive)")] = None,
updated_before: Annotated[Optional[StrictStr], Field(description="filter by updated date (RFC3339 datetime, inclusive)")] = None,
activity_duration: Annotated[Optional[StrictStr], Field(description="duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
Tuple[
Annotated[StrictFloat, Field(gt=0)],
Annotated[StrictFloat, Field(gt=0)]
]
] = None,
_request_auth: Optional[Dict[StrictStr, Any]] = None,
_content_type: Optional[StrictStr] = None,
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> ApiResponse[EnvironmentsList]:
"""list_environments
:param description: filter by description (case-insensitive substring match)
:type description: str
:param host: filter by host (case-insensitive substring match)
:type host: str
:param address: filter by address (exact match)
:type address: str
:param remote_agent: filter by whether agent is enrolled
:type remote_agent: bool
:param has_shares: filter by whether environment has active shares
:type has_shares: bool
:param has_accesses: filter by whether environment has active accesses
:type has_accesses: bool
:param has_activity: filter by whether environment has metrics within activityDuration timeframe
:type has_activity: bool
:param share_count: filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")
:type share_count: str
:param access_count: filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")
:type access_count: str
:param created_after: filter by created date (RFC3339 datetime, inclusive)
:type created_after: str
:param created_before: filter by created date (RFC3339 datetime, inclusive)
:type created_before: str
:param updated_after: filter by updated date (RFC3339 datetime, inclusive)
:type updated_after: str
:param updated_before: filter by updated date (RFC3339 datetime, inclusive)
:type updated_before: str
:param activity_duration: duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)
:type activity_duration: str
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:type _request_timeout: int, tuple(int, int), optional
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the
authentication in the spec for a single request.
:type _request_auth: dict, optional
:param _content_type: force content-type for the request.
:type _content_type: str, Optional
:param _headers: set to override the headers for a single
request; this effectively ignores the headers
in the spec for a single request.
:type _headers: dict, optional
:param _host_index: set to override the host_index for a single
request; this effectively ignores the host_index
in the spec for a single request.
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
_param = self._list_environments_serialize(
description=description,
host=host,
address=address,
remote_agent=remote_agent,
has_shares=has_shares,
has_accesses=has_accesses,
has_activity=has_activity,
share_count=share_count,
access_count=access_count,
created_after=created_after,
created_before=created_before,
updated_after=updated_after,
updated_before=updated_before,
activity_duration=activity_duration,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
_host_index=_host_index
)
_response_types_map: Dict[str, Optional[str]] = {
'200': "EnvironmentsList",
'400': "str",
'401': None,
'500': "str",
}
response_data = self.api_client.call_api(
*_param,
_request_timeout=_request_timeout
)
response_data.read()
return self.api_client.response_deserialize(
response_data=response_data,
response_types_map=_response_types_map,
)
@validate_call
def list_environments_without_preload_content(
self,
description: Annotated[Optional[StrictStr], Field(description="filter by description (case-insensitive substring match)")] = None,
host: Annotated[Optional[StrictStr], Field(description="filter by host (case-insensitive substring match)")] = None,
address: Annotated[Optional[StrictStr], Field(description="filter by address (exact match)")] = None,
remote_agent: Annotated[Optional[StrictBool], Field(description="filter by whether agent is enrolled")] = None,
has_shares: Annotated[Optional[StrictBool], Field(description="filter by whether environment has active shares")] = None,
has_accesses: Annotated[Optional[StrictBool], Field(description="filter by whether environment has active accesses")] = None,
has_activity: Annotated[Optional[StrictBool], Field(description="filter by whether environment has metrics within activityDuration timeframe")] = None,
share_count: Annotated[Optional[StrictStr], Field(description="filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")")] = None,
access_count: Annotated[Optional[StrictStr], Field(description="filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")")] = None,
created_after: Annotated[Optional[StrictStr], Field(description="filter by created date (RFC3339 datetime, inclusive)")] = None,
created_before: Annotated[Optional[StrictStr], Field(description="filter by created date (RFC3339 datetime, inclusive)")] = None,
updated_after: Annotated[Optional[StrictStr], Field(description="filter by updated date (RFC3339 datetime, inclusive)")] = None,
updated_before: Annotated[Optional[StrictStr], Field(description="filter by updated date (RFC3339 datetime, inclusive)")] = None,
activity_duration: Annotated[Optional[StrictStr], Field(description="duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
Tuple[
Annotated[StrictFloat, Field(gt=0)],
Annotated[StrictFloat, Field(gt=0)]
]
] = None,
_request_auth: Optional[Dict[StrictStr, Any]] = None,
_content_type: Optional[StrictStr] = None,
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> RESTResponseType:
"""list_environments
:param description: filter by description (case-insensitive substring match)
:type description: str
:param host: filter by host (case-insensitive substring match)
:type host: str
:param address: filter by address (exact match)
:type address: str
:param remote_agent: filter by whether agent is enrolled
:type remote_agent: bool
:param has_shares: filter by whether environment has active shares
:type has_shares: bool
:param has_accesses: filter by whether environment has active accesses
:type has_accesses: bool
:param has_activity: filter by whether environment has metrics within activityDuration timeframe
:type has_activity: bool
:param share_count: filter by share count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")
:type share_count: str
:param access_count: filter by access count with operator (e.g., \">0\", \">=5\", \"=0\", \"<10\", \"<=3\")
:type access_count: str
:param created_after: filter by created date (RFC3339 datetime, inclusive)
:type created_after: str
:param created_before: filter by created date (RFC3339 datetime, inclusive)
:type created_before: str
:param updated_after: filter by updated date (RFC3339 datetime, inclusive)
:type updated_after: str
:param updated_before: filter by updated date (RFC3339 datetime, inclusive)
:type updated_before: str
:param activity_duration: duration for hasActivity filter (e.g., \"24h\", \"7d\", \"30d\"). default \"24h\", maximum \"30d\" (720h)
:type activity_duration: str
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:type _request_timeout: int, tuple(int, int), optional
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the
authentication in the spec for a single request.
:type _request_auth: dict, optional
:param _content_type: force content-type for the request.
:type _content_type: str, Optional
:param _headers: set to override the headers for a single
request; this effectively ignores the headers
in the spec for a single request.
:type _headers: dict, optional
:param _host_index: set to override the host_index for a single
request; this effectively ignores the host_index
in the spec for a single request.
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
_param = self._list_environments_serialize(
description=description,
host=host,
address=address,
remote_agent=remote_agent,
has_shares=has_shares,
has_accesses=has_accesses,
has_activity=has_activity,
share_count=share_count,
access_count=access_count,
created_after=created_after,
created_before=created_before,
updated_after=updated_after,
updated_before=updated_before,
activity_duration=activity_duration,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
_host_index=_host_index
)
_response_types_map: Dict[str, Optional[str]] = {
'200': "EnvironmentsList",
'400': "str",
'401': None,
'500': "str",
}
response_data = self.api_client.call_api(
*_param,
_request_timeout=_request_timeout
)
return response_data.response
def _list_environments_serialize(
self,
description,
host,
address,
remote_agent,
has_shares,
has_accesses,
has_activity,
share_count,
access_count,
created_after,
created_before,
updated_after,
updated_before,
activity_duration,
_request_auth,
_content_type,
_headers,
_host_index,
) -> RequestSerialized:
_host = None
_collection_formats: Dict[str, str] = {
}
_path_params: Dict[str, str] = {}
_query_params: List[Tuple[str, str]] = []
_header_params: Dict[str, Optional[str]] = _headers or {}
_form_params: List[Tuple[str, str]] = []
_files: Dict[
str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
] = {}
_body_params: Optional[bytes] = None
# process the path parameters
# process the query parameters
if description is not None:
_query_params.append(('description', description))
if host is not None:
_query_params.append(('host', host))
if address is not None:
_query_params.append(('address', address))
if remote_agent is not None:
_query_params.append(('remoteAgent', remote_agent))
if has_shares is not None:
_query_params.append(('hasShares', has_shares))
if has_accesses is not None:
_query_params.append(('hasAccesses', has_accesses))
if has_activity is not None:
_query_params.append(('hasActivity', has_activity))
if share_count is not None:
_query_params.append(('shareCount', share_count))
if access_count is not None:
_query_params.append(('accessCount', access_count))
if created_after is not None:
_query_params.append(('createdAfter', created_after))
if created_before is not None:
_query_params.append(('createdBefore', created_before))
if updated_after is not None:
_query_params.append(('updatedAfter', updated_after))
if updated_before is not None:
_query_params.append(('updatedBefore', updated_before))
if activity_duration is not None:
_query_params.append(('activityDuration', activity_duration))
# process the header parameters
# process the form parameters
# process the body parameter
# set the HTTP header `Accept`
if 'Accept' not in _header_params:
_header_params['Accept'] = self.api_client.select_header_accept(
[
'application/zrok.v1+json'
]
)
# authentication setting
_auth_settings: List[str] = [
'key'
]
return self.api_client.param_serialize(
method='GET',
resource_path='/environments',
path_params=_path_params,
query_params=_query_params,
header_params=_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
auth_settings=_auth_settings,
collection_formats=_collection_formats,
_host=_host,
_request_auth=_request_auth
)
@validate_call
def list_memberships(
self,
@@ -40,6 +40,8 @@ from zrok_api.models.enroll200_response import Enroll200Response
from zrok_api.models.enroll_request import EnrollRequest
from zrok_api.models.environment import Environment
from zrok_api.models.environment_and_resources import EnvironmentAndResources
from zrok_api.models.environment_summary import EnvironmentSummary
from zrok_api.models.environments_list import EnvironmentsList
from zrok_api.models.frontend import Frontend
from zrok_api.models.get_sparklines200_response import GetSparklines200Response
from zrok_api.models.get_sparklines_request import GetSparklinesRequest
@@ -0,0 +1,107 @@
# coding: utf-8
"""
zrok
zrok client access
The version of the OpenAPI document: 2.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self
class EnvironmentSummary(BaseModel):
"""
EnvironmentSummary
""" # noqa: E501
env_zid: Optional[StrictStr] = Field(default=None, alias="envZId")
description: Optional[StrictStr] = None
host: Optional[StrictStr] = None
address: Optional[StrictStr] = None
remote_agent: Optional[StrictBool] = Field(default=None, alias="remoteAgent")
share_count: Optional[StrictInt] = Field(default=None, alias="shareCount")
access_count: Optional[StrictInt] = Field(default=None, alias="accessCount")
has_activity: Optional[StrictBool] = Field(default=None, alias="hasActivity")
limited: Optional[StrictBool] = None
created_at: Optional[StrictInt] = Field(default=None, alias="createdAt")
updated_at: Optional[StrictInt] = Field(default=None, alias="updatedAt")
__properties: ClassVar[List[str]] = ["envZId", "description", "host", "address", "remoteAgent", "shareCount", "accessCount", "hasActivity", "limited", "createdAt", "updatedAt"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of EnvironmentSummary from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of EnvironmentSummary from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"envZId": obj.get("envZId"),
"description": obj.get("description"),
"host": obj.get("host"),
"address": obj.get("address"),
"remoteAgent": obj.get("remoteAgent"),
"shareCount": obj.get("shareCount"),
"accessCount": obj.get("accessCount"),
"hasActivity": obj.get("hasActivity"),
"limited": obj.get("limited"),
"createdAt": obj.get("createdAt"),
"updatedAt": obj.get("updatedAt")
})
return _obj
@@ -0,0 +1,95 @@
# coding: utf-8
"""
zrok
zrok client access
The version of the OpenAPI document: 2.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, ConfigDict
from typing import Any, ClassVar, Dict, List, Optional
from zrok_api.models.environment_summary import EnvironmentSummary
from typing import Optional, Set
from typing_extensions import Self
class EnvironmentsList(BaseModel):
"""
EnvironmentsList
""" # noqa: E501
environments: Optional[List[EnvironmentSummary]] = None
__properties: ClassVar[List[str]] = ["environments"]
model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> Optional[Self]:
"""Create an instance of EnvironmentsList from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self) -> Dict[str, Any]:
"""Return the dictionary representation of the model using alias.
This has the following differences from calling pydantic's
`self.model_dump(by_alias=True)`:
* `None` is only added to the output dict for nullable fields that
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
_dict = self.model_dump(
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of each item in environments (list)
_items = []
if self.environments:
for _item_environments in self.environments:
if _item_environments:
_items.append(_item_environments.to_dict())
_dict['environments'] = _items
return _dict
@classmethod
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"""Create an instance of EnvironmentsList from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return cls.model_validate(obj)
_obj = cls.model_validate({
"environments": [EnvironmentSummary.from_dict(_item) for _item in obj["environments"]] if obj.get("environments") is not None else None
})
return _obj
+34
View File
@@ -59,6 +59,40 @@ environmentAndResources:
shares:
$ref: "#/definitions/shares"
environmentSummary:
type: object
properties:
envZId:
type: string
description:
type: string
host:
type: string
address:
type: string
remoteAgent:
type: boolean
shareCount:
type: integer
accessCount:
type: integer
hasActivity:
type: boolean
limited:
type: boolean
createdAt:
type: integer
updatedAt:
type: integer
environmentsList:
type: object
properties:
environments:
type: array
items:
$ref: "#/definitions/environmentSummary"
errorMessage:
type: string
+80
View File
@@ -68,6 +68,86 @@
500:
description: internal server error
/environments:
get:
tags:
- metadata
security:
- key: []
operationId: listEnvironments
parameters:
- name: description
in: query
type: string
description: filter by description (case-insensitive substring match)
- name: host
in: query
type: string
description: filter by host (case-insensitive substring match)
- name: address
in: query
type: string
description: filter by address (exact match)
- name: remoteAgent
in: query
type: boolean
description: filter by whether agent is enrolled
- name: hasShares
in: query
type: boolean
description: filter by whether environment has active shares
- name: hasAccesses
in: query
type: boolean
description: filter by whether environment has active accesses
- name: hasActivity
in: query
type: boolean
description: filter by whether environment has metrics within activityDuration timeframe
- name: shareCount
in: query
type: string
description: filter by share count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
- name: accessCount
in: query
type: string
description: filter by access count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
- name: createdAfter
in: query
type: string
description: filter by created date (RFC3339 datetime, inclusive)
- name: createdBefore
in: query
type: string
description: filter by created date (RFC3339 datetime, inclusive)
- name: updatedAfter
in: query
type: string
description: filter by updated date (RFC3339 datetime, inclusive)
- name: updatedBefore
in: query
type: string
description: filter by updated date (RFC3339 datetime, inclusive)
- name: activityDuration
in: query
type: string
description: duration for hasActivity filter (e.g., "24h", "7d", "30d"). default "24h", maximum "30d" (720h)
responses:
200:
description: list of environments
schema:
$ref: "#/definitions/environmentsList"
400:
description: bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator)
schema:
$ref: "#/definitions/errorMessage"
401:
description: unauthorized
500:
description: internal server error
schema:
$ref: "#/definitions/errorMessage"
/detail/frontend/{frontendId}:
get:
tags:
+114
View File
@@ -1517,6 +1517,86 @@ paths:
500:
description: internal server error
/environments:
get:
tags:
- metadata
security:
- key: []
operationId: listEnvironments
parameters:
- name: description
in: query
type: string
description: filter by description (case-insensitive substring match)
- name: host
in: query
type: string
description: filter by host (case-insensitive substring match)
- name: address
in: query
type: string
description: filter by address (exact match)
- name: remoteAgent
in: query
type: boolean
description: filter by whether agent is enrolled
- name: hasShares
in: query
type: boolean
description: filter by whether environment has active shares
- name: hasAccesses
in: query
type: boolean
description: filter by whether environment has active accesses
- name: hasActivity
in: query
type: boolean
description: filter by whether environment has metrics within activityDuration timeframe
- name: shareCount
in: query
type: string
description: filter by share count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
- name: accessCount
in: query
type: string
description: filter by access count with operator (e.g., ">0", ">=5", "=0", "<10", "<=3")
- name: createdAfter
in: query
type: string
description: filter by created date (RFC3339 datetime, inclusive)
- name: createdBefore
in: query
type: string
description: filter by created date (RFC3339 datetime, inclusive)
- name: updatedAfter
in: query
type: string
description: filter by updated date (RFC3339 datetime, inclusive)
- name: updatedBefore
in: query
type: string
description: filter by updated date (RFC3339 datetime, inclusive)
- name: activityDuration
in: query
type: string
description: duration for hasActivity filter (e.g., "24h", "7d", "30d"). default "24h", maximum "30d" (720h)
responses:
200:
description: list of environments
schema:
$ref: "#/definitions/environmentsList"
400:
description: bad request (e.g., activityDuration exceeds 30d, invalid date format, invalid operator)
schema:
$ref: "#/definitions/errorMessage"
401:
description: unauthorized
500:
description: internal server error
schema:
$ref: "#/definitions/errorMessage"
/detail/frontend/{frontendId}:
get:
tags:
@@ -2202,6 +2282,40 @@ definitions:
shares:
$ref: "#/definitions/shares"
environmentSummary:
type: object
properties:
envZId:
type: string
description:
type: string
host:
type: string
address:
type: string
remoteAgent:
type: boolean
shareCount:
type: integer
accessCount:
type: integer
hasActivity:
type: boolean
limited:
type: boolean
createdAt:
type: integer
updatedAt:
type: integer
environmentsList:
type: object
properties:
environments:
type: array
items:
$ref: "#/definitions/environmentSummary"
errorMessage:
type: string
+2
View File
@@ -32,6 +32,8 @@ models/Enroll200Response.ts
models/EnrollRequest.ts
models/Environment.ts
models/EnvironmentAndResources.ts
models/EnvironmentSummary.ts
models/EnvironmentsList.ts
models/Frontend.ts
models/GetSparklines200Response.ts
models/GetSparklinesRequest.ts
+107
View File
@@ -18,6 +18,7 @@ import type {
ClientVersionCheckRequest,
Environment,
EnvironmentAndResources,
EnvironmentsList,
Frontend,
GetSparklines200Response,
GetSparklinesRequest,
@@ -36,6 +37,8 @@ import {
EnvironmentToJSON,
EnvironmentAndResourcesFromJSON,
EnvironmentAndResourcesToJSON,
EnvironmentsListFromJSON,
EnvironmentsListToJSON,
FrontendFromJSON,
FrontendToJSON,
GetSparklines200ResponseFromJSON,
@@ -92,6 +95,23 @@ export interface GetSparklinesOperationRequest {
body?: GetSparklinesRequest;
}
export interface ListEnvironmentsRequest {
description?: string;
host?: string;
address?: string;
remoteAgent?: boolean;
hasShares?: boolean;
hasAccesses?: boolean;
hasActivity?: boolean;
shareCount?: string;
accessCount?: string;
createdAfter?: string;
createdBefore?: string;
updatedAfter?: string;
updatedBefore?: string;
activityDuration?: string;
}
export interface ListOrgMembersRequest {
organizationToken: string;
}
@@ -465,6 +485,93 @@ export class MetadataApi extends runtime.BaseAPI {
return await response.value();
}
/**
*/
async listEnvironmentsRaw(requestParameters: ListEnvironmentsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<EnvironmentsList>> {
const queryParameters: any = {};
if (requestParameters['description'] != null) {
queryParameters['description'] = requestParameters['description'];
}
if (requestParameters['host'] != null) {
queryParameters['host'] = requestParameters['host'];
}
if (requestParameters['address'] != null) {
queryParameters['address'] = requestParameters['address'];
}
if (requestParameters['remoteAgent'] != null) {
queryParameters['remoteAgent'] = requestParameters['remoteAgent'];
}
if (requestParameters['hasShares'] != null) {
queryParameters['hasShares'] = requestParameters['hasShares'];
}
if (requestParameters['hasAccesses'] != null) {
queryParameters['hasAccesses'] = requestParameters['hasAccesses'];
}
if (requestParameters['hasActivity'] != null) {
queryParameters['hasActivity'] = requestParameters['hasActivity'];
}
if (requestParameters['shareCount'] != null) {
queryParameters['shareCount'] = requestParameters['shareCount'];
}
if (requestParameters['accessCount'] != null) {
queryParameters['accessCount'] = requestParameters['accessCount'];
}
if (requestParameters['createdAfter'] != null) {
queryParameters['createdAfter'] = requestParameters['createdAfter'];
}
if (requestParameters['createdBefore'] != null) {
queryParameters['createdBefore'] = requestParameters['createdBefore'];
}
if (requestParameters['updatedAfter'] != null) {
queryParameters['updatedAfter'] = requestParameters['updatedAfter'];
}
if (requestParameters['updatedBefore'] != null) {
queryParameters['updatedBefore'] = requestParameters['updatedBefore'];
}
if (requestParameters['activityDuration'] != null) {
queryParameters['activityDuration'] = requestParameters['activityDuration'];
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.apiKey) {
headerParameters["x-token"] = await this.configuration.apiKey("x-token"); // key authentication
}
let urlPath = `/environments`;
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => EnvironmentsListFromJSON(jsonValue));
}
/**
*/
async listEnvironments(requestParameters: ListEnvironmentsRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<EnvironmentsList> {
const response = await this.listEnvironmentsRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async listMembershipsRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ListMemberships200Response>> {
+145
View File
@@ -0,0 +1,145 @@
/* tslint:disable */
/* eslint-disable */
/**
* zrok
* zrok client access
*
* The version of the OpenAPI document: 2.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface EnvironmentSummary
*/
export interface EnvironmentSummary {
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
envZId?: string;
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
description?: string;
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
host?: string;
/**
*
* @type {string}
* @memberof EnvironmentSummary
*/
address?: string;
/**
*
* @type {boolean}
* @memberof EnvironmentSummary
*/
remoteAgent?: boolean;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
shareCount?: number;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
accessCount?: number;
/**
*
* @type {boolean}
* @memberof EnvironmentSummary
*/
hasActivity?: boolean;
/**
*
* @type {boolean}
* @memberof EnvironmentSummary
*/
limited?: boolean;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
createdAt?: number;
/**
*
* @type {number}
* @memberof EnvironmentSummary
*/
updatedAt?: number;
}
/**
* Check if a given object implements the EnvironmentSummary interface.
*/
export function instanceOfEnvironmentSummary(value: object): value is EnvironmentSummary {
return true;
}
export function EnvironmentSummaryFromJSON(json: any): EnvironmentSummary {
return EnvironmentSummaryFromJSONTyped(json, false);
}
export function EnvironmentSummaryFromJSONTyped(json: any, ignoreDiscriminator: boolean): EnvironmentSummary {
if (json == null) {
return json;
}
return {
'envZId': json['envZId'] == null ? undefined : json['envZId'],
'description': json['description'] == null ? undefined : json['description'],
'host': json['host'] == null ? undefined : json['host'],
'address': json['address'] == null ? undefined : json['address'],
'remoteAgent': json['remoteAgent'] == null ? undefined : json['remoteAgent'],
'shareCount': json['shareCount'] == null ? undefined : json['shareCount'],
'accessCount': json['accessCount'] == null ? undefined : json['accessCount'],
'hasActivity': json['hasActivity'] == null ? undefined : json['hasActivity'],
'limited': json['limited'] == null ? undefined : json['limited'],
'createdAt': json['createdAt'] == null ? undefined : json['createdAt'],
'updatedAt': json['updatedAt'] == null ? undefined : json['updatedAt'],
};
}
export function EnvironmentSummaryToJSON(json: any): EnvironmentSummary {
return EnvironmentSummaryToJSONTyped(json, false);
}
export function EnvironmentSummaryToJSONTyped(value?: EnvironmentSummary | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'envZId': value['envZId'],
'description': value['description'],
'host': value['host'],
'address': value['address'],
'remoteAgent': value['remoteAgent'],
'shareCount': value['shareCount'],
'accessCount': value['accessCount'],
'hasActivity': value['hasActivity'],
'limited': value['limited'],
'createdAt': value['createdAt'],
'updatedAt': value['updatedAt'],
};
}
+73
View File
@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* zrok
* zrok client access
*
* The version of the OpenAPI document: 2.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { EnvironmentSummary } from './EnvironmentSummary';
import {
EnvironmentSummaryFromJSON,
EnvironmentSummaryFromJSONTyped,
EnvironmentSummaryToJSON,
EnvironmentSummaryToJSONTyped,
} from './EnvironmentSummary';
/**
*
* @export
* @interface EnvironmentsList
*/
export interface EnvironmentsList {
/**
*
* @type {Array<EnvironmentSummary>}
* @memberof EnvironmentsList
*/
environments?: Array<EnvironmentSummary>;
}
/**
* Check if a given object implements the EnvironmentsList interface.
*/
export function instanceOfEnvironmentsList(value: object): value is EnvironmentsList {
return true;
}
export function EnvironmentsListFromJSON(json: any): EnvironmentsList {
return EnvironmentsListFromJSONTyped(json, false);
}
export function EnvironmentsListFromJSONTyped(json: any, ignoreDiscriminator: boolean): EnvironmentsList {
if (json == null) {
return json;
}
return {
'environments': json['environments'] == null ? undefined : ((json['environments'] as Array<any>).map(EnvironmentSummaryFromJSON)),
};
}
export function EnvironmentsListToJSON(json: any): EnvironmentsList {
return EnvironmentsListToJSONTyped(json, false);
}
export function EnvironmentsListToJSONTyped(value?: EnvironmentsList | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'environments': value['environments'] == null ? undefined : ((value['environments'] as Array<any>).map(EnvironmentSummaryToJSON)),
};
}
+2
View File
@@ -25,6 +25,8 @@ export * from './Enroll200Response';
export * from './EnrollRequest';
export * from './Environment';
export * from './EnvironmentAndResources';
export * from './EnvironmentSummary';
export * from './EnvironmentsList';
export * from './Frontend';
export * from './GetSparklines200Response';
export * from './GetSparklinesRequest';
+45
View File
@@ -0,0 +1,45 @@
package util
import (
"fmt"
"regexp"
"strconv"
"time"
)
// ParseDuration extends time.ParseDuration to support 'd' (days) as a unit.
// it converts days to hours (1d = 24h) before parsing.
// examples: "24h", "7d", "2d6h30m", "1d12h"
func ParseDuration(s string) (time.Duration, error) {
if s == "" {
return 0, fmt.Errorf("invalid duration: empty string")
}
// check for invalid patterns that might contain 'd' but shouldn't be processed
// this catches cases like "-1d", "1.5d", ".5d" etc.
invalidPattern := regexp.MustCompile(`[^\d\s](\d+)d|(\d*\.\d+)d`)
if invalidPattern.MatchString(s) {
// let time.ParseDuration handle these and return its error
return time.ParseDuration(s)
}
// regex pattern to match digits followed by 'd' at word boundaries
dayPattern := regexp.MustCompile(`(\d+)d`)
// find all day values and convert to hours
converted := dayPattern.ReplaceAllStringFunc(s, func(match string) string {
// extract the numeric part
numStr := match[:len(match)-1] // remove the 'd'
days, err := strconv.Atoi(numStr)
if err != nil {
// this shouldn't happen due to regex, but handle gracefully
return match
}
// convert days to hours
hours := days * 24
return fmt.Sprintf("%dh", hours)
})
// pass to standard time.ParseDuration
return time.ParseDuration(converted)
}
+58
View File
@@ -0,0 +1,58 @@
package util
import (
"testing"
"time"
)
func TestParseDuration(t *testing.T) {
tests := []struct {
name string
input string
expected time.Duration
wantErr bool
}{
// standard formats (pass-through)
{"standard hours", "24h", 24 * time.Hour, false},
{"standard minutes", "90m", 90 * time.Minute, false},
{"standard combined", "1h30m", 90 * time.Minute, false},
{"standard seconds", "45s", 45 * time.Second, false},
// days only
{"one day", "1d", 24 * time.Hour, false},
{"seven days", "7d", 168 * time.Hour, false},
{"thirty days", "30d", 720 * time.Hour, false},
// combined formats
{"days and hours", "1d12h", 36 * time.Hour, false},
{"days hours minutes", "2d6h30m", 54*time.Hour + 30*time.Minute, false},
{"complex", "3d2h15m30s", 74*time.Hour + 15*time.Minute + 30*time.Second, false},
// edge cases
{"zero days", "0d", 0, false},
{"empty string", "", 0, true},
{"invalid format", "invalid", 0, true},
{"days without number", "d", 0, true},
{"negative days", "-1d", 0, true}, // '-' not in \d+ pattern, passes through as invalid
{"decimal days", "1.5d", 0, true}, // '.' not in \d+ pattern, passes through as invalid
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := ParseDuration(tt.input)
if tt.wantErr {
if err == nil {
t.Errorf("ParseDuration(%q) expected error but got none", tt.input)
}
return
}
if err != nil {
t.Errorf("ParseDuration(%q) unexpected error: %v", tt.input, err)
return
}
if result != tt.expected {
t.Errorf("ParseDuration(%q) = %v, expected %v", tt.input, result, tt.expected)
}
})
}
}